From ec9ef6c84397b792c114f530dfa6d79e5a06ecca Mon Sep 17 00:00:00 2001 From: nightwing Date: Sun, 25 Mar 2012 12:15:33 +0500 Subject: [PATCH] fix handling of desiredcolumn --- lib/ace/multi_cursor.js | 704 +++++++++++++++++++--------------------- lib/ace/selection.js | 40 ++- 2 files changed, 363 insertions(+), 381 deletions(-) diff --git a/lib/ace/multi_cursor.js b/lib/ace/multi_cursor.js index db286363..9b45ee70 100644 --- a/lib/ace/multi_cursor.js +++ b/lib/ace/multi_cursor.js @@ -44,221 +44,178 @@ var Selection = require("./selection").Selection; var Range = require("./range").Range; var event = require("./lib/event"); -function VirtualSelection(selection) { - this.session = selection.session; - this.doc = selection.doc; - - this.clearSelection(); - this.selectionLead = this.doc.createAnchor(0, 0); - this.selectionAnchor = this.doc.createAnchor(0, 0); - - /*var _self = this; - this.selectionLead.on("change", function(e) { - _self._emit("changeCursor"); - if (!_self.$isEmpty) - _self._emit("changeSelection"); - if (!_self.$preventUpdateDesiredColumnOnChange && e.old.column != e.value.column) - _self.$updateDesiredColumn(); - }); - - this.selectionAnchor.on("change", function() { - if (!_self.$isEmpty) - _self._emit("changeSelection"); - }); */ - - this.detach = function() { - this.selectionLead.detach(); - this.selectionAnchor.detach(); - this.session = this.doc = null; - } - - this.fromRange = function(r) { - this.setSelectionRange(r, r.cursor == r.start) - } - - this.toRange = function(r) { - var r1 = this.getRange() - - r.start.column = r1.start.column - r.start.row = r1.start.row - r.end.column = r1.end.column - r.end.row = r1.end.row - - r.cursor = this.isBackwards() ? r.start : r.end; - } -} -VirtualSelection.prototype = Selection.prototype; - function forEachSelection(editor, cmd, args) { - if (editor.session.multiSelection.inVirtualMode) - return - var session = editor.session - var selection = editor.selection - var rangeList = selection.rangeList - - var reg = selection._eventRegistry; - selection._eventRegistry = {}; - - var sh = new VirtualSelection(selection) - editor.session.multiSelection.inVirtualMode = true - for (var i = rangeList.ranges.length; i--;) { - sh.fromRange(rangeList.ranges[i]) - editor.selection = session.selection = sh - cmd.exec(editor, args || {}) - - sh.toRange(rangeList.ranges[i]) - } - sh.detach(); - - rangeList.merge() - editor.selection = session.selection = selection; - editor.session.multiSelection.inVirtualMode = false; - selection._eventRegistry = reg; - - selection.setSelectionRange(selection.rangeList.all[0]) - editor.renderer.updateCursor(); - editor.renderer.updateBackMarkers(); - - if (selection.rangeCount == 1 && editor.inMultiSelectMode) - exitMultiSelectMode(editor) + if (editor.session.multiSelection.inVirtualMode) + return + var session = editor.session + var selection = editor.selection + var rangeList = selection.rangeList + + var reg = selection._eventRegistry; + selection._eventRegistry = {}; + + var sh = new Selection(session); + editor.session.multiSelection.inVirtualMode = true; + for (var i = rangeList.ranges.length; i--;) { + sh.fromOrientedRange(rangeList.ranges[i]) + editor.selection = session.selection = sh + cmd.exec(editor, args || {}) + sh.toOrientedRange(rangeList.ranges[i]) + } + sh.detach(); + + rangeList.merge() + editor.selection = session.selection = selection; + editor.session.multiSelection.inVirtualMode = false; + selection._eventRegistry = reg; + + selection.fromOrientedRange(selection.rangeList.all[0]) + editor.renderer.updateCursor(); + editor.renderer.updateBackMarkers(); + + if (selection.rangeCount == 1 && editor.inMultiSelectMode) + exitMultiSelectMode(editor) } function exec(command, editor, args) { - if (typeof command === 'string') - command = this.commands[command]; + if (typeof command === 'string') + command = this.commands[command]; - if (!command) - return false; + if (!command) + return false; - if (editor && editor.$readOnly && !command.readOnly) - return false; + if (editor && editor.$readOnly && !command.readOnly) + return false; - if (/^(remove|insert|select|go|jumptomatching|del|backspace)/.test(command.name)) { - forEachSelection(editor, command, args) - }else - command.exec(editor, args || {}); - return true; + if (/^(remove|insert|select|go|jumptomatching|del|backspace|to(?:upp|low)ercase)/.test(command.name)) { + forEachSelection(editor, command, args) + }else + command.exec(editor, args || {}); + return true; }; function enterMultiSelectMode(editor) { - if (editor.inMultiSelectMode) - return - editor.inMultiSelectMode = true - editor.setStyle("multiselect") - editor.keyBinding.addKeyboardHandler(exports.keyboardHandler); - editor.commands.__exec = editor.commands.exec - editor.commands.exec = exec - - editor.session.$undoSelect = false - editor.selection.rangeList.attach(editor.session); + if (editor.inMultiSelectMode) + return + editor.inMultiSelectMode = true + editor.setStyle("multiselect") + editor.keyBinding.addKeyboardHandler(exports.keyboardHandler); + editor.commands.__exec = editor.commands.exec + editor.commands.exec = exec + + editor.session.$undoSelect = false + editor.selection.rangeList.attach(editor.session); } function exitMultiSelectMode(editor) { - if (editor.session.multiSelection.inVirtualMode) - return - editor.inMultiSelectMode = false; - editor.selection.secondarySelections = []; - editor.unsetStyle("multiselect"); - editor.selection.rangeList.removeAll(); - editor.keyBinding.removeKeyboardHandler(exports.keyboardHandler); - - editor.commands.exec = editor.commands.__exec; - editor.renderer.updateCursor(); - editor.renderer.updateBackMarkers(); - - editor.session.$undoSelect = true - - editor.selection.rangeList.detach(editor.session); + if (editor.session.multiSelection.inVirtualMode) + return + editor.inMultiSelectMode = false; + editor.selection.secondarySelections = []; + editor.unsetStyle("multiselect"); + editor.selection.rangeList.removeAll(); + editor.keyBinding.removeKeyboardHandler(exports.keyboardHandler); + + editor.commands.exec = editor.commands.__exec; + editor.renderer.updateCursor(); + editor.renderer.updateBackMarkers(); + + editor.session.$undoSelect = true + + editor.selection.rangeList.detach(editor.session); } function initSession(session) { - if (session.selection.rangeList) - return - session.multiSelection = session.selection - - var rangeList = new RangeList; - - rangeList.all = []; - rangeList.on("add", function(e) { - rangeList.all.unshift(e.range) - }) - - rangeList.on("remove", function(e) { - var ranges = e.ranges - for (var i = ranges.length; i--; ) { - var index = rangeList.all.indexOf(ranges[i]); - rangeList.all.splice(index, 1); - } - }); - - session.selection.rangeList = rangeList; - session.selection.cursor = session.selection.selectionLead; - session.selection.secondarySelections = []; - session.selection.getAllRanges = function() { - return this.rangeList.ranges.concat(this.secondarySelections) - }; - session.selection.rangeCount = 1; + if (session.selection.rangeList) + return + session.multiSelection = session.selection + + var rangeList = new RangeList; + + rangeList.all = []; + rangeList.on("add", function(e) { + rangeList.all.unshift(e.range) + }) + + rangeList.on("remove", function(e) { + var ranges = e.ranges + for (var i = ranges.length; i--; ) { + var index = rangeList.all.indexOf(ranges[i]); + rangeList.all.splice(index, 1); + } + }); + + session.selection.rangeList = rangeList; + session.selection.cursor = session.selection.selectionLead; + session.selection.secondarySelections = []; + session.selection.getAllRanges = function() { + return this.rangeList.ranges.concat(this.secondarySelections) + }; + session.selection.rangeCount = 1; } var addSelectionRange = function(editor, orientedRange) { - if (!editor.inMultiSelectMode) - enterMultiSelectMode(editor) - - if (!orientedRange.cursor) - orientedRange.cursor = orientedRange.end + if (!editor.inMultiSelectMode) + enterMultiSelectMode(editor) - var style = editor.getSelectionStyle(); - orientedRange.marker = editor.session.addMarker(orientedRange, "ace_selection", style); + if (!orientedRange.cursor) + orientedRange.cursor = orientedRange.end - // use this to not conflict with virtualSelections added by forEachSelection - var selection = editor.session.multiSelection; - selection.rangeList.add(orientedRange); - selection.rangeCount = selection.rangeList.all.length + selection.secondarySelections.length; - - selection.setSelectionRange(orientedRange, orientedRange.cursor == orientedRange.start) - editor.renderer.updateCursor(); - editor.renderer.updateBackMarkers(); + var style = editor.getSelectionStyle(); + orientedRange.marker = editor.session.addMarker(orientedRange, "ace_selection", style); + + // use this to not conflict with virtualSelections added by forEachSelection + var selection = editor.session.multiSelection; + selection.rangeList.add(orientedRange); + selection.rangeCount = selection.rangeList.all.length + selection.secondarySelections.length; + + selection.fromOrientedRange(orientedRange) + editor.renderer.updateCursor(); + editor.renderer.updateBackMarkers(); }; function addCursorV(editor, dir){ - var range = editor.selection.getRange() - var isBackwards = editor.selection.isBackwards() - range.cursor = isBackwards ? range.start : range.end; - - var screenLead = editor.session.documentToScreenPosition(range.cursor); - var lead = editor.session.screenToDocumentPosition(screenLead.row + dir, screenLead.column); - - if (!range.isEmpty()) { - var screenAnchor = editor.session.documentToScreenPosition(isBackwards ? range.end : range.start); - var anchor = editor.session.screenToDocumentPosition(screenAnchor.row + dir, screenAnchor.column); - } else { - var anchor = lead - } - - if (isBackwards) { - var newRange = Range.fromPoints(lead, anchor) - newRange.cursor = newRange.start - } else { - var newRange = Range.fromPoints(anchor, lead) - newRange.cursor = newRange.end - } - if (!editor.inMultiSelectMode) { - addSelectionRange(editor, range) - } else { - var allRanges = editor.selection.rangeList.ranges - // remove range if at end - if (range.isEequal(allRanges[dir == 1 ? 0 : allRanges.length - 1])) - var toRemove = range.cursor - } - addSelectionRange(editor, newRange) - if (toRemove) - editor.selection.rangeList.substractPoint(toRemove) + var range = editor.selection.getRange() + var isBackwards = editor.selection.isBackwards() + range.cursor = isBackwards ? range.start : range.end; + + var screenLead = editor.session.documentToScreenPosition(range.cursor); + screenLead.column = editor.selection.$desiredColumn; + + var lead = editor.session.screenToDocumentPosition(screenLead.row + dir, screenLead.column); + + if (!range.isEmpty()) { + var screenAnchor = editor.session.documentToScreenPosition(isBackwards ? range.end : range.start); + var anchor = editor.session.screenToDocumentPosition(screenAnchor.row + dir, screenAnchor.column); + } else { + var anchor = lead + } + + if (isBackwards) { + var newRange = Range.fromPoints(lead, anchor) + newRange.cursor = newRange.start + } else { + var newRange = Range.fromPoints(anchor, lead) + newRange.cursor = newRange.end + } + newRange.desiredColumn = editor.selection.$desiredColumn + if (!editor.inMultiSelectMode) { + addSelectionRange(editor, range) + } else { + var allRanges = editor.selection.rangeList.ranges + // remove range if at end + if (range.isEequal(allRanges[dir == 1 ? 0 : allRanges.length - 1])) + var toRemove = range.cursor + } + addSelectionRange(editor, newRange) + if (toRemove) + editor.selection.rangeList.substractPoint(toRemove) } // commands exports.defaultCommands = [{ name: "addCursorAbove", exec: function(editor) { - addCursorV(editor, -1) + addCursorV(editor, -1) }, bindKey: { win: "Alt-Shift-Up", @@ -267,7 +224,7 @@ exports.defaultCommands = [{ }, { name: "addCursorBelow", exec: function(editor) { - addCursorV(editor, 1) + addCursorV(editor, 1) }, bindKey: { win: "Alt-Shift-Down", @@ -279,7 +236,7 @@ exports.multiEditCommands = [{ name: "singleSelection", bindKey: "esc", exec: function(editor) { - console.log(editor) + console.log(editor) exitMultiSelectMode(editor) }, }]; @@ -289,208 +246,205 @@ exports.keyboardHandler = new HashHandler(exports.multiEditCommands); // mouse function isSamePoint(p1, p2) { - return p1.row == p2.row && p1.column == p2.column + return p1.row == p2.row && p1.column == p2.column } function onMouseDown(e) { - var ev = e.domEvent; - var alt = ev.altKey; - var shift = ev.shiftKey; - var ctrl = ev.ctrlKey; - var button = e.getButton(); - - if (!ctrl && !alt) { - if (e.editor.selection.rangeCount > 1) { - if (button == 0) { - exitMultiSelectMode(e.editor) - } else if (button == 2) { - var editor = e.editor; - var selectionEmpty = editor.selection.isEmpty() - editor.textInput.onContextMenu({x: e.clientX, y: e.clientY}, selectionEmpty); - event.capture(editor.container, function(){}, editor.textInput.onContextMenuClose); - e.stop(); - } - } - return; - } - - var editor = e.editor; - var selection = editor.selection; - var isMultiSelect = selection.rangeCount > 1 - var pos = e.getDocumentPosition(); - var rangeList = selection.rangeList; - var cursor = selection.getCursor() - var inSelection = e.inSelection() || (selection.isEmpty() && isSamePoint(pos, cursor)); - - if (ctrl && !shift && !alt && button == 0) { - if (!isMultiSelect && inSelection) - return // dragging - - if (!isMultiSelect) { - var tmpSel = selection.getRange(); - tmpSel.cursor = selection.isBackwards() ? tmpSel.start : tmpSel.end; - addSelectionRange(editor, tmpSel) - } - if (inSelection) - selection.clearSelection(); - - selection.secondarySelections.push(selection) - selection.rangeCount++ - var oldRange = rangeList.substractPoint(pos) - - event.capture(editor.container, function(){}, function() { - var i = selection.secondarySelections.indexOf(selection); - if (i != -1) { - selection.rangeCount-- - selection.secondarySelections.splice(i, 1); - } - - var tmpSel = selection.getRange(); - tmpSel.cursor = selection.isBackwards() ? tmpSel.start : tmpSel.end; + var ev = e.domEvent; + var alt = ev.altKey; + var shift = ev.shiftKey; + var ctrl = ev.ctrlKey; + var button = e.getButton(); - if (oldRange && oldRange.isEmpty() && tmpSel.isEequal(oldRange)) { - var range = selection.rangeList.all[0] - editor.selection.rangeList._emit("remove", {ranges: []}) - selection.setSelectionRange(range, range.cursor == range.start) - selection._emit("changeSelection"); - selection._emit("changeCursor"); - return; - } + if (!ctrl && !alt) { + if (e.editor.selection.rangeCount > 1) { + if (button == 0) { + exitMultiSelectMode(e.editor) + } else if (button == 2) { + var editor = e.editor; + var selectionEmpty = editor.selection.isEmpty() + editor.textInput.onContextMenu({x: e.clientX, y: e.clientY}, selectionEmpty); + event.capture(editor.container, function(){}, editor.textInput.onContextMenuClose); + e.stop(); + } + } + return; + } - addSelectionRange(editor, tmpSel) - }); + var editor = e.editor; + var selection = editor.selection; + var isMultiSelect = selection.rangeCount > 1 + var pos = e.getDocumentPosition(); + var rangeList = selection.rangeList; + var cursor = selection.getCursor() + var inSelection = e.inSelection() || (selection.isEmpty() && isSamePoint(pos, cursor)); - //e.stop() - } else if (!shift && alt && button == 0) { - e.stop() - var mouseX = e.pageX, mouseY = e.pageY; - var onMouseSelection = function(e) { - mouseX = event.getDocumentX(e); - mouseY = event.getDocumentY(e); - }; + if (ctrl && !shift && !alt && button == 0) { + if (!isMultiSelect && inSelection) + return // dragging - selection.moveCursorToPosition(pos); - selection.clearSelection(); - if (!isMultiSelect) { - enterMultiSelectMode(editor) - selection.rangeCount = Infinity - } - - - var rectSel = [] - selection.secondarySelections = rectSel - - var session = editor.session - var style = editor.getSelectionStyle(); - function addMarker(range) { - range.marker = session.addMarker(range, "ace_selection", style); - } - function removeMarker(range) { - session.removeMarker(range.marker); - } - - - - var onMouseSelectionEnd = function(e) { - clearInterval(timerId); - rectSel.forEach(removeMarker) - selection.secondarySelections = []; - for (var i = rectSel.length; i--; ) - addSelectionRange(editor, rectSel[i]) - - if (selection.rangeCount == Infinity) { - selection.rangeCount = selection.rangeList.all.length + selection.secondarySelections.length; - - if (selection.rangeCount <= 1) - exitMultiSelectMode(editor) - } - }; - - var anchor = selection.getCursor(); - var screenAnchor = session.documentToScreenPosition(anchor); - var screenCursor = screenAnchor - var screenLength = session.getScreenLength() - 1 - - var onSelectionInterval = function() { - var newCursor = editor.renderer.pixelToScreenCoordinates(mouseX, mouseY); - if (isSamePoint(screenCursor, newCursor)) - return - rectSel.forEach(removeMarker) - rectSel.splice(0, rectSel.length) - screenCursor = newCursor - var xBackwards = screenCursor.column < screenAnchor.column - if (xBackwards) { - var startColumn = screenCursor.column - var endColumn = screenAnchor.column - } else { - var startColumn = screenAnchor.column - var endColumn = screenCursor.column - } - var yBackwards = screenCursor.row < screenAnchor.row - if (yBackwards) { - var startRow = screenCursor.row - var endRow = screenAnchor.row - } else { - var startRow = screenAnchor.row - var endRow = screenCursor.row - } - if (startColumn < 0) - startColumn = 0 - if (startRow < 0) - startRow = 0 - if (endRow > screenLength) - endRow = screenLength - - for (var row = startRow; row <= endRow; row++) { - var r = Range.fromPoints( - session.screenToDocumentPosition(row, startColumn), - session.screenToDocumentPosition(row, endColumn) - ) - r.cursor = xBackwards ? r.start : r.end - rectSel.push(r) - } - - rectSel.forEach(addMarker) - var lastIndex = yBackwards ? 0 : rectSel.length - 1 - selection.moveCursorToPosition(rectSel[lastIndex].cursor); - selection.clearSelection() - editor.renderer.scrollCursorIntoView(); - - editor.renderer.updateCursor(); - editor.renderer.updateBackMarkers(); - }; - - event.capture(editor.container, onMouseSelection, onMouseSelectionEnd); - var timerId = setInterval(onSelectionInterval, 20); + if (!isMultiSelect) { + addSelectionRange(editor, selection.toOrientedRange()) + } + if (inSelection) + selection.clearSelection(); - return e.preventDefault(); - } + selection.secondarySelections.push(selection) + selection.rangeCount++ + var oldRange = rangeList.substractPoint(pos) + + event.capture(editor.container, function(){}, function() { + var i = selection.secondarySelections.indexOf(selection); + if (i != -1) { + selection.rangeCount-- + selection.secondarySelections.splice(i, 1); + } + + var tmpSel = selection.toOrientedRange(); + + if (oldRange && oldRange.isEmpty() && tmpSel.isEequal(oldRange)) { + var range = selection.rangeList.all[0] + editor.selection.rangeList._emit("remove", {ranges: []}) + selection.setSelectionRange(range, range.cursor == range.start) + selection._emit("changeSelection"); + selection._emit("changeCursor"); + return; + } + + addSelectionRange(editor, tmpSel) + }); + + //e.stop() + } else if (!shift && alt && button == 0) { + e.stop() + var mouseX = e.pageX, mouseY = e.pageY; + var onMouseSelection = function(e) { + mouseX = event.getDocumentX(e); + mouseY = event.getDocumentY(e); + }; + + selection.moveCursorToPosition(pos); + selection.clearSelection(); + if (!isMultiSelect) { + enterMultiSelectMode(editor) + selection.rangeCount = Infinity + } + + + var rectSel = [] + selection.secondarySelections = rectSel + + var session = editor.session + var style = editor.getSelectionStyle(); + function addMarker(range) { + range.marker = session.addMarker(range, "ace_selection", style); + } + function removeMarker(range) { + session.removeMarker(range.marker); + } + + + + var onMouseSelectionEnd = function(e) { + clearInterval(timerId); + rectSel.forEach(removeMarker) + selection.secondarySelections = []; + for (var i = rectSel.length; i--; ) + addSelectionRange(editor, rectSel[i]) + + if (selection.rangeCount == Infinity) { + selection.rangeCount = selection.rangeList.all.length + selection.secondarySelections.length; + + if (selection.rangeCount <= 1) + exitMultiSelectMode(editor) + } + }; + + var anchor = selection.getCursor(); + var screenAnchor = session.documentToScreenPosition(anchor); + var screenCursor = screenAnchor + var screenLength = session.getScreenLength() - 1 + + var onSelectionInterval = function() { + var newCursor = editor.renderer.pixelToScreenCoordinates(mouseX, mouseY); + if (isSamePoint(screenCursor, newCursor)) + return + rectSel.forEach(removeMarker) + rectSel.splice(0, rectSel.length) + screenCursor = newCursor + var xBackwards = screenCursor.column < screenAnchor.column + if (xBackwards) { + var startColumn = screenCursor.column + var endColumn = screenAnchor.column + } else { + var startColumn = screenAnchor.column + var endColumn = screenCursor.column + } + var yBackwards = screenCursor.row < screenAnchor.row + if (yBackwards) { + var startRow = screenCursor.row + var endRow = screenAnchor.row + } else { + var startRow = screenAnchor.row + var endRow = screenCursor.row + } + if (startColumn < 0) + startColumn = 0 + if (startRow < 0) + startRow = 0 + if (endRow > screenLength) + endRow = screenLength + + for (var row = startRow; row <= endRow; row++) { + var r = Range.fromPoints( + session.screenToDocumentPosition(row, startColumn), + session.screenToDocumentPosition(row, endColumn) + ) + r.cursor = xBackwards ? r.start : r.end + rectSel.push(r) + } + + rectSel.forEach(addMarker) + var lastIndex = yBackwards ? 0 : rectSel.length - 1 + selection.moveCursorToPosition(rectSel[lastIndex].cursor); + selection.clearSelection() + editor.renderer.scrollCursorIntoView(); + + editor.renderer.updateCursor(); + editor.renderer.updateBackMarkers(); + }; + + event.capture(editor.container, onMouseSelection, onMouseSelectionEnd); + var timerId = setInterval(onSelectionInterval, 20); + + return e.preventDefault(); + } } - + function altSelect(ev) { - -} + +} // MultiCursor function MultiCursor(editor) { - initSession(editor.session); - editor.on("changeSession", function(e) { - initSession(e.session) - }.bind(editor)); + initSession(editor.session); + editor.on("changeSession", function(e) { + initSession(e.session) + }.bind(editor)); - editor.selection.rangeList.on("remove", function(e) { - var ranges = e.ranges; - for (var i = ranges.length; i--; ) { - var range = ranges[i]; - if (range.marker != null) - this.session.removeMarker(range.marker); + editor.selection.rangeList.on("remove", function(e) { + var ranges = e.ranges; + for (var i = ranges.length; i--; ) { + var range = ranges[i]; + if (range.marker != null) + this.session.removeMarker(range.marker); - this.rangeCount --; - } + this.rangeCount --; + } + + if (this.rangeCount == 1 && editor.inMultiSelectMode) + exitMultiSelectMode(editor) + }.bind(editor.selection)); - if (this.rangeCount == 1 && editor.inMultiSelectMode) - exitMultiSelectMode(editor) - }.bind(editor.selection)); - editor.on("mousedown", onMouseDown); editor.commands.addCommands(exports.defaultCommands); } diff --git a/lib/ace/selection.js b/lib/ace/selection.js index 810a0289..7827d359 100644 --- a/lib/ace/selection.js +++ b/lib/ace/selection.js @@ -392,14 +392,14 @@ var Selection = function(session) { this.moveCursorTo(fold.end.row, fold.end.column); return; } - + // first skip space if (match = this.session.nonTokenRe.exec(rightOfCursor)) { column += this.session.nonTokenRe.lastIndex; this.session.nonTokenRe.lastIndex = 0; rightOfCursor = line.substring(column); } - + // if at line end proceed with next line if (column >= line.length) { this.moveCursorTo(row, line.length); @@ -408,7 +408,7 @@ var Selection = function(session) { this.moveCursorWordRight(); return; } - + // advance to the end of the next token if (match = this.session.tokenRe.exec(rightOfCursor)) { column += this.session.tokenRe.lastIndex; @@ -433,19 +433,19 @@ var Selection = function(session) { if (str == null) { str = this.doc.getLine(row).substring(0, column) } - + var leftOfCursor = lang.stringReverse(str); var match; this.session.nonTokenRe.lastIndex = 0; this.session.tokenRe.lastIndex = 0; - + // skip whitespace if (match = this.session.nonTokenRe.exec(leftOfCursor)) { column -= this.session.nonTokenRe.lastIndex; leftOfCursor = leftOfCursor.slice(this.session.nonTokenRe.lastIndex); this.session.nonTokenRe.lastIndex = 0; } - + // if at begin of the line proceed in line above if (column <= 0) { this.moveCursorTo(row, 0); @@ -504,6 +504,34 @@ var Selection = function(session) { this.moveCursorTo(row, column, preventUpdateDesiredColumn); }; + // remove listeners from document + this.detach = function() { + this.selectionLead.detach(); + this.selectionAnchor.detach(); + this.session = this.doc = null; + } + + this.fromOrientedRange = function(range) { + this.setSelectionRange(range, range.cursor == range.start); + this.$desiredColumn = range.desiredColumn || this.$desiredColumn; + } + + this.toOrientedRange = function(range) { + var r = this.getRange(); + if (range) { + range.start.column = r.start.column; + range.start.row = r.start.row; + range.end.column = r.end.column; + range.end.row = r.end.row; + } else { + range = r; + } + + range.cursor = this.isBackwards() ? range.start : range.end; + range.desiredColumn = this.$desiredColumn; + return range; + } + }).call(Selection.prototype); exports.Selection = Selection;