-
Notifications
You must be signed in to change notification settings - Fork 7.7k
Product Backlog - Move Line Up/Down on Key #1282
Changes from 4 commits
b86ec3f
bed03b5
53ed4f0
4833b4c
df6a3b7
45034aa
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -38,6 +38,12 @@ define(function (require, exports, module) { | |
EditorManager = require("editor/EditorManager"); | ||
|
||
|
||
/** | ||
* List of constants | ||
*/ | ||
var DIRECTION_UP = -1; | ||
var DIRECTION_DOWN = +1; | ||
|
||
/** | ||
* Add or remove line-comment tokens to all the lines in the selected range, preserving selection | ||
* and cursor position. Applies to currently focused Editor. | ||
|
@@ -152,6 +158,85 @@ define(function (require, exports, module) { | |
var selectedText = doc.getRange(sel.start, sel.end) + delimiter; | ||
doc.replaceRange(selectedText, sel.start); | ||
} | ||
|
||
/** | ||
* Moves the selected text, or current line if no selection. The cursor/selection | ||
* moves with the line/lines. | ||
* @param {Editor} editor - target editor | ||
* @param {Number} direction - direction of the move (-1,+1) => (Up,Down) | ||
*/ | ||
function moveLine(editor, direction) { | ||
editor = editor || EditorManager.getFocusedEditor(); | ||
if (!editor) { | ||
return; | ||
} | ||
|
||
var doc = editor.document, | ||
sel = editor.getSelection(), | ||
originalSel = editor.getSelection(), | ||
hasSelection = (sel.start.line !== sel.end.line) || (sel.start.ch !== sel.end.ch); | ||
|
||
sel.start.ch = 0; | ||
// The end of the selection becomes the start of the next line, if it isn't already | ||
if (!hasSelection || sel.end.ch !== 0) { | ||
sel.end = {line: sel.end.line + 1, ch: 0}; | ||
} | ||
|
||
// Make the move | ||
switch (direction) { | ||
case DIRECTION_UP: | ||
if (sel.start.line !== 0) { | ||
var prevText = doc.getRange({ line: sel.start.line - 1, ch: 0 }, sel.start); | ||
|
||
if (sel.end.line === editor.lineCount()) { | ||
prevText = "\n" + prevText.substring(0, prevText.length - 1); | ||
} | ||
|
||
doc.replaceRange("", { line: sel.start.line - 1, ch: 0 }, sel.start); | ||
doc.replaceRange(prevText, { line: sel.end.line - 1, ch: 0 }); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should wrap this in a doc.batchOperation() call. In this case, include the setSelection() code within that block too. Sorry, I should have caught this in the original code review. |
||
|
||
// fixes selection problems | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It'd be good to be more specific about the problem. Something like "make sure CodeMirror hasn't expanded the selection to include the line we inserted below." |
||
originalSel.start.line--; | ||
originalSel.end.line--; | ||
editor.setSelection(originalSel.start, originalSel.end); | ||
} | ||
break; | ||
case DIRECTION_DOWN: | ||
if (sel.end.line < editor.lineCount()) { | ||
var nextText = doc.getRange(sel.end, { line: sel.end.line + 1, ch: 0 }); | ||
|
||
var deletionStart = sel.end; | ||
if (sel.end.line === editor.lineCount() - 1) { | ||
nextText += "\n"; | ||
|
||
var lastSelectedLine = doc.getLine(sel.end.line - 1); | ||
if (lastSelectedLine !== undefined) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there any case where lastSelectedLine would be undefined? It seems like that can only happen if the line where the cursor/selection lies doesn't exist... which presumably is impossible. |
||
deletionStart = { line: sel.end.line - 1, ch: lastSelectedLine.length }; | ||
} | ||
} | ||
|
||
doc.replaceRange("", deletionStart, { line: sel.end.line + 1, ch: 0 }); | ||
doc.replaceRange(nextText, { line: sel.start.line, ch: 0 }); | ||
} | ||
break; | ||
} | ||
} | ||
|
||
/** | ||
* Moves the selected text, or current line if no selection, one line up. The cursor/selection | ||
* moves with the line/lines. | ||
*/ | ||
function moveLineUp(editor) { | ||
moveLine(editor, DIRECTION_UP); | ||
} | ||
|
||
/** | ||
* Moves the selected text, or current line if no selection, one line down. The cursor/selection | ||
* moves with the line/lines. | ||
*/ | ||
function moveLineDown(editor) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The code here is very close to moveLineUp(). Is there a clean way to consolidate these? For the parts that just vary +1 vs. -1, you could pass in a "direction" argument. Then the only real diffs would be the corner case checks. |
||
moveLine(editor, DIRECTION_DOWN); | ||
} | ||
|
||
/** | ||
* Indent a line of text if no selection. Otherwise, indent all lines in selection. | ||
|
@@ -182,4 +267,6 @@ define(function (require, exports, module) { | |
CommandManager.register(Strings.CMD_UNINDENT, Commands.EDIT_UNINDENT, unidentText); | ||
CommandManager.register(Strings.CMD_COMMENT, Commands.EDIT_LINE_COMMENT, lineComment); | ||
CommandManager.register(Strings.CMD_DUPLICATE, Commands.EDIT_DUPLICATE, duplicateText); | ||
CommandManager.register(Strings.CMD_LINE_UP, Commands.EDIT_LINE_UP, moveLineUp); | ||
CommandManager.register(Strings.CMD_LINE_DOWN, Commands.EDIT_LINE_DOWN, moveLineDown); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The standard on Windows seems to be Ctrl+Shift+up/down (see Sublime, Notepad++, and IntelliJ/WebStorm). The only odd one out I could find is Eclipse, which uses Alt+up/down. On all of those editors, Ctrl+up/down instead scrolls the view by one line (without making any edits).
On Mac, most editors seem to lack this feature. Eclipse uses Alt+up/down, Sublime uses Cmd+Ctrl+up/down (edit: TextMate and Espresso also use this shortcut), and IntelliJ/WebStorm uses Cmd+Shift+up/down. I'd be inclined to go with Cmd+Shift since it's more consistent with the Windows shortcut (in fact Brackets will automatically convert Ctrl<->Cmd, so you wouldn't even have to declare two shortcuts in that case).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Re the menus: move line up/down feels more related to Duplicate. In fact, now that this menu section is getting longer it feels weird to have Comment/Uncomment grouped in with more generic editing commands. How about reordering it so the menu looks like this?
...
Duplicate
Move Line(s) Up
Move Line(s) Down
---divider---
Comment/Uncomment Lines
---divider---
Use Tab Characters
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I think the note in the backlog got this shortcut confused with the "scroll 1 line" feature that most editors have. Let's use Ctrl+Shift+up/down on Windows.
On Mac, I found that more of them support this than I thought. Sublime, TextMate and Espresso all use Cmd+Ctrl+up/down, so that seems like the best shortcut to use.