diff --git a/spec/text-editor-spec.coffee b/spec/text-editor-spec.coffee index cd3f06c96..7ee8d2ee8 100644 --- a/spec/text-editor-spec.coffee +++ b/spec/text-editor-spec.coffee @@ -1837,6 +1837,33 @@ describe "TextEditor", -> expect(editor.lineTextForBufferRow(2)).toBe " var pivot = items.shift(), current, left = [], right = [];" expect(editor.lineTextForBufferRow(3)).toBe " if (items.length <= 1) return items;" + describe "when the cursor is at the beginning of a fold", -> + it "moves the line to the following row without breaking the fold", -> + expect(editor.lineTextForBufferRow(4)).toBe " while(items.length > 0) {" + + editor.createFold(4, 7) + editor.setSelectedBufferRange([[4, 2], [4, 9]], preserveFolds: true) + expect(editor.getSelectedBufferRange()).toEqual [[4, 2], [4, 9]] + + expect(editor.isFoldedAtBufferRow(4)).toBeTruthy() + expect(editor.isFoldedAtBufferRow(5)).toBeTruthy() + expect(editor.isFoldedAtBufferRow(6)).toBeTruthy() + expect(editor.isFoldedAtBufferRow(7)).toBeTruthy() + expect(editor.isFoldedAtBufferRow(8)).toBeFalsy() + + editor.moveLineUp() + + expect(editor.getSelectedBufferRange()).toEqual [[3, 2], [3, 9]] + expect(editor.lineTextForBufferRow(3)).toBe " while(items.length > 0) {" + expect(editor.lineTextForBufferRow(7)).toBe " var pivot = items.shift(), current, left = [], right = [];" + + expect(editor.isFoldedAtBufferRow(3)).toBeTruthy() + expect(editor.isFoldedAtBufferRow(4)).toBeTruthy() + expect(editor.isFoldedAtBufferRow(5)).toBeTruthy() + expect(editor.isFoldedAtBufferRow(6)).toBeTruthy() + expect(editor.isFoldedAtBufferRow(7)).toBeFalsy() + + describe "when the preceding row consists of folded code", -> it "moves the line above the folded row and preseveres the correct folds", -> expect(editor.lineTextForBufferRow(8)).toBe " return sort(left).concat(pivot).concat(sort(right));" @@ -1876,6 +1903,63 @@ describe "TextEditor", -> expect(editor.lineTextForBufferRow(3)).toBe " while(items.length > 0) {" expect(editor.lineTextForBufferRow(4)).toBe " if (items.length <= 1) return items;" + describe "when the selection's end intersects a fold", -> + it "moves the lines to the following row without breaking the fold", -> + expect(editor.lineTextForBufferRow(4)).toBe " while(items.length > 0) {" + + editor.createFold(4, 7) + editor.setSelectedBufferRange([[3, 2], [4, 9]], preserveFolds: true) + + expect(editor.isFoldedAtBufferRow(3)).toBeFalsy() + expect(editor.isFoldedAtBufferRow(4)).toBeTruthy() + expect(editor.isFoldedAtBufferRow(5)).toBeTruthy() + expect(editor.isFoldedAtBufferRow(6)).toBeTruthy() + expect(editor.isFoldedAtBufferRow(7)).toBeTruthy() + expect(editor.isFoldedAtBufferRow(8)).toBeFalsy() + + editor.moveLineUp() + + expect(editor.getSelectedBufferRange()).toEqual [[2, 2], [3, 9]] + expect(editor.lineTextForBufferRow(2)).toBe " var pivot = items.shift(), current, left = [], right = [];" + expect(editor.lineTextForBufferRow(3)).toBe " while(items.length > 0) {" + expect(editor.lineTextForBufferRow(7)).toBe " if (items.length <= 1) return items;" + + expect(editor.isFoldedAtBufferRow(2)).toBeFalsy() + expect(editor.isFoldedAtBufferRow(3)).toBeTruthy() + expect(editor.isFoldedAtBufferRow(4)).toBeTruthy() + expect(editor.isFoldedAtBufferRow(5)).toBeTruthy() + expect(editor.isFoldedAtBufferRow(6)).toBeTruthy() + expect(editor.isFoldedAtBufferRow(7)).toBeFalsy() + + describe "when the selection's start intersects a fold", -> + it "moves the lines to the following row without breaking the fold", -> + expect(editor.lineTextForBufferRow(4)).toBe " while(items.length > 0) {" + + editor.createFold(4, 7) + editor.setSelectedBufferRange([[4, 2], [8, 9]], preserveFolds: true) + + expect(editor.isFoldedAtBufferRow(4)).toBeTruthy() + expect(editor.isFoldedAtBufferRow(5)).toBeTruthy() + expect(editor.isFoldedAtBufferRow(6)).toBeTruthy() + expect(editor.isFoldedAtBufferRow(7)).toBeTruthy() + expect(editor.isFoldedAtBufferRow(8)).toBeFalsy() + expect(editor.isFoldedAtBufferRow(9)).toBeFalsy() + + editor.moveLineUp() + + expect(editor.getSelectedBufferRange()).toEqual [[3, 2], [7, 9]] + expect(editor.lineTextForBufferRow(3)).toBe " while(items.length > 0) {" + expect(editor.lineTextForBufferRow(7)).toBe " return sort(left).concat(pivot).concat(sort(right));" + expect(editor.lineTextForBufferRow(8)).toBe " var pivot = items.shift(), current, left = [], right = [];" + + expect(editor.isFoldedAtBufferRow(3)).toBeTruthy() + expect(editor.isFoldedAtBufferRow(4)).toBeTruthy() + expect(editor.isFoldedAtBufferRow(5)).toBeTruthy() + expect(editor.isFoldedAtBufferRow(6)).toBeTruthy() + expect(editor.isFoldedAtBufferRow(7)).toBeFalsy() + expect(editor.isFoldedAtBufferRow(8)).toBeFalsy() + + describe "when the selection spans multiple lines, but ends at column 0", -> it "does not move the last line of the selection", -> expect(editor.lineTextForBufferRow(2)).toBe " if (items.length <= 1) return items;" @@ -1994,6 +2078,31 @@ describe "TextEditor", -> expect(editor.lineTextForBufferRow(2)).toBe " var pivot = items.shift(), current, left = [], right = [];" expect(editor.lineTextForBufferRow(3)).toBe " if (items.length <= 1) return items;" + describe "when the cursor is at the beginning of a fold", -> + it "moves the line to the following row without breaking the fold", -> + expect(editor.lineTextForBufferRow(4)).toBe " while(items.length > 0) {" + + editor.createFold(4, 7) + editor.setSelectedBufferRange([[4, 2], [4, 9]], preserveFolds: true) + + expect(editor.isFoldedAtBufferRow(4)).toBeTruthy() + expect(editor.isFoldedAtBufferRow(5)).toBeTruthy() + expect(editor.isFoldedAtBufferRow(6)).toBeTruthy() + expect(editor.isFoldedAtBufferRow(7)).toBeTruthy() + expect(editor.isFoldedAtBufferRow(8)).toBeFalsy() + + editor.moveLineDown() + + expect(editor.getSelectedBufferRange()).toEqual [[5, 2], [5, 9]] + expect(editor.lineTextForBufferRow(4)).toBe " return sort(left).concat(pivot).concat(sort(right));" + expect(editor.lineTextForBufferRow(5)).toBe " while(items.length > 0) {" + + expect(editor.isFoldedAtBufferRow(5)).toBeTruthy() + expect(editor.isFoldedAtBufferRow(6)).toBeTruthy() + expect(editor.isFoldedAtBufferRow(7)).toBeTruthy() + expect(editor.isFoldedAtBufferRow(8)).toBeTruthy() + expect(editor.isFoldedAtBufferRow(9)).toBeFalsy() + describe "when the following row is a folded row", -> it "moves the line below the folded row and preserves the fold", -> expect(editor.lineTextForBufferRow(3)).toBe " var pivot = items.shift(), current, left = [], right = [];" @@ -2049,6 +2158,63 @@ describe "TextEditor", -> expect(editor.lineTextForBufferRow(3)).toBe " if (items.length <= 1) return items;" expect(editor.lineTextForBufferRow(4)).toBe " while(items.length > 0) {" + describe "when the selection's end intersects a fold", -> + it "moves the lines to the following row without breaking the fold", -> + expect(editor.lineTextForBufferRow(4)).toBe " while(items.length > 0) {" + + editor.createFold(4, 7) + editor.setSelectedBufferRange([[3, 2], [4, 9]], preserveFolds: true) + + expect(editor.isFoldedAtBufferRow(3)).toBeFalsy() + expect(editor.isFoldedAtBufferRow(4)).toBeTruthy() + expect(editor.isFoldedAtBufferRow(5)).toBeTruthy() + expect(editor.isFoldedAtBufferRow(6)).toBeTruthy() + expect(editor.isFoldedAtBufferRow(7)).toBeTruthy() + expect(editor.isFoldedAtBufferRow(8)).toBeFalsy() + + editor.moveLineDown() + + expect(editor.getSelectedBufferRange()).toEqual [[4, 2], [5, 9]] + expect(editor.lineTextForBufferRow(3)).toBe " return sort(left).concat(pivot).concat(sort(right));" + expect(editor.lineTextForBufferRow(4)).toBe " var pivot = items.shift(), current, left = [], right = [];" + expect(editor.lineTextForBufferRow(5)).toBe " while(items.length > 0) {" + + expect(editor.isFoldedAtBufferRow(4)).toBeFalsy() + expect(editor.isFoldedAtBufferRow(5)).toBeTruthy() + expect(editor.isFoldedAtBufferRow(6)).toBeTruthy() + expect(editor.isFoldedAtBufferRow(7)).toBeTruthy() + expect(editor.isFoldedAtBufferRow(8)).toBeTruthy() + expect(editor.isFoldedAtBufferRow(9)).toBeFalsy() + + describe "when the selection's start intersects a fold", -> + it "moves the lines to the following row without breaking the fold", -> + expect(editor.lineTextForBufferRow(4)).toBe " while(items.length > 0) {" + + editor.createFold(4, 7) + editor.setSelectedBufferRange([[4, 2], [8, 9]], preserveFolds: true) + + expect(editor.isFoldedAtBufferRow(4)).toBeTruthy() + expect(editor.isFoldedAtBufferRow(5)).toBeTruthy() + expect(editor.isFoldedAtBufferRow(6)).toBeTruthy() + expect(editor.isFoldedAtBufferRow(7)).toBeTruthy() + expect(editor.isFoldedAtBufferRow(8)).toBeFalsy() + expect(editor.isFoldedAtBufferRow(9)).toBeFalsy() + + editor.moveLineDown() + + expect(editor.getSelectedBufferRange()).toEqual [[5, 2], [9, 9]] + expect(editor.lineTextForBufferRow(4)).toBe " };" + expect(editor.lineTextForBufferRow(5)).toBe " while(items.length > 0) {" + expect(editor.lineTextForBufferRow(9)).toBe " return sort(left).concat(pivot).concat(sort(right));" + + expect(editor.isFoldedAtBufferRow(4)).toBeFalsy() + expect(editor.isFoldedAtBufferRow(5)).toBeTruthy() + expect(editor.isFoldedAtBufferRow(6)).toBeTruthy() + expect(editor.isFoldedAtBufferRow(7)).toBeTruthy() + expect(editor.isFoldedAtBufferRow(8)).toBeTruthy() + expect(editor.isFoldedAtBufferRow(9)).toBeFalsy() + expect(editor.isFoldedAtBufferRow(10)).toBeFalsy() + describe "when the following row is a folded row", -> it "moves the lines spanned by the selection to the following row, but preserves the folded code", -> expect(editor.lineTextForBufferRow(2)).toBe " if (items.length <= 1) return items;" diff --git a/src/text-editor.coffee b/src/text-editor.coffee index e77ccb4a8..a1baa06f0 100644 --- a/src/text-editor.coffee +++ b/src/text-editor.coffee @@ -899,6 +899,15 @@ class TextEditor extends Model else linesRange = new Range(linesRangeStart, [selection.end.row + 1, 0]) + # If there's a fold containing either the starting row or the end row + # of the selection then the whole fold needs to be moved. + if fold = @displayBuffer.largestFoldContainingBufferRow(selection.start.row) + newEndRow = fold.getBufferRange().end.row + 1 + linesRange.end.row = newEndRow if newEndRow > linesRange.end.row + else if fold = @displayBuffer.largestFoldContainingBufferRow(selection.end.row) + newEndRow = fold.getBufferRange().end.row + 1 + linesRange.end.row = newEndRow if newEndRow > linesRange.end.row + # If selected line range is preceded by a fold, one line above on screen # could be multiple lines in the buffer. precedingScreenRow = @screenRowForBufferRow(linesRange.start.row) - 1 @@ -961,6 +970,15 @@ class TextEditor extends Model else linesRange = new Range(linesRangeStart, [selection.end.row + 1, 0]) + # If there's a fold containing either the starting row or the end row + # of the selection then the whole fold needs to be moved. + if fold = @displayBuffer.largestFoldContainingBufferRow(selection.start.row) + newEndRow = fold.getBufferRange().end.row + 1 + linesRange.end.row = newEndRow if newEndRow > linesRange.end.row + else if fold = @displayBuffer.largestFoldContainingBufferRow(selection.end.row) + newEndRow = fold.getBufferRange().end.row + 1 + linesRange.end.row = newEndRow if newEndRow > linesRange.end.row + # If selected line range is followed by a fold, one line below on screen # could be multiple lines in the buffer. But at the same time, if the # next buffer row is wrapped, one line in the buffer can represent many