From a1e8d25e55a2456be91c46ec0b785a8c9a288dce Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Fri, 3 Nov 2017 09:57:29 -0600 Subject: [PATCH] Autoscroll to cursor position after folding or unfolding There were several different fold/unfold code paths, so I decided to weave simple autoscroll assertions into the existing tests. --- spec/text-editor-spec.js | 26 +++++++++++++++++++++++--- src/text-editor.js | 28 ++++++++++++++++++++++------ 2 files changed, 45 insertions(+), 9 deletions(-) diff --git a/spec/text-editor-spec.js b/spec/text-editor-spec.js index 382d020d4..84eea43ef 100644 --- a/spec/text-editor-spec.js +++ b/spec/text-editor-spec.js @@ -115,12 +115,12 @@ describe('TextEditor', () => { editor.update({showCursorOnSelection: false}) editor.setSelectedBufferRange([[1, 2], [3, 4]]) editor.addSelectionForBufferRange([[5, 6], [7, 8]], {reversed: true}) + editor.foldBufferRow(4) + expect(editor.isFoldedAtBufferRow(4)).toBeTruthy() editor.setScrollTopRow(3) expect(editor.getScrollTopRow()).toBe(3) editor.setScrollLeftColumn(4) expect(editor.getScrollLeftColumn()).toBe(4) - editor.foldBufferRow(4) - expect(editor.isFoldedAtBufferRow(4)).toBeTruthy() const editor2 = editor.copy() const element2 = editor2.getElement() @@ -7002,15 +7002,19 @@ describe('TextEditor', () => { }) describe('.unfoldAll()', () => { - it('unfolds every folded line', async () => { + it('unfolds every folded line and autoscrolls', async () => { editor = await atom.workspace.open('sample.js', {autoIndent: false}) + const autoscrollEvents = [] + editor.onDidRequestAutoscroll(event => autoscrollEvents.push(event)) const initialScreenLineCount = editor.getScreenLineCount() editor.foldBufferRow(0) editor.foldBufferRow(1) expect(editor.getScreenLineCount()).toBeLessThan(initialScreenLineCount) + expect(autoscrollEvents.length).toBe(1) editor.unfoldAll() expect(editor.getScreenLineCount()).toBe(initialScreenLineCount) + expect(autoscrollEvents.length).toBe(2) }) it('unfolds every folded line with comments', async () => { @@ -7028,8 +7032,11 @@ describe('TextEditor', () => { describe('.foldAll()', () => { it('folds every foldable line', async () => { editor = await atom.workspace.open('sample.js', {autoIndent: false}) + const autoscrollEvents = [] + editor.onDidRequestAutoscroll(event => autoscrollEvents.push(event)) editor.foldAll() + expect(autoscrollEvents.length).toBe(1) const [fold1, fold2, fold3] = editor.unfoldAll() expect([fold1.start.row, fold1.end.row]).toEqual([0, 12]) expect([fold2.start.row, fold2.end.row]).toEqual([1, 9]) @@ -7060,7 +7067,11 @@ describe('TextEditor', () => { describe('when bufferRow can be folded', () => { it('creates a fold based on the syntactic region starting at the given row', () => { + const autoscrollEvents = [] + editor.onDidRequestAutoscroll(event => autoscrollEvents.push(event)) + editor.foldBufferRow(1) + expect(autoscrollEvents.length).toBe(1) const [fold] = editor.unfoldAll() expect([fold.start.row, fold.end.row]).toEqual([1, 9]) }) @@ -7107,10 +7118,14 @@ describe('TextEditor', () => { describe('.foldCurrentRow()', () => { it('creates a fold at the location of the last cursor', async () => { editor = await atom.workspace.open() + editor.setText('\nif (x) {\n y()\n}') editor.setCursorBufferPosition([1, 0]) expect(editor.getScreenLineCount()).toBe(4) + const autoscrollEvents = [] + editor.onDidRequestAutoscroll(event => autoscrollEvents.push(event)) editor.foldCurrentRow() + expect(autoscrollEvents.length).toBe(1) expect(editor.getScreenLineCount()).toBe(3) }) @@ -7127,21 +7142,26 @@ describe('TextEditor', () => { describe('.foldAllAtIndentLevel(indentLevel)', () => { it('folds blocks of text at the given indentation level', async () => { editor = await atom.workspace.open('sample.js', {autoIndent: false}) + const autoscrollEvents = [] + editor.onDidRequestAutoscroll(event => autoscrollEvents.push(event)) editor.foldAllAtIndentLevel(0) expect(editor.lineTextForScreenRow(0)).toBe(`var quicksort = function () {${editor.displayLayer.foldCharacter}`) expect(editor.getLastScreenRow()).toBe(0) + expect(autoscrollEvents.length).toBe(1) editor.foldAllAtIndentLevel(1) expect(editor.lineTextForScreenRow(0)).toBe('var quicksort = function () {') expect(editor.lineTextForScreenRow(1)).toBe(` var sort = function(items) {${editor.displayLayer.foldCharacter}`) expect(editor.getLastScreenRow()).toBe(4) + expect(autoscrollEvents.length).toBe(2) editor.foldAllAtIndentLevel(2) expect(editor.lineTextForScreenRow(0)).toBe('var quicksort = function () {') expect(editor.lineTextForScreenRow(1)).toBe(' var sort = function(items) {') expect(editor.lineTextForScreenRow(2)).toBe(' if (items.length <= 1) return items;') expect(editor.getLastScreenRow()).toBe(9) + expect(autoscrollEvents.length).toBe(3) }) it('folds every foldable range at a given indentLevel', async () => { diff --git a/src/text-editor.js b/src/text-editor.js index a0b9d19a0..8eee5c140 100644 --- a/src/text-editor.js +++ b/src/text-editor.js @@ -3750,13 +3750,19 @@ class TextEditor { foldCurrentRow () { const {row} = this.getCursorBufferPosition() const range = this.tokenizedBuffer.getFoldableRangeContainingPoint(Point(row, Infinity)) - if (range) return this.displayLayer.foldBufferRange(range) + if (range) { + const result = this.displayLayer.foldBufferRange(range) + this.scrollToCursorPosition() + return result + } } // Essential: Unfold the most recent cursor's row by one level. unfoldCurrentRow () { const {row} = this.getCursorBufferPosition() - return this.displayLayer.destroyFoldsContainingBufferPositions([Point(row, Infinity)], false) + const result = this.displayLayer.destroyFoldsContainingBufferPositions([Point(row, Infinity)], false) + this.scrollToCursorPosition() + return result } // Essential: Fold the given row in buffer coordinates based on its indentation @@ -3774,6 +3780,7 @@ class TextEditor { const existingFolds = this.displayLayer.foldsIntersectingBufferRange(Range(foldableRange.start, foldableRange.start)) if (existingFolds.length === 0) { this.displayLayer.foldBufferRange(foldableRange) + this.scrollToCursorPosition() } else { const firstExistingFoldRange = this.displayLayer.bufferRangeForFold(existingFolds[0]) if (firstExistingFoldRange.start.isLessThan(position)) { @@ -3791,7 +3798,9 @@ class TextEditor { // * `bufferRow` A {Number} unfoldBufferRow (bufferRow) { const position = Point(bufferRow, Infinity) - return this.displayLayer.destroyFoldsContainingBufferPositions([position]) + const result = this.displayLayer.destroyFoldsContainingBufferPositions([position]) + this.scrollToCursorPosition() + return result } // Extended: For each selection, fold the rows it intersects. @@ -3807,6 +3816,7 @@ class TextEditor { for (let range of this.tokenizedBuffer.getFoldableRanges(this.getTabLength())) { this.displayLayer.foldBufferRange(range) } + this.scrollToCursorPosition() } // Extended: Unfold all existing folds. @@ -3824,6 +3834,7 @@ class TextEditor { for (let range of this.tokenizedBuffer.getFoldableRangesAtIndentLevel(level, this.getTabLength())) { this.displayLayer.foldBufferRange(range) } + this.scrollToCursorPosition() } // Extended: Determine whether the given row in buffer coordinates is foldable. @@ -3851,11 +3862,14 @@ class TextEditor { // Extended: Fold the given buffer row if it isn't currently folded, and unfold // it otherwise. toggleFoldAtBufferRow (bufferRow) { + let result if (this.isFoldedAtBufferRow(bufferRow)) { - return this.unfoldBufferRow(bufferRow) + result = this.unfoldBufferRow(bufferRow) } else { - return this.foldBufferRow(bufferRow) + result = this.foldBufferRow(bufferRow) } + this.scrollToCursorPosition() + return result } // Extended: Determine whether the most recently added cursor's row is folded. @@ -3894,7 +3908,9 @@ class TextEditor { // // Returns the new {Fold}. foldBufferRowRange (startRow, endRow) { - return this.foldBufferRange(Range(Point(startRow, Infinity), Point(endRow, Infinity))) + const result = this.foldBufferRange(Range(Point(startRow, Infinity), Point(endRow, Infinity))) + this.scrollToCursorPosition() + return result } foldBufferRange (range) {