Merge pull request #8232 from lpommers/move-lines-up-and-down-with-multiple-selections

Move lines up and down with multiple selections
This commit is contained in:
Nathan Sobo
2015-11-07 14:40:58 -07:00
3 changed files with 840 additions and 111 deletions

12
spec/fixtures/sample-with-many-folds.js vendored Normal file
View File

@@ -0,0 +1,12 @@
1;
2;
function f3() {
return 4;
};
6;
7;
function f8() {
return 9;
};
11;
12;

View File

@@ -2123,6 +2123,692 @@ describe "TextEditor", ->
expect(editor2.getSelectedBufferRanges()).not.toEqual editor.getSelectedBufferRanges()
describe "buffer manipulation", ->
describe ".moveLineUp", ->
it "moves the line under the cursor up", ->
editor.setCursorBufferPosition([1, 0])
editor.moveLineUp()
expect(editor.getTextInBufferRange([[0, 0], [0, 30]])).toBe " var sort = function(items) {"
expect(editor.indentationForBufferRow(0)).toBe 1
expect(editor.indentationForBufferRow(1)).toBe 0
it "updates the line's indentation when the editor.autoIndent setting is true", ->
atom.config.set('editor.autoIndent', true)
editor.setCursorBufferPosition([1, 0])
editor.moveLineUp()
expect(editor.indentationForBufferRow(0)).toBe 0
expect(editor.indentationForBufferRow(1)).toBe 0
describe "when there is a single selection", ->
describe "when the selection spans a single line", ->
describe "when there is no fold in the preceeding row", ->
it "moves the line to the preceding row", ->
expect(editor.lineTextForBufferRow(2)).toBe " if (items.length <= 1) return items;"
expect(editor.lineTextForBufferRow(3)).toBe " var pivot = items.shift(), current, left = [], right = [];"
editor.setSelectedBufferRange([[3, 2], [3, 9]])
editor.moveLineUp()
expect(editor.getSelectedBufferRange()).toEqual [[2, 2], [2, 9]]
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 previous 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));"
expect(editor.lineTextForBufferRow(9)).toBe " };"
editor.createFold(4, 7)
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.setSelectedBufferRange([[8, 0], [8, 4]])
editor.moveLineUp()
expect(editor.getSelectedBufferRange()).toEqual [[4, 0], [4, 4]]
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 selection spans multiple lines", ->
it "moves the lines spanned by the selection to the preceding row", ->
expect(editor.lineTextForBufferRow(2)).toBe " if (items.length <= 1) return items;"
expect(editor.lineTextForBufferRow(3)).toBe " var pivot = items.shift(), current, left = [], right = [];"
expect(editor.lineTextForBufferRow(4)).toBe " while(items.length > 0) {"
editor.setSelectedBufferRange([[3, 2], [4, 9]])
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(4)).toBe " if (items.length <= 1) return items;"
describe "when the selection's end intersects a fold", ->
it "moves the lines to the previous 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 previous 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;"
expect(editor.lineTextForBufferRow(3)).toBe " var pivot = items.shift(), current, left = [], right = [];"
expect(editor.lineTextForBufferRow(4)).toBe " while(items.length > 0) {"
editor.setSelectedBufferRange([[3, 2], [4, 0]])
editor.moveLineUp()
expect(editor.getSelectedBufferRange()).toEqual [[2, 2], [3, 0]]
expect(editor.lineTextForBufferRow(2)).toBe " var pivot = items.shift(), current, left = [], right = [];"
expect(editor.lineTextForBufferRow(3)).toBe " if (items.length <= 1) return items;"
expect(editor.lineTextForBufferRow(4)).toBe " while(items.length > 0) {"
describe "when the preceeding row is a folded row", ->
it "moves the lines spanned by the selection to the preceeding row, but preserves the folded code", ->
expect(editor.lineTextForBufferRow(8)).toBe " return sort(left).concat(pivot).concat(sort(right));"
expect(editor.lineTextForBufferRow(9)).toBe " };"
editor.createFold(4, 7)
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.setSelectedBufferRange([[8, 0], [9, 2]])
editor.moveLineUp()
expect(editor.getSelectedBufferRange()).toEqual [[4, 0], [5, 2]]
expect(editor.lineTextForBufferRow(4)).toBe " return sort(left).concat(pivot).concat(sort(right));"
expect(editor.lineTextForBufferRow(5)).toBe " };"
expect(editor.lineTextForBufferRow(6)).toBe " while(items.length > 0) {"
expect(editor.isFoldedAtBufferRow(5)).toBeFalsy()
expect(editor.isFoldedAtBufferRow(6)).toBeTruthy()
expect(editor.isFoldedAtBufferRow(7)).toBeTruthy()
expect(editor.isFoldedAtBufferRow(8)).toBeTruthy()
expect(editor.isFoldedAtBufferRow(9)).toBeTruthy()
expect(editor.isFoldedAtBufferRow(10)).toBeFalsy()
describe "when there are multiple selections", ->
describe "when all the selections span different lines", ->
describe "when there is no folds", ->
it "moves all lines that are spanned by a selection to the preceding row", ->
editor.setSelectedBufferRanges([[[1, 2], [1, 9]], [[3, 2], [3, 9]], [[5, 2], [5, 9]]])
editor.moveLineUp()
expect(editor.getSelectedBufferRanges()).toEqual [[[0, 2], [0, 9]], [[2, 2], [2, 9]], [[4, 2], [4, 9]]]
expect(editor.lineTextForBufferRow(0)).toBe " var sort = function(items) {"
expect(editor.lineTextForBufferRow(1)).toBe "var quicksort = function () {"
expect(editor.lineTextForBufferRow(2)).toBe " var pivot = items.shift(), current, left = [], right = [];"
expect(editor.lineTextForBufferRow(3)).toBe " if (items.length <= 1) return items;"
expect(editor.lineTextForBufferRow(4)).toBe " current = items.shift();"
expect(editor.lineTextForBufferRow(5)).toBe " while(items.length > 0) {"
describe "when one selection intersects a fold", ->
it "moves the lines to the previous row without breaking the fold", ->
expect(editor.lineTextForBufferRow(4)).toBe " while(items.length > 0) {"
editor.createFold(4, 7)
editor.setSelectedBufferRanges([
[[2, 2], [2, 9]],
[[4, 2], [4, 9]]
], preserveFolds: true)
expect(editor.isFoldedAtBufferRow(2)).toBeFalsy()
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()
expect(editor.isFoldedAtBufferRow(9)).toBeFalsy()
editor.moveLineUp()
expect(editor.getSelectedBufferRanges()).toEqual([
[[1, 2], [1, 9]],
[[3, 2], [3, 9]]
])
expect(editor.lineTextForBufferRow(1)).toBe " if (items.length <= 1) return items;"
expect(editor.lineTextForBufferRow(2)).toBe " var sort = function(items) {"
expect(editor.lineTextForBufferRow(3)).toBe " while(items.length > 0) {"
expect(editor.lineTextForBufferRow(7)).toBe " var pivot = items.shift(), current, left = [], right = [];"
expect(editor.isFoldedAtBufferRow(1)).toBeFalsy()
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()
expect(editor.isFoldedAtBufferRow(8)).toBeFalsy()
describe "when there is a fold", ->
it "moves all lines that spanned by a selection to preceding row, preserving all folds", ->
editor.createFold(4, 7)
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.setSelectedBufferRanges([[[8, 0], [8, 3]], [[11, 0], [11, 5]]])
editor.moveLineUp()
expect(editor.getSelectedBufferRanges()).toEqual [[[4, 0], [4, 3]], [[10, 0], [10, 5]]]
expect(editor.lineTextForBufferRow(4)).toBe " return sort(left).concat(pivot).concat(sort(right));"
expect(editor.lineTextForBufferRow(10)).toBe " return sort(Array.apply(this, arguments));"
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 there are many folds', ->
beforeEach ->
waitsForPromise ->
atom.workspace.open('sample-with-many-folds.js', autoIndent: false).then (o) -> editor = o
describe 'and many selections intersects folded rows', ->
it 'moves and preserves all the folds', ->
editor.createFold(2, 4)
editor.createFold(7, 9)
editor.setSelectedBufferRanges([
[[1, 0], [5, 4]],
[[7, 0], [7, 4]]
], preserveFolds: true)
editor.moveLineUp()
expect(editor.lineTextForBufferRow(1)).toEqual "function f3() {"
expect(editor.lineTextForBufferRow(4)).toEqual "6;"
expect(editor.lineTextForBufferRow(5)).toEqual "1;"
expect(editor.lineTextForBufferRow(6)).toEqual "function f8() {"
expect(editor.lineTextForBufferRow(9)).toEqual "7;"
expect(editor.isFoldedAtBufferRow(1)).toBeTruthy()
expect(editor.isFoldedAtBufferRow(2)).toBeTruthy()
expect(editor.isFoldedAtBufferRow(3)).toBeTruthy()
expect(editor.isFoldedAtBufferRow(4)).toBeFalsy()
expect(editor.isFoldedAtBufferRow(6)).toBeTruthy()
expect(editor.isFoldedAtBufferRow(7)).toBeTruthy()
expect(editor.isFoldedAtBufferRow(8)).toBeTruthy()
expect(editor.isFoldedAtBufferRow(9)).toBeFalsy()
describe "when some of the selections span the same lines", ->
it "moves lines that contain multiple selections correctly", ->
editor.setSelectedBufferRanges([[[3, 2], [3, 9]], [[3, 12], [3, 13]]])
editor.moveLineUp()
expect(editor.getSelectedBufferRanges()).toEqual [[[2, 2], [2, 9]], [[2, 12], [2, 13]]]
expect(editor.lineTextForBufferRow(2)).toBe " var pivot = items.shift(), current, left = [], right = [];"
describe "when one of the selections spans line 0", ->
it "doesn't move any lines, since line 0 can't move", ->
editor.setSelectedBufferRanges([[[0, 2], [1, 9]], [[2, 2], [2, 9]], [[4, 2], [4, 9]]])
editor.moveLineUp()
expect(editor.getSelectedBufferRanges()).toEqual [[[0, 2], [1, 9]], [[2, 2], [2, 9]], [[4, 2], [4, 9]]]
expect(buffer.isModified()).toBe false
describe "when one of the selections spans the last line, and it is empty", ->
it "doesn't move any lines, since the last line can't move", ->
buffer.append('\n')
editor.setSelectedBufferRanges([[[0, 2], [1, 9]], [[2, 2], [2, 9]], [[13, 0], [13, 0]]])
editor.moveLineUp()
expect(editor.getSelectedBufferRanges()).toEqual [[[0, 2], [1, 9]], [[2, 2], [2, 9]], [[13, 0], [13, 0]]]
describe ".moveLineDown", ->
it "moves the line under the cursor down", ->
editor.setCursorBufferPosition([0, 0])
editor.moveLineDown()
expect(editor.getTextInBufferRange([[1, 0], [1, 31]])).toBe "var quicksort = function () {"
expect(editor.indentationForBufferRow(0)).toBe 1
expect(editor.indentationForBufferRow(1)).toBe 0
it "updates the line's indentation when the editor.autoIndent setting is true", ->
atom.config.set('editor.autoIndent', true)
editor.setCursorBufferPosition([0, 0])
editor.moveLineDown()
expect(editor.indentationForBufferRow(0)).toBe 1
expect(editor.indentationForBufferRow(1)).toBe 2
describe "when there is a single selection", ->
describe "when the selection spans a single line", ->
describe "when there is no fold in the following row", ->
it "moves the line to the following row", ->
expect(editor.lineTextForBufferRow(2)).toBe " if (items.length <= 1) return items;"
expect(editor.lineTextForBufferRow(3)).toBe " var pivot = items.shift(), current, left = [], right = [];"
editor.setSelectedBufferRange([[2, 2], [2, 9]])
editor.moveLineDown()
expect(editor.getSelectedBufferRange()).toEqual [[3, 2], [3, 9]]
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 = [];"
expect(editor.lineTextForBufferRow(4)).toBe " while(items.length > 0) {"
editor.createFold(4, 7)
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.setSelectedBufferRange([[3, 0], [3, 4]])
editor.moveLineDown()
expect(editor.getSelectedBufferRange()).toEqual [[7, 0], [7, 4]]
expect(editor.lineTextForBufferRow(3)).toBe " while(items.length > 0) {"
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.lineTextForBufferRow(7)).toBe " var pivot = items.shift(), current, left = [], right = [];"
describe "when the selection spans multiple lines", ->
it "moves the lines spanned by the selection to the following row", ->
expect(editor.lineTextForBufferRow(2)).toBe " if (items.length <= 1) return items;"
expect(editor.lineTextForBufferRow(3)).toBe " var pivot = items.shift(), current, left = [], right = [];"
expect(editor.lineTextForBufferRow(4)).toBe " while(items.length > 0) {"
editor.setSelectedBufferRange([[2, 2], [3, 9]])
editor.moveLineDown()
expect(editor.getSelectedBufferRange()).toEqual [[3, 2], [4, 9]]
expect(editor.lineTextForBufferRow(2)).toBe " while(items.length > 0) {"
expect(editor.lineTextForBufferRow(3)).toBe " if (items.length <= 1) return items;"
expect(editor.lineTextForBufferRow(4)).toBe " var pivot = items.shift(), current, left = [], right = [];"
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;"
expect(editor.lineTextForBufferRow(3)).toBe " var pivot = items.shift(), current, left = [], right = [];"
expect(editor.lineTextForBufferRow(4)).toBe " while(items.length > 0) {"
editor.setSelectedBufferRange([[2, 2], [3, 0]])
editor.moveLineDown()
expect(editor.getSelectedBufferRange()).toEqual [[3, 2], [4, 0]]
expect(editor.lineTextForBufferRow(2)).toBe " var pivot = items.shift(), current, left = [], right = [];"
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;"
expect(editor.lineTextForBufferRow(3)).toBe " var pivot = items.shift(), current, left = [], right = [];"
editor.createFold(4, 7)
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.setSelectedBufferRange([[2, 0], [3, 2]])
editor.moveLineDown()
expect(editor.getSelectedBufferRange()).toEqual [[6, 0], [7, 2]]
expect(editor.lineTextForBufferRow(2)).toBe " while(items.length > 0) {"
expect(editor.isFoldedAtBufferRow(1)).toBeFalsy()
expect(editor.isFoldedAtBufferRow(2)).toBeTruthy()
expect(editor.isFoldedAtBufferRow(3)).toBeTruthy()
expect(editor.isFoldedAtBufferRow(4)).toBeTruthy()
expect(editor.isFoldedAtBufferRow(5)).toBeTruthy()
expect(editor.isFoldedAtBufferRow(6)).toBeFalsy()
expect(editor.lineTextForBufferRow(6)).toBe " if (items.length <= 1) return items;"
describe "when there are multiple selections", ->
describe "when all the selections span different lines", ->
describe "when there is no folds", ->
it "moves all lines that are spanned by a selection to the following row", ->
editor.setSelectedBufferRanges([[[1, 2], [1, 9]], [[3, 2], [3, 9]], [[5, 2], [5, 9]]])
editor.moveLineDown()
expect(editor.getSelectedBufferRanges()).toEqual [[[6, 2], [6, 9]], [[4, 2], [4, 9]], [[2, 2], [2, 9]]]
expect(editor.lineTextForBufferRow(1)).toBe " if (items.length <= 1) return items;"
expect(editor.lineTextForBufferRow(2)).toBe " var sort = function(items) {"
expect(editor.lineTextForBufferRow(3)).toBe " while(items.length > 0) {"
expect(editor.lineTextForBufferRow(4)).toBe " var pivot = items.shift(), current, left = [], right = [];"
expect(editor.lineTextForBufferRow(5)).toBe " current < pivot ? left.push(current) : right.push(current);"
expect(editor.lineTextForBufferRow(6)).toBe " current = items.shift();"
describe 'when there are many folds', ->
beforeEach ->
waitsForPromise ->
atom.workspace.open('sample-with-many-folds.js', autoIndent: false).then (o) -> editor = o
describe 'and many selections intersects folded rows', ->
it 'moves and preserves all the folds', ->
editor.createFold(2, 4)
editor.createFold(7, 9)
editor.setSelectedBufferRanges([
[[2, 0], [2, 4]],
[[6, 0], [10, 4]]
], preserveFolds: true)
editor.moveLineDown()
expect(editor.lineTextForBufferRow(2)).toEqual "6;"
expect(editor.lineTextForBufferRow(3)).toEqual "function f3() {"
expect(editor.lineTextForBufferRow(6)).toEqual "12;"
expect(editor.lineTextForBufferRow(7)).toEqual "7;"
expect(editor.lineTextForBufferRow(8)).toEqual "function f8() {"
expect(editor.lineTextForBufferRow(11)).toEqual "11;"
expect(editor.isFoldedAtBufferRow(2)).toBeFalsy()
expect(editor.isFoldedAtBufferRow(3)).toBeTruthy()
expect(editor.isFoldedAtBufferRow(4)).toBeTruthy()
expect(editor.isFoldedAtBufferRow(5)).toBeTruthy()
expect(editor.isFoldedAtBufferRow(6)).toBeFalsy()
expect(editor.isFoldedAtBufferRow(7)).toBeFalsy()
expect(editor.isFoldedAtBufferRow(8)).toBeTruthy()
expect(editor.isFoldedAtBufferRow(9)).toBeTruthy()
expect(editor.isFoldedAtBufferRow(10)).toBeTruthy()
expect(editor.isFoldedAtBufferRow(11)).toBeFalsy()
describe "when there is a fold below one of the selected row", ->
it "moves all lines spanned by a selection to the following row, preserving the fold", ->
editor.createFold(4, 7)
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.setSelectedBufferRanges([[[1, 2], [1, 6]], [[3, 0], [3, 4]], [[8, 0], [8, 3]]])
editor.moveLineDown()
expect(editor.getSelectedBufferRanges()).toEqual [[[9, 0], [9, 3]], [[7, 0], [7, 4]], [[2, 2], [2, 6]]]
expect(editor.lineTextForBufferRow(2)).toBe " var sort = function(items) {"
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.lineTextForBufferRow(7)).toBe " var pivot = items.shift(), current, left = [], right = [];"
expect(editor.lineTextForBufferRow(9)).toBe " return sort(left).concat(pivot).concat(sort(right));"
describe "when there is a fold below a group of multiple selections without any lines with no selection in-between", ->
it "moves all the lines below the fold, preserving the fold", ->
editor.createFold(4, 7)
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.setSelectedBufferRanges([[[2, 2], [2, 6]], [[3, 0], [3, 4]]])
editor.moveLineDown()
expect(editor.getSelectedBufferRanges()).toEqual [[[7, 0], [7, 4]], [[6, 2], [6, 6]]]
expect(editor.lineTextForBufferRow(2)).toBe " while(items.length > 0) {"
expect(editor.isFoldedAtBufferRow(2)).toBeTruthy()
expect(editor.isFoldedAtBufferRow(3)).toBeTruthy()
expect(editor.isFoldedAtBufferRow(4)).toBeTruthy()
expect(editor.isFoldedAtBufferRow(5)).toBeTruthy()
expect(editor.isFoldedAtBufferRow(6)).toBeFalsy()
expect(editor.lineTextForBufferRow(6)).toBe " if (items.length <= 1) return items;"
expect(editor.lineTextForBufferRow(7)).toBe " var pivot = items.shift(), current, left = [], right = [];"
describe "when one selection intersects a fold", ->
it "moves the lines to the previous row without breaking the fold", ->
expect(editor.lineTextForBufferRow(4)).toBe " while(items.length > 0) {"
editor.createFold(4, 7)
editor.setSelectedBufferRanges([
[[2, 2], [2, 9]],
[[4, 2], [4, 9]]
], preserveFolds: true)
expect(editor.isFoldedAtBufferRow(2)).toBeFalsy()
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()
expect(editor.isFoldedAtBufferRow(9)).toBeFalsy()
editor.moveLineDown()
expect(editor.getSelectedBufferRanges()).toEqual([
[[5, 2], [5, 9]]
[[3, 2], [3, 9]],
])
expect(editor.lineTextForBufferRow(2)).toBe " var pivot = items.shift(), current, left = [], right = [];"
expect(editor.lineTextForBufferRow(3)).toBe " if (items.length <= 1) return items;"
expect(editor.lineTextForBufferRow(4)).toBe " return sort(left).concat(pivot).concat(sort(right));"
expect(editor.lineTextForBufferRow(5)).toBe " while(items.length > 0) {"
expect(editor.lineTextForBufferRow(9)).toBe " };"
expect(editor.isFoldedAtBufferRow(2)).toBeFalsy()
expect(editor.isFoldedAtBufferRow(3)).toBeFalsy()
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 some of the selections span the same lines", ->
it "moves lines that contain multiple selections correctly", ->
editor.setSelectedBufferRanges([[[3, 2], [3, 9]], [[3, 12], [3, 13]]])
editor.moveLineDown()
expect(editor.getSelectedBufferRanges()).toEqual [[[4, 12], [4, 13]], [[4, 2], [4, 9]]]
expect(editor.lineTextForBufferRow(3)).toBe " while(items.length > 0) {"
describe "when the selections are above a wrapped line", ->
beforeEach ->
editor.setSoftWrapped(true)
editor.setEditorWidthInChars(80)
editor.setText("""
1
2
Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat.
3
4
""")
it 'moves the lines past the soft wrapped line', ->
editor.setSelectedBufferRanges([[[0, 0], [0, 0]], [[1, 0], [1, 0]]])
editor.moveLineDown()
expect(editor.lineTextForBufferRow(0)).not.toBe "2"
expect(editor.lineTextForBufferRow(1)).toBe "1"
expect(editor.lineTextForBufferRow(2)).toBe "2"
describe ".insertText(text)", ->
describe "when there is a single selection", ->
beforeEach ->
@@ -4492,36 +5178,6 @@ describe "TextEditor", ->
"""
expect(editor.getSelectedBufferRange()).toEqual [[13, 0], [14, 2]]
describe ".moveLineUp()", ->
it "moves the line under the cursor up", ->
editor.setCursorBufferPosition([1, 0])
editor.moveLineUp()
expect(editor.getTextInBufferRange([[0, 0], [0, 30]])).toBe " var sort = function(items) {"
expect(editor.indentationForBufferRow(0)).toBe 1
expect(editor.indentationForBufferRow(1)).toBe 0
it "updates the line's indentation when the editor.autoIndent setting is true", ->
atom.config.set('editor.autoIndent', true)
editor.setCursorBufferPosition([1, 0])
editor.moveLineUp()
expect(editor.indentationForBufferRow(0)).toBe 0
expect(editor.indentationForBufferRow(1)).toBe 0
describe ".moveLineDown()", ->
it "moves the line under the cursor down", ->
editor.setCursorBufferPosition([0, 0])
editor.moveLineDown()
expect(editor.getTextInBufferRange([[1, 0], [1, 31]])).toBe "var quicksort = function () {"
expect(editor.indentationForBufferRow(0)).toBe 1
expect(editor.indentationForBufferRow(1)).toBe 0
it "updates the line's indentation when the editor.autoIndent setting is true", ->
atom.config.set('editor.autoIndent', true)
editor.setCursorBufferPosition([0, 0])
editor.moveLineDown()
expect(editor.indentationForBufferRow(0)).toBe 1
expect(editor.indentationForBufferRow(1)).toBe 2
describe ".shouldPromptToSave()", ->
it "returns false when an edit session's buffer is in use by more than one session", ->
jasmine.unspy(editor, 'shouldPromptToSave')

View File

@@ -866,116 +866,177 @@ class TextEditor extends Model
@transact groupingInterval, =>
fn(selection, index) for selection, index in @getSelectionsOrderedByBufferPosition()
# Move lines intersection the most recent selection up by one row in screen
# coordinates.
# Move lines intersecting the most recent selection or multiple selections
# up by one row in screen coordinates.
moveLineUp: ->
selection = @getSelectedBufferRange()
return if selection.start.row is 0
lastRow = @buffer.getLastRow()
return if selection.isEmpty() and selection.start.row is lastRow and @buffer.getLastLine() is ''
selections = @getSelectedBufferRanges()
selections.sort (a, b) -> a.compare(b)
if selections[0].start.row is 0
return
if selections[selections.length - 1].start.row is @getLastBufferRow() and @buffer.getLastLine() is ''
return
@transact =>
foldedRows = []
rows = [selection.start.row..selection.end.row]
if selection.start.row isnt selection.end.row and selection.end.column is 0
rows.pop() unless @isFoldedAtBufferRow(selection.end.row)
newSelectionRanges = []
# Move line around the fold that is directly above the selection
precedingScreenRow = @screenPositionForBufferPosition([selection.start.row]).translate([-1])
precedingBufferRow = @bufferPositionForScreenPosition(precedingScreenRow).row
if fold = @largestFoldContainingBufferRow(precedingBufferRow)
insertDelta = fold.getBufferRange().getRowCount()
else
insertDelta = 1
while selections.length > 0
# Find selections spanning a contiguous set of lines
selection = selections.shift()
selectionsToMove = [selection]
for row in rows
if fold = @displayBuffer.largestFoldStartingAtBufferRow(row)
bufferRange = fold.getBufferRange()
startRow = bufferRange.start.row
endRow = bufferRange.end.row
foldedRows.push(startRow - insertDelta)
while selection.end.row is selections[0]?.start.row
selectionsToMove.push(selections[0])
selection.end.row = selections[0].end.row
selections.shift()
# Compute the range spanned by all these selections...
linesRangeStart = [selection.start.row, 0]
if selection.end.row > selection.start.row and selection.end.column is 0
# Don't move the last line of a multi-line selection if the selection ends at column 0
linesRange = new Range(linesRangeStart, selection.end)
else
startRow = row
endRow = row
linesRange = new Range(linesRangeStart, [selection.end.row + 1, 0])
insertPosition = Point.fromObject([startRow - insertDelta])
endPosition = Point.min([endRow + 1], @buffer.getEndPosition())
lines = @buffer.getTextInRange([[startRow], endPosition])
if endPosition.row is lastRow and endPosition.column > 0 and not @buffer.lineEndingForRow(endPosition.row)
lines = "#{lines}\n"
# 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 and restored.
# The initial fold range is stored and will be translated once the
# insert delta is know.
selectionFoldRanges = []
foldAtSelectionStart =
@displayBuffer.largestFoldContainingBufferRow(selection.start.row)
foldAtSelectionEnd =
@displayBuffer.largestFoldContainingBufferRow(selection.end.row)
if fold = foldAtSelectionStart ? foldAtSelectionEnd
selectionFoldRanges.push range = fold.getBufferRange()
newEndRow = range.end.row + 1
linesRange.end.row = newEndRow if newEndRow > linesRange.end.row
fold.destroy()
@buffer.deleteRows(startRow, endRow)
# 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
precedingBufferRow = @bufferRowForScreenRow(precedingScreenRow)
insertDelta = linesRange.start.row - precedingBufferRow
# Any folds in the text that is moved will need to be re-created.
# It includes the folds that were intersecting with the selection.
rangesToRefold = selectionFoldRanges.concat(
@outermostFoldsInBufferRowRange(linesRange.start.row, linesRange.end.row).map (fold) ->
range = fold.getBufferRange()
fold.destroy()
range
).map (range) -> range.translate([-insertDelta, 0])
# Make sure the inserted text doesn't go into an existing fold
if fold = @displayBuffer.largestFoldStartingAtBufferRow(insertPosition.row)
@unfoldBufferRow(insertPosition.row)
foldedRows.push(insertPosition.row + endRow - startRow + fold.getBufferRange().getRowCount())
if fold = @displayBuffer.largestFoldStartingAtBufferRow(precedingBufferRow)
rangesToRefold.push(fold.getBufferRange().translate([linesRange.getRowCount() - 1, 0]))
fold.destroy()
@buffer.insert(insertPosition, lines)
# Delete lines spanned by selection and insert them on the preceding buffer row
lines = @buffer.getTextInRange(linesRange)
lines += @buffer.lineEndingForRow(linesRange.end.row - 1) unless lines[lines.length - 1] is '\n'
@buffer.delete(linesRange)
@buffer.insert([precedingBufferRow, 0], lines)
# Restore folds that existed before the lines were moved
for foldedRow in foldedRows when 0 <= foldedRow <= @getLastBufferRow()
@foldBufferRow(foldedRow)
# Restore folds that existed before the lines were moved
for rangeToRefold in rangesToRefold
@displayBuffer.createFold(rangeToRefold.start.row, rangeToRefold.end.row)
@setSelectedBufferRange(selection.translate([-insertDelta]), preserveFolds: true, autoscroll: true)
for selection in selectionsToMove
newSelectionRanges.push(selection.translate([-insertDelta, 0]))
@setSelectedBufferRanges(newSelectionRanges, {autoscroll: false, preserveFolds: true})
@autoIndentSelectedRows() if @shouldAutoIndent()
@scrollToBufferPosition([newSelectionRanges[0].start.row, 0])
# Move lines intersecting the most recent selection down by one row in screen
# coordinates.
# Move lines intersecting the most recent selection or muiltiple selections
# down by one row in screen coordinates.
moveLineDown: ->
selection = @getSelectedBufferRange()
lastRow = @buffer.getLastRow()
return if selection.end.row is lastRow
return if selection.end.row is lastRow - 1 and @buffer.getLastLine() is ''
selections = @getSelectedBufferRanges()
selections.sort (a, b) -> a.compare(b)
selections = selections.reverse()
@transact =>
foldedRows = []
rows = [selection.end.row..selection.start.row]
if selection.start.row isnt selection.end.row and selection.end.column is 0
rows.shift() unless @isFoldedAtBufferRow(selection.end.row)
@consolidateSelections()
newSelectionRanges = []
# Move line around the fold that is directly below the selection
followingScreenRow = @screenPositionForBufferPosition([selection.end.row]).translate([1])
followingBufferRow = @bufferPositionForScreenPosition(followingScreenRow).row
if fold = @largestFoldContainingBufferRow(followingBufferRow)
insertDelta = fold.getBufferRange().getRowCount()
else
insertDelta = 1
while selections.length > 0
# Find selections spanning a contiguous set of lines
selection = selections.shift()
selectionsToMove = [selection]
for row in rows
if fold = @displayBuffer.largestFoldStartingAtBufferRow(row)
bufferRange = fold.getBufferRange()
startRow = bufferRange.start.row
endRow = bufferRange.end.row
foldedRows.push(endRow + insertDelta)
# if the current selection start row matches the next selections' end row - make them one selection
while selection.start.row is selections[0]?.end.row
selectionsToMove.push(selections[0])
selection.start.row = selections[0].start.row
selections.shift()
# Compute the range spanned by all these selections...
linesRangeStart = [selection.start.row, 0]
if selection.end.row > selection.start.row and selection.end.column is 0
# Don't move the last line of a multi-line selection if the selection ends at column 0
linesRange = new Range(linesRangeStart, selection.end)
else
startRow = row
endRow = row
linesRange = new Range(linesRangeStart, [selection.end.row + 1, 0])
if endRow + 1 is lastRow
endPosition = [endRow, @buffer.lineLengthForRow(endRow)]
else
endPosition = [endRow + 1]
lines = @buffer.getTextInRange([[startRow], endPosition])
@buffer.deleteRows(startRow, endRow)
# 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 and restored.
# The initial fold range is stored and will be translated once the
# insert delta is know.
selectionFoldRanges = []
foldAtSelectionStart =
@displayBuffer.largestFoldContainingBufferRow(selection.start.row)
foldAtSelectionEnd =
@displayBuffer.largestFoldContainingBufferRow(selection.end.row)
if fold = foldAtSelectionStart ? foldAtSelectionEnd
selectionFoldRanges.push range = fold.getBufferRange()
newEndRow = range.end.row + 1
linesRange.end.row = newEndRow if newEndRow > linesRange.end.row
fold.destroy()
insertPosition = Point.min([startRow + insertDelta], @buffer.getEndPosition())
if insertPosition.row is @buffer.getLastRow() and insertPosition.column > 0
# 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
# screen rows.
followingScreenRow = @displayBuffer.lastScreenRowForBufferRow(linesRange.end.row) + 1
followingBufferRow = @bufferRowForScreenRow(followingScreenRow)
insertDelta = followingBufferRow - linesRange.end.row
# Any folds in the text that is moved will need to be re-created.
# It includes the folds that were intersecting with the selection.
rangesToRefold = selectionFoldRanges.concat(
@outermostFoldsInBufferRowRange(linesRange.start.row, linesRange.end.row).map (fold) ->
range = fold.getBufferRange()
fold.destroy()
range
).map (range) -> range.translate([insertDelta, 0])
# Make sure the inserted text doesn't go into an existing fold
if fold = @displayBuffer.largestFoldStartingAtBufferRow(followingBufferRow)
rangesToRefold.push(fold.getBufferRange().translate([insertDelta - 1, 0]))
fold.destroy()
# Delete lines spanned by selection and insert them on the following correct buffer row
insertPosition = new Point(selection.translate([insertDelta, 0]).start.row, 0)
lines = @buffer.getTextInRange(linesRange)
if linesRange.end.row is @buffer.getLastRow()
lines = "\n#{lines}"
# Make sure the inserted text doesn't go into an existing fold
if fold = @displayBuffer.largestFoldStartingAtBufferRow(insertPosition.row)
@unfoldBufferRow(insertPosition.row)
foldedRows.push(insertPosition.row + fold.getBufferRange().getRowCount())
@buffer.delete(linesRange)
@buffer.insert(insertPosition, lines)
# Restore folds that existed before the lines were moved
for foldedRow in foldedRows when 0 <= foldedRow <= @getLastBufferRow()
@foldBufferRow(foldedRow)
# Restore folds that existed before the lines were moved
for rangeToRefold in rangesToRefold
@displayBuffer.createFold(rangeToRefold.start.row, rangeToRefold.end.row)
@setSelectedBufferRange(selection.translate([insertDelta]), preserveFolds: true, autoscroll: true)
for selection in selectionsToMove
newSelectionRanges.push(selection.translate([insertDelta, 0]))
@setSelectedBufferRanges(newSelectionRanges, {autoscroll: false, preserveFolds: true})
@autoIndentSelectedRows() if @shouldAutoIndent()
@scrollToBufferPosition([newSelectionRanges[0].start.row - 1, 0])
# Duplicate the most recent cursor's current line.
duplicateLines: ->