diff --git a/spec/app/fold-suggester-spec.coffee b/spec/app/fold-suggester-spec.coffee new file mode 100644 index 000000000..5b68ac415 --- /dev/null +++ b/spec/app/fold-suggester-spec.coffee @@ -0,0 +1,16 @@ +FoldSuggester = require 'fold-suggester' +Buffer = require 'buffer' + +describe "FoldSuggester", -> + foldSuggester = null + + beforeEach -> + buffer = new Buffer(require.resolve 'fixtures/sample.js') + foldSuggester = new FoldSuggester(buffer) + + describe ".isBufferRowFoldable(bufferRow)", -> + it "returns true only when the buffer row starts a foldable region", -> + expect(foldSuggester.isBufferRowFoldable(0)).toBeTruthy() + expect(foldSuggester.isBufferRowFoldable(1)).toBeTruthy() + expect(foldSuggester.isBufferRowFoldable(2)).toBeFalsy() + expect(foldSuggester.isBufferRowFoldable(3)).toBeFalsy() diff --git a/spec/app/renderer-spec.coffee b/spec/app/renderer-spec.coffee index ef887fb6d..aef53f199 100644 --- a/spec/app/renderer-spec.coffee +++ b/spec/app/renderer-spec.coffee @@ -141,6 +141,21 @@ describe "Renderer", -> expect(event.newRange).toEqual([[0, 0], [18, 2]]) expect(event.lineNumbersChanged).toBeTruthy() + describe "fold markers", -> + it "sets 'foldable' to true for screen lines that start a foldable region", -> + expect(renderer.lineForRow(0).foldable).toBeTruthy() + expect(renderer.lineForRow(1).foldable).toBeTruthy() + expect(renderer.lineForRow(2).foldable).toBeFalsy() + expect(renderer.lineForRow(3).foldable).toBeFalsy() + + describe "when a foldable line is wrapped", -> + it "only marks the first screen line as foldable", -> + renderer.setMaxLineLength(20) + expect(renderer.lineForRow(0).foldable).toBeTruthy() + expect(renderer.lineForRow(1).foldable).toBeFalsy() + expect(renderer.lineForRow(2).foldable).toBeTruthy() + expect(renderer.lineForRow(3).foldable).toBeFalsy() + describe "folding", -> beforeEach -> buffer = new Buffer(require.resolve 'fixtures/two-hundred.txt') diff --git a/src/app/ace-fold-adaptor.coffee b/src/app/ace-fold-adaptor.coffee new file mode 100644 index 000000000..34b029d27 --- /dev/null +++ b/src/app/ace-fold-adaptor.coffee @@ -0,0 +1,6 @@ +module.exports = +class AceFoldAdaptor + constructor: (@buffer) -> + + getLine: (bufferRow) -> + @buffer.lineForRow(bufferRow) diff --git a/src/app/fold-suggester.coffee b/src/app/fold-suggester.coffee new file mode 100644 index 000000000..ce06320d4 --- /dev/null +++ b/src/app/fold-suggester.coffee @@ -0,0 +1,10 @@ +AceFoldAdaptor = require 'ace-fold-adaptor' + +module.exports = +class FoldSuggester + constructor: (@buffer) -> + @aceFoldMode = @buffer.getMode().foldingRules + @aceFoldAdaptor = new AceFoldAdaptor(@buffer) + + isBufferRowFoldable: (bufferRow) -> + @aceFoldMode.getFoldWidget(@aceFoldAdaptor, null, bufferRow) == "start" diff --git a/src/app/renderer.coffee b/src/app/renderer.coffee index a34dc0dd2..06aba78c8 100644 --- a/src/app/renderer.coffee +++ b/src/app/renderer.coffee @@ -1,5 +1,6 @@ _ = require 'underscore' Highlighter = require 'highlighter' +FoldSuggester = require 'fold-suggester' LineMap = require 'line-map' Point = require 'point' EventEmitter = require 'event-emitter' @@ -22,6 +23,7 @@ class Renderer constructor: (@buffer, options={}) -> @id = @constructor.idCounter++ @highlighter = new Highlighter(@buffer, options.tabText ? ' ') + @foldSuggester = new FoldSuggester(@buffer) @maxLineLength = options.maxLineLength ? Infinity @activeFolds = {} @foldsById = {} @@ -161,6 +163,7 @@ class Renderer startBufferColumn = 0 while currentBufferRow <= endBufferRow screenLine = @highlighter.lineForRow(currentBufferRow) + screenLine.foldable = @foldSuggester.isBufferRowFoldable(currentBufferRow) if fold = @largestFoldForBufferRow(currentBufferRow) screenLine = screenLine.copy() diff --git a/src/app/screen-line-fragment.coffee b/src/app/screen-line-fragment.coffee index 8dfdde1e2..3d47a7053 100644 --- a/src/app/screen-line-fragment.coffee +++ b/src/app/screen-line-fragment.coffee @@ -8,6 +8,7 @@ class ScreenLineFragment tokens: null screenDelta: null bufferDelta: null + foldable: null constructor: (@tokens, @text, screenDelta, bufferDelta, extraFields) -> @screenDelta = Point.fromObject(screenDelta) @@ -15,7 +16,7 @@ class ScreenLineFragment _.extend(this, extraFields) copy: -> - new ScreenLineFragment(@tokens, @text, @screenDelta, @bufferDelta, { @state }) + new ScreenLineFragment(@tokens, @text, @screenDelta, @bufferDelta, { @state, @foldable }) splitAt: (column) -> return [new ScreenLineFragment([], '', [0, 0], [0, 0]), this] if column == 0 @@ -36,7 +37,7 @@ class ScreenLineFragment [leftScreenDelta, rightScreenDelta] = @screenDelta.splitAt(column) [leftBufferDelta, rightBufferDelta] = @bufferDelta.splitAt(column) - leftFragment = new ScreenLineFragment(leftTokens, leftText, leftScreenDelta, leftBufferDelta, {@state}) + leftFragment = new ScreenLineFragment(leftTokens, leftText, leftScreenDelta, leftBufferDelta, {@state, @foldable}) rightFragment = new ScreenLineFragment(rightTokens, rightText, rightScreenDelta, rightBufferDelta, {@state}) [leftFragment, rightFragment]