Bug 924996 - Implement keyboard shortcut to move selected lines in source editor. r=anton
authorGabriel Luong <gabriel.luong@gmail.com>
Mon, 25 Nov 2013 19:06:42 -0800
changeset 157500 ddcfbf433ae4d2afc092944457b6b31985c85c60
parent 157499 f0cc82e94cceb088b2849968b08707dd5f5a4ca3
child 157501 33e652387cd5f8a301f7226b27fef6a8c8044313
push id25714
push usercbook@mozilla.com
push dateTue, 26 Nov 2013 11:39:03 +0000
treeherdermozilla-central@4a8c40940659 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersanton
bugs924996
milestone28.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 924996 - Implement keyboard shortcut to move selected lines in source editor. r=anton
browser/devtools/sourceeditor/editor.js
browser/devtools/sourceeditor/test/browser.ini
browser/devtools/sourceeditor/test/browser_editor_movelines.js
browser/locales/en-US/chrome/browser/devtools/sourceeditor.properties
--- a/browser/devtools/sourceeditor/editor.js
+++ b/browser/devtools/sourceeditor/editor.js
@@ -132,16 +132,18 @@ function Editor(config) {
     indentWithTabs:    useTabs,
     styleActiveLine:   true,
     autoCloseBrackets: true,
     theme:             "mozilla"
   };
 
   // Additional shortcuts.
   this.config.extraKeys[Editor.keyFor("jumpToLine")] = (cm) => this.jumpToLine(cm);
