diff --git a/spec/text-editor-spec.coffee b/spec/text-editor-spec.coffee index d7230c9a0..8ff34bacb 100644 --- a/spec/text-editor-spec.coffee +++ b/spec/text-editor-spec.coffee @@ -2747,6 +2747,39 @@ describe "TextEditor", -> expect(editor.lineTextForBufferRow(0)).toBe "var quicksort" expect(editor.lineTextForBufferRow(1)).toBe "sort = function () {" + describe "when a full line was cut", -> + beforeEach -> + editor.setCursorBufferPosition([2, 13]) + editor.cutSelectedText() + editor.setCursorBufferPosition([2, 13]) + + it "pastes the line above the cursor and retains the cursor's column", -> + editor.pasteText() + 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.getCursorBufferPosition()).toEqual([3, 13]) + + describe "when a full line was copied", -> + beforeEach -> + editor.setCursorBufferPosition([2, 13]) + editor.copySelectedText() + + describe "when there is a selection", -> + it "overwrites the selection as with any copied text", -> + editor.setSelectedBufferRange([[1, 2], [1, Infinity]]) + editor.pasteText() + expect(editor.lineTextForBufferRow(1)).toBe(" if (items.length <= 1) return items;") + expect(editor.lineTextForBufferRow(2)).toBe(" ") + expect(editor.lineTextForBufferRow(3)).toBe(" if (items.length <= 1) return items;") + expect(editor.getCursorBufferPosition()).toEqual([2, 2]) + + describe "when there is no selection", -> + it "pastes the line above the cursor and retains the cursor's column", -> + editor.pasteText() + expect(editor.lineTextForBufferRow(2)).toBe(" if (items.length <= 1) return items;") + expect(editor.lineTextForBufferRow(3)).toBe(" if (items.length <= 1) return items;") + expect(editor.getCursorBufferPosition()).toEqual([3, 13]) + describe ".indentSelectedRows()", -> describe "when nothing is selected", -> describe "when softTabs is enabled", -> diff --git a/src/selection.coffee b/src/selection.coffee index 70ab6ab0f..3f39df0d4 100644 --- a/src/selection.coffee +++ b/src/selection.coffee @@ -546,8 +546,8 @@ class Selection extends Model # Public: Copies the selection to the clipboard and then deletes it. # # * `maintainClipboard` {Boolean} (default: false) See {::copy} - cut: (maintainClipboard=false) -> - @copy(maintainClipboard) + cut: (maintainClipboard=false, fullLine=false) -> + @copy(maintainClipboard, fullLine) @delete() # Public: Copies the current selection to the clipboard. @@ -556,7 +556,7 @@ class Selection extends Model # is created to store each content copied to the clipboard. The clipboard # `text` still contains the concatenation of the clipboard with the # current selection. (default: false) - copy: (maintainClipboard=false) -> + copy: (maintainClipboard=false, fullLine=false) -> return if @isEmpty() selectionText = @editor.buffer.getTextInRange(@getBufferRange()) selectionIndentation = @editor.indentationForBufferRow(@getBufferRange().start.row) @@ -569,10 +569,17 @@ class Selection extends Model text: clipboardText, indentBasis: metadata.indentBasis, }] - metadata.selections.push(text: selectionText, indentBasis: selectionIndentation) + metadata.selections.push({ + text: selectionText, + indentBasis: selectionIndentation, + fullLine: fullLine + }) atom.clipboard.write([clipboardText, selectionText].join("\n"), metadata) else - atom.clipboard.write(selectionText, {indentBasis: selectionIndentation}) + atom.clipboard.write(selectionText, { + indentBasis: selectionIndentation, + fullLine: fullLine + }) # Public: Creates a fold containing the current selection. fold: -> diff --git a/src/text-editor.coffee b/src/text-editor.coffee index fd789aaa9..a43d5dd50 100644 --- a/src/text-editor.coffee +++ b/src/text-editor.coffee @@ -2472,18 +2472,21 @@ class TextEditor extends Model if selection.isEmpty() previousRange = selection.getBufferRange() selection.selectLine() - selection.copy(maintainClipboard) + selection.copy(maintainClipboard, true) selection.setBufferRange(previousRange) else - selection.copy(maintainClipboard) + selection.copy(maintainClipboard, false) maintainClipboard = true # Essential: For each selection, cut the selected text. cutSelectedText: -> maintainClipboard = false @mutateSelectedText (selection) -> - selection.selectLine() if selection.isEmpty() - selection.cut(maintainClipboard) + if selection.isEmpty() + selection.selectLine() + selection.cut(maintainClipboard, true) + else + selection.cut(maintainClipboard, false) maintainClipboard = true # Essential: For each selection, replace the selected text with the contents of @@ -2501,9 +2504,10 @@ class TextEditor extends Model @mutateSelectedText (selection, index) => if metadata.selections?.length is @getSelections().length - {text, indentBasis} = metadata.selections[index] + {text, indentBasis, fullLine} = metadata.selections[index] else - [text, indentBasis] = [clipboardText, metadata.indentBasis] + {indentBasis, fullLine} = metadata + text = clipboardText delete options.indentBasis {cursor} = selection @@ -2512,7 +2516,14 @@ class TextEditor extends Model if containsNewlines or !cursor.hasPrecedingCharactersOnLine() options.indentBasis ?= indentBasis - selection.insertText(text, options) + if fullLine and selection.isEmpty() + oldPosition = selection.getBufferRange().start + selection.setBufferRange([[oldPosition.row, 0], [oldPosition.row, 0]]) + selection.insertText(text, options) + newPosition = oldPosition.translate([1, 0]) + selection.setBufferRange([newPosition, newPosition]) + else + selection.insertText(text, options) # Public: For each selection, if the selection is empty, cut all characters # of the containing line following the cursor. Otherwise cut the selected