diff --git a/lib/ace/commands/default_commands.js b/lib/ace/commands/default_commands.js index 8b714411..f109b336 100644 --- a/lib/ace/commands/default_commands.js +++ b/lib/ace/commands/default_commands.js @@ -293,6 +293,18 @@ exports.commands = [{ // commands disabled in readOnly mode { + name: "cut", + exec: function(editor) { + var range = editor.getSelectionRange(); + editor._emit("cut", range); + + if (!editor.selection.isEmpty()) { + editor.session.remove(range); + editor.clearSelection(); + } + }, + multiSelectAction: "forEach" +}, { name: "removeline", bindKey: bindKey("Ctrl-D", "Command-D"), exec: function(editor) { editor.removeLines(); }, diff --git a/lib/ace/editor.js b/lib/ace/editor.js index 837355c1..d7a5966e 100644 --- a/lib/ace/editor.js +++ b/lib/ace/editor.js @@ -422,16 +422,7 @@ var Editor = function(renderer, session) { }; this.onCut = function() { - if (this.$readOnly) - return; - - var range = this.getSelectionRange(); - this._emit("cut", range); - - if (!this.selection.isEmpty()) { - this.session.remove(range); - this.clearSelection(); - } + this.commands.exec("cut", this); }; this.insert = function(text) { diff --git a/lib/ace/multi_select.js b/lib/ace/multi_select.js index 153d8a2b..716bc0fc 100644 --- a/lib/ace/multi_select.js +++ b/lib/ace/multi_select.js @@ -72,8 +72,10 @@ var EditSession = require("./edit_session").EditSession; this.rangeList = null; /** - * add a range to selection entering multiselect mode if necessary - */ + * Selection.addRange(Range) -> Void + * + * adds a range to selection entering multiselect mode if necessary + **/ this.addRange = function(range) { if (!this.inMultiSelectMode && this.rangeCount == 0) { var oldRange = this.toOrientedRange(); @@ -112,7 +114,13 @@ var EditSession = require("./edit_session").EditSession; range && this.fromOrientedRange(range); }; - + + /** + * Selection.addRange(pos) -> Range + * pos: {row, column} + * + * removes range containing pos (if exists) + **/ this.substractPoint = function(pos) { var removed = this.rangeList.substractPoint(pos); if (removed) { @@ -121,6 +129,11 @@ var EditSession = require("./edit_session").EditSession; } }; + /** + * Selection.mergeOverlappingRanges() -> Void + * + * merges overlapping ranges ensuring consistency after changes + **/ this.mergeOverlappingRanges = function() { var removed = this.rangeList.merge(); if (removed.length) @@ -195,6 +208,7 @@ var EditSession = require("./edit_session").EditSession; }; /** + * Selection.rectangularRangeBlock(screenCursor, screenAnchor, includeEmptyLines) -> [Range] * gets list of ranges composing rectangular block on the screen * @includeEmptyLines if true includes ranges inside the block which * are empty becuase of the clipping @@ -267,11 +281,22 @@ var EditSession = require("./edit_session").EditSession; // extend Editor var Editor = require("./editor").Editor; (function() { + /** + * Editor.updateSelectionMarkers() -> Void + * + * updates cursor and marker layers + **/ this.updateSelectionMarkers = function() { this.renderer.updateCursor(); this.renderer.updateBackMarkers(); }; + /** + * Editor.addSelectionMarker(orientedRange) -> Range + * - orientedRange: range with cursor + * + * adds selection and cursor + **/ this.addSelectionMarker = function(orientedRange) { if (!orientedRange.cursor) orientedRange.cursor = orientedRange.end; @@ -302,11 +327,13 @@ var Editor = require("./editor").Editor; this.renderer.updateCursor(); this.renderer.updateBackMarkers(); }; + this.$onRemoveRange = function(e) { this.removeSelectionMarkers(e.ranges); this.renderer.updateCursor(); this.renderer.updateBackMarkers(); }; + this.$onMultiSelect = function(e) { if (this.inMultiSelectMode) return; @@ -319,6 +346,7 @@ var Editor = require("./editor").Editor; this.renderer.updateCursor(); this.renderer.updateBackMarkers(); }; + this.$onSingleSelect = function(e) { if (this.session.multiSelect.inVirtualMode) return; @@ -350,7 +378,13 @@ var Editor = require("./editor").Editor; e.preventDefault(); }; - + /** + * Editor.forEachSelection(cmd, args) -> Void + * - cmd: command to execute + * - args: arguments to the command + * + * executes command for each selection range + **/ this.forEachSelection = function(cmd, args) { if (this.inVirtualSelectionMode) return; @@ -380,14 +414,18 @@ var Editor = require("./editor").Editor; this.onCursorChange(); this.onSelectionChange(); }; - + + /** + * Editor.exitMultiSelectMode() -> Void + * + * removes all selections except the last added one. + **/ this.exitMultiSelectMode = function() { if (this.inVirtualSelectionMode) return; this.multiSelect.toSingleRange(); }; - // todo route copy/cut/paste through commandmanager this.getCopyText = function() { var text = ""; if (this.inMultiSelectMode) { @@ -404,26 +442,15 @@ var Editor = require("./editor").Editor; return text; }; - this.onCut = function() { - var cmd = { - name: "cut", - exec: function(editor) { - var range = editor.getSelectionRange(); - editor._emit("cut", range); - - if (!editor.selection.isEmpty()) { - editor.session.remove(range); - editor.clearSelection(); - } - }, - readonly: true, - multiSelectAction: "forEach" - }; - this.commands.exec(cmd, this); - }; // commands - + /** + * Editor.selectMoreLines(dir, skip) -> Void + * - dir: -1 up, 1 down + * - skip: remove active selection range if true + * + * adds cursor above or bellow active cursor + **/ this.selectMoreLines = function(dir, skip) { var range = this.selection.toOrientedRange(); var isBackwards = range.cursor == range.end; @@ -462,12 +489,18 @@ var Editor = require("./editor").Editor; this.selection.substractPoint(toRemove); }; + /** + * Editor.transposeSelections(dir) -> Void + * - dir: direction to rotate selections + * + * contents + * empty ranges are expanded to word + **/ this.transposeSelections = function(dir) { var session = this.session; var sel = session.multiSelect; var all = sel.ranges; - var words = []; for (var i = all.length; i--; ) { var range = all[i]; if (range.isEmpty()) { @@ -477,8 +510,13 @@ var Editor = require("./editor").Editor; range.end.row = tmp.end.row; range.end.column = tmp.end.column; } - - words.unshift(this.session.getTextRange(range)); + } + sel.mergeOverlappingRanges(); + + var words = []; + for (var i = all.length; i--; ) { + var range = all[i]; + words.unshift(session.getTextRange(range)); } if (dir < 0) @@ -495,6 +533,14 @@ var Editor = require("./editor").Editor; } } + /** + * Editor.selectMore(dir, skip) -> Void + * - dir: 1 next, -1 previous + * - skip: remove active selection range if true + * + * finds next occurence of text in active selection + * and adds it to the selections + **/ this.selectMore = function (dir, skip) { var session = this.session; var sel = session.multiSelect; @@ -560,7 +606,12 @@ exports.onSessionChange = function(e) { } }; -// adds multicursor support to editor instance +/** + * MultiSelect(editor) -> Void + * + * adds multiple selection support to the editor + * (note: should be called only once for each editor instance) + **/ function MultiSelect(editor) { editor.$onAddRange = editor.$onAddRange.bind(editor); editor.$onRemoveRange = editor.$onRemoveRange.bind(editor);