+  this.config.extraKeys[Editor.keyFor("moveLineUp")] = (cm) => this.moveLineUp();
+  this.config.extraKeys[Editor.keyFor("moveLineDown")] = (cm) => this.moveLineDown();
   this.config.extraKeys[Editor.keyFor("toggleComment")] = "toggleComment";
 
   // Disable ctrl-[ and ctrl-] because toolbox uses those shortcuts.
   this.config.extraKeys[Editor.keyFor("indentLess")] = false;
   this.config.extraKeys[Editor.keyFor("indentMore")] = false;
 
   // Overwrite default config with user-provided, if needed.
   Object.keys(config).forEach((k) => {
@@ -633,16 +635,75 @@ Editor.prototype = {
 
     div.appendChild(txt);
     div.appendChild(inp);
 
     this.openDialog(div, (line) => this.setCursor({ line: line - 1, ch: 0 }));
   },
 
   /**
+   * Moves the content of the current line or the lines selected up a line.
+   */
+  moveLineUp: function () {
+    let cm = editors.get(this);
+    let start = cm.getCursor("start");
+    let end = cm.getCursor("end");
+
+    if (start.line === 0)
+      return;
+
+    // Get the text in the lines selected or the current line of the cursor
+    // and append the text of the previous line.
+    let value;
+    if (start.line !== end.line) {
+      value = cm.getRange({ line: start.line, ch: 0 },
+        { line: end.line, ch: cm.getLine(end.line).length }) + "\n";
+    } else {
+      value = cm.getLine(start.line) + "\n";
+    }
+    value += cm.getLine(start.line - 1);
+
+    // Replace the previous line and the currently selected lines with the new
+    // value and maintain the selection of the text.
+    cm.replaceRange(value, { line: start.line - 1, ch: 0 },
+      { line: end.line, ch: cm.getLine(end.line).length });
+    cm.setSelection({ line: start.line - 1, ch: start.ch },
+      { line: end.line - 1, ch: end.ch });
+  },
+
+  /**
+   * Moves the content of the current line or the lines selected down a line.
+   */
+  moveLineDown: function () {
+    let cm = editors.get(this);
+    let start = cm.getCursor("start");
+    let end = cm.getCursor("end");
+
+    if (end.line + 1 === cm.lineCount())
+      return;
+
+    // Get the text of next line and append the text in the lines selected
+    // or the current line of the cursor.
+    let value = cm.getLine(end.line + 1) + "\n";
+    if (start.line !== end.line) {
+      value += cm.getRange({ line: start.line, ch: 0 },
+        { line: end.line, ch: cm.getLine(end.line).length });
+    } else {
+      value += cm.getLine(start.line);
+    }
+
+    // Replace the currently selected lines and the next line with the new
+    // value and maintain the selection of the text.
+    cm.replaceRange(value, { line: start.line, ch: 0 },
+      { line: end.line + 1, ch: cm.getLine(end.line + 1).length});
+    cm.setSelection({ line: start.line + 1, ch: start.ch },
+      { line: end.line + 1, ch: end.ch });
+  },
+
+  /**
    * Extends an instance of the Editor object with additional
    * functions. Each function will be called with context as
    * the first argument. Context is a {ed, cm} object where
    * 'ed' is an instance of the Editor object and 'cm' is an
    * instance of the CodeMirror object. Example:
    *
    * function hello(ctx, name) {
    *   let { cm, ed } = ctx;
--- a/browser/devtools/sourceeditor/test/browser.ini
+++ b/browser/devtools/sourceeditor/test/browser.ini
@@ -8,10 +8,11 @@ support-files =
   cm_test.js
   codemirror.html
   head.js
 
 [browser_editor_basic.js]
 [browser_editor_cursor.js]
 [browser_editor_history.js]
 [browser_editor_markers.js]
+[browser_editor_movelines.js]
 [browser_codemirror.js]
 [browser_sourceeditor_initialization.js]
new file mode 100644
--- /dev/null
+++ b/browser/devtools/sourceeditor/test/browser_editor_movelines.js
@@ -0,0 +1,62 @@
+/* vim: set ts=2 et sw=2 tw=80: */
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+function test() {
+  waitForExplicitFinish();
+  setup((ed, win) => {
+    var simpleProg = "function foo() {\n  let i = 1;\n  let j = 2;\n  return bar;\n}";
+    ed.setText(simpleProg);
+
+    // Move first line up
+    ed.setCursor({ line: 0, ch: 0 });
+    ed.moveLineUp();
+    is(ed.getText(0), "function foo() {", "getText(num)");
+    ch(ed.getCursor(), { line: 0, ch: 0 }, "getCursor");
+
+    // Move last line down
+    ed.setCursor({ line: 4, ch: 0 });
+    ed.moveLineDown();
+    is(ed.getText(4), "}", "getText(num)");
+    ch(ed.getCursor(), { line: 4, ch: 0 }, "getCursor");
+
+    // Move line 2 up
+    ed.setCursor({ line: 1, ch: 5});
+    ed.moveLineUp();
+    is(ed.getText(0), "  let i = 1;", "getText(num)");
+    is(ed.getText(1), "function foo() {", "getText(num)");
+    ch(ed.getCursor(), { line: 0, ch: 5 }, "getCursor");
+
+    // Undo previous move by moving line 1 down
+    ed.moveLineDown();
+    is(ed.getText(0), "function foo() {", "getText(num)");
+    is(ed.getText(1), "  let i = 1;", "getText(num)");
+    ch(ed.getCursor(), { line: 1, ch: 5 }, "getCursor");
+
+    // Move line 2 and 3 up
+    ed.setSelection({ line: 1, ch: 0 }, { line: 2, ch: 0 });
+    ed.moveLineUp();
+    is(ed.getText(0), "  let i = 1;", "getText(num)");
+    is(ed.getText(1), "  let j = 2;", "getText(num)");
+    is(ed.getText(2), "function foo() {", "getText(num)");
+    ch(ed.getCursor("start"), { line: 0, ch: 0 }, "getCursor(string)");
+    ch(ed.getCursor("end"), { line: 1, ch: 0 }, "getCursor(string)");
+
+    // Move line 1 to 3 down twice
+    ed.dropSelection();
+    ed.setSelection({ line: 0, ch: 7 }, { line: 2, ch: 5 });
+    ed.moveLineDown();
+    ed.moveLineDown();
+    is(ed.getText(0), "  return bar;", "getText(num)");
+    is(ed.getText(1), "}", "getText(num)");
+    is(ed.getText(2), "  let i = 1;", "getText(num)");
+    is(ed.getText(3), "  let j = 2;", "getText(num)");
+    is(ed.getText(4), "function foo() {", "getText(num)");
+    ch(ed.getCursor("start"), { line: 2, ch: 7 }, "getCursor(string)");
+    ch(ed.getCursor("end"), { line: 4, ch: 5 }, "getCursor(string)");
+
+    teardown(ed, win);
+  });
+}
--- a/browser/locales/en-US/chrome/browser/devtools/sourceeditor.properties
+++ b/browser/locales/en-US/chrome/browser/devtools/sourceeditor.properties
@@ -68,9 +68,19 @@ toggleComment.commandkey=/
 indentLess.commandkey=[
 
 # LOCALIZATION NOTE  (toolboxPrevTool.commandkey): This the key to use in
 # conjunction with accel (Command on Mac or Ctrl on other platforms) to increase
 # indentation level in CodeMirror. However, its default value also used by
 # the Toolbox to switch between tools
 #
 # DO NOT translate this key without proper synchronization with toolbox.dtd.
-indentMore.commandkey=]
\ No newline at end of file
+indentMore.commandkey=]
+
+# LOCALIZATION NOTE  (moveLineUp.commandkey): This the key to use in
+# conjunction with accel (Command on Mac or Ctrl on other platforms) to move
+# the selected lines up.
+moveLineUp.commandkey=Alt-Up
+
+# LOCALIZATION NOTE  (moveLineDown.commandkey): This the key to use in
+# conjunction with accel (Command on Mac or Ctrl on other platforms) to move
+# the selected lines down.
+moveLineDown.commandkey=Alt-Down