diff --git a/demo/demo.js b/demo/demo.js index 0437c78c..408036f4 100644 --- a/demo/demo.js +++ b/demo/demo.js @@ -127,6 +127,26 @@ exports.launch = function(env) { var container = document.getElementById("editor"); env.editor = new Editor(new Renderer(container, theme)); + var Anchor = require("ace/anchor").Anchor; + var Range = require("ace/range").Range; + + var anchorStart = new Anchor(docs.js, 2, 8); + var anchorEnd = new Anchor(docs.js, 2, 13); + + var marker; + function updateFloat() { + if (marker) + env.editor.renderer.removeMarker(marker); + var range = Range.fromPoints( + anchorStart.getPosition(), + anchorEnd.getPosition() + ); + marker = env.editor.renderer.addMarker(range, "cool", "text"); + }; + updateFloat(); + anchorStart.on("change", updateFloat); + anchorEnd.on("change", updateFloat); + var modes = { text: new TextMode(), xml: new XmlMode(), diff --git a/demo/styles.css b/demo/styles.css index 3f244f7c..2c941c00 100644 --- a/demo/styles.css +++ b/demo/styles.css @@ -15,6 +15,12 @@ body { color: white; } +#editor .cool { + position: absolute; + z-index: 4; + background: orange; +} + #editor { position: absolute; top: 60px; diff --git a/lib/ace/anchor.js b/lib/ace/anchor.js index ab5946ac..1be42e22 100644 --- a/lib/ace/anchor.js +++ b/lib/ace/anchor.js @@ -46,11 +46,14 @@ var EventEmitter = require("pilot/event_emitter").EventEmitter; */ var Anchor = exports.Anchor = function(doc, row, column) { this.document = doc; - this.pos = { - row: row, - column: column - }; - doc.on("change", this.onChange.bind(this)); + + if (typeof column == "undefined") + this.setPosition(row.row, row.column) + else + this.setPosition(row, column); + + this.$onChange = this.onChange.bind(this); + doc.on("change", this.$onChange); }; (function() { @@ -58,10 +61,7 @@ var Anchor = exports.Anchor = function(doc, row, column) { oop.implement(this, EventEmitter); this.getPosition = function() { - return { - row: this.pos.row, - column: this.pos.column - }; + return this.$clipPositionToDocument(this.row, this.column); }; this.getDocument = function() { @@ -72,80 +72,103 @@ var Anchor = exports.Anchor = function(doc, row, column) { var delta = e.data; var range = delta.range; - if (range.start.row == range.end.row && range.start.row != this.pos.row) + if (range.start.row == range.end.row && range.start.row != this.row) return; - if (range.start.row > this.pos.row) + if (range.start.row > this.row) return; - if (range.start.row == this.pos.row && range.start.column > this.pos.column) + if (range.start.row == this.row && range.start.column > this.column) return; - var pos = this.getPosition(); + var row = this.row; + var column = this.column; + if (delta.action === "insertText") { - if (range.start.row === pos.row && range.start.column <= pos.column) { + if (range.start.row === row && range.start.column <= column) { if (range.start.row === range.end.row) { - pos.column += range.end.column - range.start.column; + column += range.end.column - range.start.column; } else { - pos.column -= range.start.column; - pos.row += range.end.row - range.start.row; + column -= range.start.column; + row += range.end.row - range.start.row; } } - else if (range.start.row !== range.end.row && range.start.row < pos.row) { - pos.row += range.end.row - range.start.row; + else if (range.start.row !== range.end.row && range.start.row < row) { + row += range.end.row - range.start.row; } } else if (delta.action === "insertLines") { - if (range.start.row <= pos.row) { - pos.row += range.end.row - range.start.row; + if (range.start.row <= row) { + row += range.end.row - range.start.row; } } else if (delta.action == "removeText") { - if (range.start.row == pos.row && range.start.column < pos.column) { - if (range.end.column >= pos.column) - pos.column = range.start.column; + if (range.start.row == row && range.start.column < column) { + if (range.end.column >= column) + column = range.start.column; else - pos.column = Math.max(0, pos.column - (range.end.column - range.start.column)); + column = Math.max(0, column - (range.end.column - range.start.column)); - } else if (range.start.row !== range.end.row && range.start.row < pos.row) { - if (range.end.row == pos.row) { - pos.column = Math.max(0, pos.column - range.end.column) + range.start.column; + } else if (range.start.row !== range.end.row && range.start.row < row) { + if (range.end.row == row) { + column = Math.max(0, column - range.end.column) + range.start.column; } - pos.row -= (range.end.row - range.start.row); + row -= (range.end.row - range.start.row); } - else if (range.end.row == pos.row) { - pos.row -= range.end.row - range.start.row; - pos.column = Math.max(0, pos.column - range.end.column) + range.start.column; + else if (range.end.row == row) { + row -= range.end.row - range.start.row; + column = Math.max(0, column - range.end.column) + range.start.column; } } else if (delta.action == "removeLines") { - if (range.start.row <= pos.row) { - if (range.end.row <= pos.row) - pos.row -= range.end.row - range.start.row; + if (range.start.row <= row) { + if (range.end.row <= row) + row -= range.end.row - range.start.row; else { - pos.row = range.start.row; - pos.column = 0; + row = range.start.row; + column = 0; } } } - // clip - var len = this.document.getLength(); - if (pos.row > len) { - pos.row = len - 1; - pos.column = this.document.getLine(len-1).length; - } - - this.setPosition(pos); + this.setPosition(row, column); }; - this.setPosition = function(pos) { - if (this.pos.row == pos.row && this.pos.column == pos.column) + this.setPosition = function(row, column) { + pos = this.$clipPositionToDocument(row, column); + if (this.row == pos.row && this.column == pos.column) return; - this.pos = pos; + this.row = pos.row; + this.column = pos.column; this._dispatchEvent("change"); }; + this.detach = function() { + this.document.removeEventListener("change", this.$onChange); + }; + + this.$clipPositionToDocument = function(row, column) { + var pos = {}; + + if (row >= this.document.getLength()) { + pos.row = Math.max(0, this.document.getLength() - 1); + pos.column = this.document.getLine(pos.row).length; + } + else if (row < 0) { + pos.row = 0; + pos.column = 0; + } + else { + pos.row = row; + pos.column = Math.min(this.document.getLine(pos.row).length, Math.max(0, column)); + } + + if (column < 0) + pos.column = 0; + + return pos; + }; + }).call(Anchor.prototype); }); diff --git a/lib/ace/edit_session.js b/lib/ace/edit_session.js index 98f382bc..0e299141 100644 --- a/lib/ace/edit_session.js +++ b/lib/ace/edit_session.js @@ -49,7 +49,6 @@ var NO_CHANGE_DELTAS = {}; var EditSession = function(text, mode) { this.$modified = true; - this.selection = new Selection(this); this.$breakpoints = []; this.$wrapData = []; this.listeners = []; @@ -60,6 +59,7 @@ var EditSession = function(text, mode) { this.setDocument(new Document(text)); } + this.selection = new Selection(this); if (mode) this.setMode(mode); }; @@ -576,7 +576,6 @@ var EditSession = function(text, mode) { for (var row=startRow; row<=endRow; row++) { this.insert({row: row, column:0}, indentString); } - return indentString.length; }; this.outdentRows = function (range) { @@ -599,13 +598,8 @@ var EditSession = function(text, mode) { deleteRange.start.column = 0; deleteRange.end.column = j; } - if (i == range.start.row) - range.start.column -= deleteRange.end.column - deleteRange.start.column; - if (i == range.end.row) - range.end.column -= deleteRange.end.column - deleteRange.start.column; this.remove(deleteRange); } - return range; }; this.moveLinesUp = function(firstRow, lastRow) { diff --git a/lib/ace/editor.js b/lib/ace/editor.js index 685ee10a..8d66ad8a 100644 --- a/lib/ace/editor.js +++ b/lib/ace/editor.js @@ -375,7 +375,7 @@ var Editor =function(renderer, session) { return; if (!this.selection.isEmpty()) { - this.moveCursorToPosition(this.session.remove(this.getSelectionRange())); + this.session.remove(this.getSelectionRange()) this.clearSelection(); } }; @@ -405,14 +405,6 @@ var Editor =function(renderer, session) { var lineIndent = this.mode.getNextLineIndent(lineState, line.slice(0, cursor.column), this.session.getTabString()); var end = this.session.insert(cursor, text); - /* TODO: This shortcut is somehow broken - if (!shouldOutdent && line != this.session.getLine(row) && text != "\n") { - this.moveCursorToPosition(end); - this.renderer.scrollCursorIntoView(); - return; - } - */ - var lineState = this.bgTokenizer.getState(cursor.row); // multi line insert if (cursor.row !== end.row) { @@ -445,15 +437,12 @@ var Editor =function(renderer, session) { outdent -= 1; this.session.replace(new Range(row, 0, row, line.length), line.substr(i)); } - end.column += this.session.indentRows(cursor.row + 1, end.row, lineIndent); + this.session.indentRows(cursor.row + 1, end.row, lineIndent); } else { if (shouldOutdent) { - end.column += this.mode.autoOutdent(lineState, this.session, cursor.row); + this.mode.autoOutdent(lineState, this.session, cursor.row); } } - - this.moveCursorToPosition(end); - this.renderer.scrollCursorIntoView(); } this.onTextInput = function(text) { @@ -561,7 +550,7 @@ var Editor =function(renderer, session) { if (this.selection.isEmpty()) { this.selection.selectRight(); } - this.moveCursorToPosition(this.session.remove(this.getSelectionRange())); + this.session.remove(this.getSelectionRange()) this.clearSelection(); }; @@ -572,7 +561,7 @@ var Editor =function(renderer, session) { if (this.selection.isEmpty()) this.selection.selectLeft(); - this.moveCursorToPosition(this.session.remove(this.getSelectionRange())); + this.session.remove(this.getSelectionRange()); this.clearSelection(); }; @@ -585,9 +574,7 @@ var Editor =function(renderer, session) { if (range.start.row < range.end.row || range.start.column < range.end.column) { var rows = this.$getSelectedRows(); - var count = session.indentRows(rows.first, rows.last, "\t"); - - this.selection.shiftSelection(count); + session.indentRows(rows.first, rows.last, "\t"); } else { var indentString; @@ -609,9 +596,7 @@ var Editor =function(renderer, session) { return; var selection = this.session.getSelection(); - var range = this.session.outdentRows(selection.getRange()); - - selection.setSelectionRange(range, selection.isBackwards()); + this.session.outdentRows(selection.getRange()); }; this.toggleCommentLines = function() { @@ -620,8 +605,7 @@ var Editor =function(renderer, session) { var state = this.bgTokenizer.getState(this.getCursorPosition().row); var rows = this.$getSelectedRows() - var addedColumns = this.mode.toggleCommentLines(state, this.session, rows.first, rows.last); - this.selection.shiftSelection(addedColumns); + this.mode.toggleCommentLines(state, this.session, rows.first, rows.last); }; this.removeLines = function() { @@ -629,10 +613,7 @@ var Editor =function(renderer, session) { return; var rows = this.$getSelectedRows(); - this.selection.setSelectionAnchor(rows.last+1, 0); - this.selection.selectTo(rows.first, 0); - - this.session.remove(this.getSelectionRange()); + this.session.remove(new Range(rows.first, 0, rows.last+1, 0)); this.clearSelection(); }; @@ -697,7 +678,6 @@ var Editor =function(renderer, session) { this.onCompositionStart = function(text) { this.renderer.showComposition(this.getCursorPosition()); - //this.onTextInput(text); }; this.onCompositionUpdate = function(text) { @@ -706,7 +686,6 @@ var Editor =function(renderer, session) { this.onCompositionEnd = function() { this.renderer.hideComposition(); - //this.removeLeft(); }; diff --git a/lib/ace/mode/c_cpp.js b/lib/ace/mode/c_cpp.js index 986afbad..08bd249e 100644 --- a/lib/ace/mode/c_cpp.js +++ b/lib/ace/mode/c_cpp.js @@ -69,16 +69,16 @@ oop.inherits(Mode, TextMode); var deleteRange = new Range(0, 0, 0, 0); for (var i=startRow; i<= endRow; i++) { - var line = doc.getLine(i).replace(re, "$1"); + var line = doc.getLine(i); + var m = line.match(re); deleteRange.start.row = i; deleteRange.end.row = i; - deleteRange.end.column = line.length + 2; - doc.replace(deleteRange, line); + deleteRange.end.column = m[0].length; + doc.replace(deleteRange, m[1]); } - return -2; } else { - return doc.indentRows(startRow, endRow, "//"); + doc.indentRows(startRow, endRow, "//"); } }; @@ -119,7 +119,7 @@ oop.inherits(Mode, TextMode); }; this.autoOutdent = function(state, doc, row) { - return this.$outdent.autoOutdent(doc, row); + this.$outdent.autoOutdent(doc, row); }; }).call(Mode.prototype); diff --git a/lib/ace/mode/coffee.js b/lib/ace/mode/coffee.js index 32c692b4..27a9360a 100644 --- a/lib/ace/mode/coffee.js +++ b/lib/ace/mode/coffee.js @@ -37,52 +37,63 @@ define(function(require, exports, module) { -var Tokenizer = require("ace/tokenizer").Tokenizer - , Rules = require("ace/mode/coffee_highlight_rules").CoffeeHighlightRules - , Outdent = require("ace/mode/matching_brace_outdent").MatchingBraceOutdent - , Range = require("ace/range").Range -; -require("pilot/oop").inherits(CoffeeMode, require("ace/mode/text").Mode); +var Tokenizer = require("ace/tokenizer").Tokenizer; +var Rules = require("ace/mode/coffee_highlight_rules").CoffeeHighlightRules; +var Outdent = require("ace/mode/matching_brace_outdent").MatchingBraceOutdent; +var Range = require("ace/range").Range; +var TextMode = require("ace/mode/text").Mode; +var oop = require("pilot/oop") function CoffeeMode() { this.$tokenizer = new Tokenizer(new Rules().getRules()); this.$outdent = new Outdent(); -} -var proto = CoffeeMode.prototype - , indenter = /(?:[({[=:]|[-=]>|\b(?:else|switch|try|catch(?:\s*[$A-Za-z_\x7f-\uffff][$\w\x7f-\uffff]*)?|finally))\s*$/ - , commentLine = /^(\s*)#/ - , hereComment = /^\s*###(?!#)/ - , indentation = /^\s*/ -; -proto.getNextLineIndent = function(state, line, tab){ - var indent = this.$getIndent(line) - , tokens = this.$tokenizer.getLineTokens(line, state).tokens - ; +}; + +oop.inherits(CoffeeMode, TextMode); + +var proto = CoffeeMode.prototype; +var indenter = /(?:[({[=:]|[-=]>|\b(?:else|switch|try|catch(?:\s*[$A-Za-z_\x7f-\uffff][$\w\x7f-\uffff]*)?|finally))\s*$/; +var commentLine = /^(\s*)#/; +var hereComment = /^\s*###(?!#)/; +var indentation = /^\s*/; + +proto.getNextLineIndent = function(state, line, tab) { + var indent = this.$getIndent(line); + var tokens = this.$tokenizer.getLineTokens(line, state).tokens; + if (!(tokens.length && tokens[tokens.length - 1].type === 'comment') && state === 'start' && indenter.test(line)) indent += tab; return indent; }; + proto.toggleCommentLines = function(state, doc, startRow, endRow){ - var out, range = new Range(0, 0, 0, 0); + console.log("toggle"); + var range = new Range(0, 0, 0, 0); for (var i = startRow; i <= endRow; ++i) { var line = doc.getLine(i); - if (hereComment.test(line)) continue; - line = (out = commentLine.test(line)) - ? line.replace(commentLine, '$1') - : line.replace(indentation, '$&#'); + if (hereComment.test(line)) + continue; + + if (commentLine.test(line)) + line = line.replace(commentLine, '$1'); + else + line = line.replace(indentation, '$&#'); + range.end.row = range.start.row = i; range.end.column = line.length + 1; doc.replace(range, line); } - return 1 - out * 2; }; + proto.checkOutdent = function(state, line, input) { return this.$outdent.checkOutdent(line, input); }; + proto.autoOutdent = function(state, doc, row) { - return this.$outdent.autoOutdent(doc, row); + this.$outdent.autoOutdent(doc, row); }; exports.Mode = CoffeeMode; -}); + +}); \ No newline at end of file diff --git a/lib/ace/mode/css.js b/lib/ace/mode/css.js index bb12cbca..d8878bda 100644 --- a/lib/ace/mode/css.js +++ b/lib/ace/mode/css.js @@ -73,7 +73,7 @@ oop.inherits(Mode, TextMode); }; this.autoOutdent = function(state, doc, row) { - return this.$outdent.autoOutdent(doc, row); + this.$outdent.autoOutdent(doc, row); }; }).call(Mode.prototype); diff --git a/lib/ace/mode/html.js b/lib/ace/mode/html.js index ec2a521c..2dced037 100644 --- a/lib/ace/mode/html.js +++ b/lib/ace/mode/html.js @@ -55,7 +55,7 @@ oop.inherits(Mode, TextMode); (function() { this.toggleCommentLines = function(state, doc, startRow, endRow) { - return this.$delegate("toggleCommentLines", arguments, function() { + this.$delegate("toggleCommentLines", arguments, function() { return 0; }); }; @@ -74,7 +74,7 @@ oop.inherits(Mode, TextMode); }; this.autoOutdent = function(state, doc, row) { - return this.$delegate("autoOutdent", arguments); + this.$delegate("autoOutdent", arguments); }; this.$delegate = function(method, args, defaultHandler) { diff --git a/lib/ace/mode/javascript.js b/lib/ace/mode/javascript.js index 2179edc3..a7634bf6 100644 --- a/lib/ace/mode/javascript.js +++ b/lib/ace/mode/javascript.js @@ -69,16 +69,16 @@ oop.inherits(Mode, TextMode); var deleteRange = new Range(0, 0, 0, 0); for (var i=startRow; i<= endRow; i++) { - var line = doc.getLine(i).replace(re, "$1"); + var line = doc.getLine(i); + var m = line.match(re); deleteRange.start.row = i; deleteRange.end.row = i; - deleteRange.end.column = line.length + 2; - doc.replace(deleteRange, line); + deleteRange.end.column = m[0].length; + doc.replace(deleteRange, m[1]); } - return -2; } else { - return doc.indentRows(startRow, endRow, "//"); + doc.indentRows(startRow, endRow, "//"); } }; @@ -119,7 +119,7 @@ oop.inherits(Mode, TextMode); }; this.autoOutdent = function(state, doc, row) { - return this.$outdent.autoOutdent(doc, row); + this.$outdent.autoOutdent(doc, row); }; this.createWorker = function(session) { diff --git a/lib/ace/mode/matching_brace_outdent.js b/lib/ace/mode/matching_brace_outdent.js index 05d20e5a..3ca68c04 100644 --- a/lib/ace/mode/matching_brace_outdent.js +++ b/lib/ace/mode/matching_brace_outdent.js @@ -63,8 +63,6 @@ var MatchingBraceOutdent = function() {}; var indent = this.$getIndent(doc.getLine(openBracePos.row)); doc.replace(new Range(row, 0, row, column-1), indent); - - return indent.length - (column-1); }; this.$getIndent = function(line) { diff --git a/lib/ace/mode/php.js b/lib/ace/mode/php.js index 843d324d..13fdf30b 100644 --- a/lib/ace/mode/php.js +++ b/lib/ace/mode/php.js @@ -68,16 +68,16 @@ oop.inherits(Mode, TextMode); var deleteRange = new Range(0, 0, 0, 0); for (var i=startRow; i<= endRow; i++) { - var line = doc.getLine(i).replace(re, "$1"); + var line = doc.getLine(i); + var m = line.match(re); deleteRange.start.row = i; deleteRange.end.row = i; - deleteRange.end.column = line.length + 2; - doc.replace(deleteRange, line); + deleteRange.end.column = m[0].length; + doc.replace(deleteRange, m[1]); } - return -2; } else { - return doc.indentRows(startRow, endRow, "#"); + doc.indentRows(startRow, endRow, "#"); } }; @@ -107,7 +107,7 @@ oop.inherits(Mode, TextMode); }; this.autoOutdent = function(state, doc, row) { - return this.$outdent.autoOutdent(doc, row); + this.$outdent.autoOutdent(doc, row); }; }).call(Mode.prototype); diff --git a/lib/ace/mode/python.js b/lib/ace/mode/python.js index dbc74389..2d8569e6 100644 --- a/lib/ace/mode/python.js +++ b/lib/ace/mode/python.js @@ -69,16 +69,16 @@ oop.inherits(Mode, TextMode); var deleteRange = new Range(0, 0, 0, 0); for (var i=startRow; i<= endRow; i++) { - var line = doc.getLine(i).replace(re, "$1"); + var line = doc.getLine(i); + var m = line.match(re); deleteRange.start.row = i; deleteRange.end.row = i; - deleteRange.end.column = line.length + 2; - doc.replace(deleteRange, line); + deleteRange.end.column = m[0].length; + doc.replace(deleteRange, m[1]); } - return -2; } else { - return doc.indentRows(startRow, endRow, "#"); + doc.indentRows(startRow, endRow, "#"); } }; @@ -108,7 +108,7 @@ oop.inherits(Mode, TextMode); }; this.autoOutdent = function(state, doc, row) { - return this.$outdent.autoOutdent(doc, row); + this.$outdent.autoOutdent(doc, row); }; }).call(Mode.prototype); diff --git a/lib/ace/mode/ruby.js b/lib/ace/mode/ruby.js index b6944ef2..532c8cec 100644 --- a/lib/ace/mode/ruby.js +++ b/lib/ace/mode/ruby.js @@ -69,16 +69,16 @@ oop.inherits(Mode, TextMode); var deleteRange = new Range(0, 0, 0, 0); for (var i=startRow; i<= endRow; i++) { - var line = doc.getLine(i).replace(re, "$1"); + var line = doc.getLine(i); + var m = line.match(re); deleteRange.start.row = i; deleteRange.end.row = i; - deleteRange.end.column = line.length + 2; - doc.replace(deleteRange, line); + deleteRange.end.column = m[0].length; + doc.replace(deleteRange, m[1]); } - return -2; } else { - return doc.indentRows(startRow, endRow, "#"); + doc.indentRows(startRow, endRow, "#"); } }; @@ -108,7 +108,7 @@ oop.inherits(Mode, TextMode); }; this.autoOutdent = function(state, doc, row) { - return this.$outdent.autoOutdent(doc, row); + this.$outdent.autoOutdent(doc, row); }; }).call(Mode.prototype); diff --git a/lib/ace/mode/text.js b/lib/ace/mode/text.js index 7a400ef9..fe1c9f17 100644 --- a/lib/ace/mode/text.js +++ b/lib/ace/mode/text.js @@ -51,7 +51,6 @@ var Mode = function() { }; this.toggleCommentLines = function(state, doc, startRow, endRow) { - return 0; }; this.getNextLineIndent = function(state, line, tab) { diff --git a/lib/ace/selection.js b/lib/ace/selection.js index 2adc54be..8e6d4b73 100644 --- a/lib/ace/selection.js +++ b/lib/ace/selection.js @@ -42,15 +42,27 @@ var oop = require("pilot/oop"); var lang = require("pilot/lang"); var EventEmitter = require("pilot/event_emitter").EventEmitter; var Range = require("ace/range").Range; +var Anchor = require("ace/anchor").Anchor; -var Selection = function(doc) { - this.doc = doc; +var Selection = function(session) { + this.session = session; + this.doc = session.getDocument(); this.clearSelection(); - this.selectionLead = { - row: 0, - column: 0 - }; + this.selectionLead = new Anchor(this.doc, 0, 0); + this.selectionAnchor = new Anchor(this.doc, 0, 0); + + var _self = this; + this.selectionLead.on("change", function() { + _self._dispatchEvent("changeCursor"); + if (!_self.$isEmpty) + _self._dispatchEvent("changeSelection"); + }); + + this.selectionAnchor.on("change", function() { + if (!_self.$isEmpty) + _self._dispatchEvent("changeSelection"); + }); }; (function() { @@ -58,9 +70,10 @@ var Selection = function(doc) { oop.implement(this, EventEmitter); this.isEmpty = function() { - return (!this.selectionAnchor || - (this.selectionAnchor.row == this.selectionLead.row && - this.selectionAnchor.column == this.selectionLead.column)); + return (this.$isEmpty || ( + this.selectionAnchor.row == this.selectionLead.row && + this.selectionAnchor.column == this.selectionLead.column + )); }; this.isMultiLine = function() { @@ -72,37 +85,31 @@ var Selection = function(doc) { }; this.getCursor = function() { - return this.selectionLead; + return this.selectionLead.getPosition(); }; this.setSelectionAnchor = function(row, column) { - var anchor = this.$clipPositionToDocument(row, column); + this.selectionAnchor.setPosition(row, column); - if (!this.selectionAnchor) { - this.selectionAnchor = anchor; - this._dispatchEvent("changeSelection", {}); + if (this.$isEmpty) { + this.$isEmpty = false; + this._dispatchEvent("changeSelection"); } - else if (this.selectionAnchor.row !== anchor.row || this.selectionAnchor.column !== anchor.column) { - this.selectionAnchor = anchor; - this._dispatchEvent("changeSelection", {}); - } - }; this.getSelectionAnchor = function() { - if (this.selectionAnchor) { - return this.$clone(this.selectionAnchor); - } else { - return this.$clone(this.selectionLead); - } + if (this.$isEmpty) + return this.getSelectionLead() + else + return this.selectionAnchor.getPosition(); }; this.getSelectionLead = function() { - return this.$clone(this.selectionLead); + return this.selectionLead.getPosition(); }; this.shiftSelection = function(columns) { - if (this.isEmpty()) { + if (this.$isEmpty) { this.moveCursorTo(this.selectionLead.row, this.selectionLead.column + columns); return; }; @@ -123,15 +130,18 @@ var Selection = function(doc) { }; this.isBackwards = function() { - var anchor = this.selectionAnchor || this.selectionLead; + var anchor = this.selectionAnchor; var lead = this.selectionLead; return (anchor.row > lead.row || (anchor.row == lead.row && anchor.column > lead.column)); }; this.getRange = function() { - var anchor = this.selectionAnchor || this.selectionLead; + var anchor = this.selectionAnchor; var lead = this.selectionLead; + if (this.isEmpty()) + return Range.fromPoints(lead, lead); + if (this.isBackwards()) { return Range.fromPoints(lead, anchor); } @@ -141,26 +151,17 @@ var Selection = function(doc) { }; this.clearSelection = function() { - if (this.selectionAnchor) { - this.selectionAnchor = null; - this._dispatchEvent("changeSelection", {}); + if (!this.$isEmpty) { + this.$isEmpty = true; + this._dispatchEvent("changeSelection"); } }; this.selectAll = function() { var lastRow = this.doc.getLength() - 1; this.setSelectionAnchor(lastRow, this.doc.getLine(lastRow).length); - - if (!this.selectionAnchor) { - this.selectionAnchor = this.$clone(this.selectionLead); - } - - var cursor = {row:0, column:0}; - // only dispatch change if the cursor actually changed - if (cursor.row !== this.selectionLead.row || cursor.column !== this.selectionLead.column) { - this.selectionLead = cursor; - this._dispatchEvent("changeSelection", {blockScrolling: true}); - } + this.setSelectionLead(0, 0); +// this._dispatchEvent("changeSelection", {blockScrolling: true}); }; this.setSelectionRange = function(range, reverse) { @@ -177,27 +178,16 @@ var Selection = function(doc) { this.$updateDesiredColumn = function() { var cursor = this.getCursor(); if (cursor) { - this.$desiredColumn = this.doc.documentToScreenColumn(cursor.row, cursor.column); + this.$desiredColumn = this.session.documentToScreenColumn(cursor.row, cursor.column); } }; this.$moveSelection = function(mover) { - var changed = false; + var lead = this.selectionLead; + if (this.$isEmpty) + this.setSelectionAnchor(lead.row, lead.column); - if (!this.selectionAnchor) { - changed = true; - this.selectionAnchor = this.$clone(this.selectionLead); - } - - var cursor = this.$clone(this.selectionLead); mover.call(this); - - if (cursor.row !== this.selectionLead.row || cursor.column !== this.selectionLead.column) { - changed = true; - } - - if (changed) - this._dispatchEvent("changeSelection", {}); }; this.selectTo = function(row, column) { @@ -253,15 +243,9 @@ var Selection = function(doc) { }; this.selectWord = function() { - var cursor = this.selectionLead; - var column = cursor.column; - var range = this.doc.getWordRange(cursor.row, column); + var cursor = this.getCursor(); + var range = this.session.getWordRange(cursor.row, cursor.column); this.setSelectionRange(range); - - /*this.setSelectionAnchor(cursor.row, start); - this.$moveSelection(function() { - this.moveCursorTo(cursor.row, end); - });*/ }; this.selectLine = function() { @@ -280,18 +264,16 @@ var Selection = function(doc) { }; this.moveCursorLeft = function() { - if (this.selectionLead.column == 0) { + var cursor = this.selectionLead.getPosition(); + if (cursor.column == 0) { // cursor is a line (start - if (this.selectionLead.row > 0) { - this.moveCursorTo(this.selectionLead.row - 1, this.doc - .getLine(this.selectionLead.row - 1).length); + if (cursor.row > 0) { + this.moveCursorTo(cursor.row - 1, this.doc.getLine(cursor.row - 1).length); } } else { - var doc = this.doc; - var tabSize = doc.getTabSize(); - var cursor = this.selectionLead; - if (doc.isTabStop(cursor) && doc.getLine(cursor.row).slice(cursor.column-tabSize, cursor.column).split(" ").length-1 == tabSize) + var tabSize = this.session.getTabSize(); + if (this.session.isTabStop(cursor) && this.doc.getLine(cursor.row).slice(cursor.column-tabSize, cursor.column).split(" ").length-1 == tabSize) this.moveCursorBy(0, -tabSize); else this.moveCursorBy(0, -1); @@ -305,10 +287,9 @@ var Selection = function(doc) { } } else { - var doc = this.doc; - var tabSize = doc.getTabSize(); + var tabSize = this.session.getTabSize(); var cursor = this.selectionLead; - if (doc.isTabStop(cursor) && doc.getLine(cursor.row).slice(cursor.column, cursor.column+tabSize).split(" ").length-1 == tabSize) + if (this.session.isTabStop(cursor) && this.doc.getLine(cursor.row).slice(cursor.column, cursor.column+tabSize).split(" ").length-1 == tabSize) this.moveCursorBy(0, tabSize); else this.moveCursorBy(0, 1); @@ -318,12 +299,12 @@ var Selection = function(doc) { this.moveCursorLineStart = function() { var row = this.selectionLead.row; var column = this.selectionLead.column; - var screenRow = this.doc.documentToScreenRow(row, column); - var firstRowColumn = this.doc.getScreenFirstRowColumn(screenRow); + var screenRow = this.session.documentToScreenRow(row, column); + var firstRowColumn = this.session.getScreenFirstRowColumn(screenRow); var beforeCursor = this.doc.getLine(row).slice(firstRowColumn, column); var leadingSpace = beforeCursor.match(/^\s*/); if (leadingSpace[0].length == 0) { - var lastRowColumn = this.doc.getDocumentLastRowColumn(row, column); + var lastRowColumn = this.session.getDocumentLastRowColumn(row, column); leadingSpace = this.doc.getLine(row). substring(firstRowColumn, lastRowColumn). match(/^\s*/); @@ -336,9 +317,8 @@ var Selection = function(doc) { }; this.moveCursorLineEnd = function() { - var selLead = this.selectionLead; - this.moveCursorTo(selLead.row, - this.doc.getDocumentLastRowColumn(selLead.row, selLead.column)); + var lead = this.selectionLead; + this.moveCursorTo(lead.row, this.session.getDocumentLastRowColumn(lead.row, lead.column)); }; this.moveCursorFileEnd = function() { @@ -358,20 +338,20 @@ var Selection = function(doc) { var rightOfCursor = line.substring(column); var match; - this.doc.nonTokenRe.lastIndex = 0; - this.doc.tokenRe.lastIndex = 0; + this.session.nonTokenRe.lastIndex = 0; + this.session.tokenRe.lastIndex = 0; if (column == line.length) { this.moveCursorRight(); return; } - else if (match = this.doc.nonTokenRe.exec(rightOfCursor)) { - column += this.doc.nonTokenRe.lastIndex; - this.doc.nonTokenRe.lastIndex = 0; + else if (match = this.session.nonTokenRe.exec(rightOfCursor)) { + column += this.session.nonTokenRe.lastIndex; + this.session.nonTokenRe.lastIndex = 0; } - else if (match = this.doc.tokenRe.exec(rightOfCursor)) { - column += this.doc.tokenRe.lastIndex; - this.doc.tokenRe.lastIndex = 0; + else if (match = this.session.tokenRe.exec(rightOfCursor)) { + column += this.session.tokenRe.lastIndex; + this.session.tokenRe.lastIndex = 0; } this.moveCursorTo(row, column); @@ -384,83 +364,49 @@ var Selection = function(doc) { var leftOfCursor = lang.stringReverse(line.substring(0, column)); var match; - this.doc.nonTokenRe.lastIndex = 0; - this.doc.tokenRe.lastIndex = 0; + this.session.nonTokenRe.lastIndex = 0; + this.session.tokenRe.lastIndex = 0; if (column == 0) { this.moveCursorLeft(); return; } - else if (match = this.doc.nonTokenRe.exec(leftOfCursor)) { - column -= this.doc.nonTokenRe.lastIndex; - this.doc.nonTokenRe.lastIndex = 0; + else if (match = this.session.nonTokenRe.exec(leftOfCursor)) { + column -= this.session.nonTokenRe.lastIndex; + this.session.nonTokenRe.lastIndex = 0; } - else if (match = this.doc.tokenRe.exec(leftOfCursor)) { - column -= this.doc.tokenRe.lastIndex; - this.doc.tokenRe.lastIndex = 0; + else if (match = this.session.tokenRe.exec(leftOfCursor)) { + column -= this.session.tokenRe.lastIndex; + this.session.tokenRe.lastIndex = 0; } this.moveCursorTo(row, column); }; this.moveCursorBy = function(rows, chars) { - if (this.doc.getUseWrapMode()) { - var screenPos = this.doc.documentToScreenPosition( - this.selectionLead.row, this.selectionLead.column); - var screenCol = - (chars == 0 && this.$desiredColumn) || screenPos.column; - - var docPos = this.doc.screenToDocumentPosition( - screenPos.row + rows, screenCol); + if (this.session.getUseWrapMode()) { + var screenPos = this.session.documentToScreenPosition( + this.selectionLead.row, + this.selectionLead.column + ); + var screenCol = (chars == 0 && this.$desiredColumn) || screenPos.column; + var docPos = this.session.screenToDocumentPosition(screenPos.row + rows, screenCol); + this.moveCursorTo(docPos.row, docPos.column + chars, chars == 0); } else { - var docColumn = - (chars == 0 && this.$desiredColumn) || this.selectionLead.column; - this.moveCursorTo( - this.selectionLead.row + rows, docColumn + chars, chars == 0); + var docColumn = (chars == 0 && this.$desiredColumn) || this.selectionLead.column; + this.moveCursorTo(this.selectionLead.row + rows, docColumn + chars, chars == 0); } }; - this.moveCursorToPosition = function(position) { this.moveCursorTo(position.row, position.column); }; this.moveCursorTo = function(row, column, preventUpdateDesiredColumn) { - var cursor = this.$clipPositionToDocument(row, column); - - // only dispatch change if the cursor actually changed - if (cursor.row !== this.selectionLead.row || cursor.column !== this.selectionLead.column) { - this.selectionLead = cursor; - !preventUpdateDesiredColumn && this.$updateDesiredColumn(column); - this._dispatchEvent("changeCursor", { data: this.getCursor() }); - } - }; - - this.$clipPositionToDocument = function(row, column) { - var pos = {}; - - if (row >= this.doc.getLength()) { - pos.row = Math.max(0, this.doc.getLength() - 1); - pos.column = this.doc.getLine(pos.row).length; - } - else if (row < 0) { - pos.row = 0; - pos.column = 0; - } - else { - pos.row = row; - pos.column = Math.min(this.doc.getLine(pos.row).length, - Math.max(0, column)); - } - return pos; - }; - - this.$clone = function(pos) { - return { - row: pos.row, - column: pos.column - }; + this.selectionLead.setPosition(row, column); + if (!preventUpdateDesiredColumn) + this.$updateDesiredColumn(this.selectionLead.column); }; }).call(Selection.prototype); diff --git a/lib/ace/test/anchor_test.js b/lib/ace/test/anchor_test.js index 1eb86287..47191799 100644 --- a/lib/ace/test/anchor_test.js +++ b/lib/ace/test/anchor_test.js @@ -104,7 +104,6 @@ var Test = { var anchor = new Anchor(doc, 1, 4); doc.remove(new Range(1, 4, 1, 5)); - console.log(doc.$lines); assert.position(anchor.getPosition(), 1, 4); },