From f5a61599cf6adf19713393d3583eb823820b9574 Mon Sep 17 00:00:00 2001 From: Fabian Jakobs Date: Mon, 12 Apr 2010 16:04:49 +0200 Subject: [PATCH] add delete line command --- src/Editor.js | 107 +++++++++++++++++++---------------------- src/TextDocument.js | 11 +++-- test/MockRenderer.js | 3 ++ test/NavigationTest.js | 75 +++++++++++++---------------- test/TextEditTest.js | 34 +++++++++++++ test/assertions.js | 4 ++ 6 files changed, 131 insertions(+), 103 deletions(-) create mode 100644 test/TextEditTest.js create mode 100644 test/assertions.js diff --git a/src/Editor.js b/src/Editor.js index ab9a5c32..5468832c 100644 --- a/src/Editor.js +++ b/src/Editor.js @@ -15,7 +15,8 @@ var keys = { DELETE : 46, BACKSPACE : 8, TAB : 9, - A : 65 + A : 65, + D: 68 }; var KeyBinding = function(element, host) { @@ -30,6 +31,13 @@ var KeyBinding = function(element, host) { } break; + case keys.D: + if (e.metaKey) { + host.removeLine(); + return ace.stopEvent(e); + } + break; + case keys.UP: if (e.metaKey && e.shiftKey) { host.selectFileStart(); @@ -165,7 +173,7 @@ ace.Editor = function(doc, renderer) { ace.addListener(container, "dblclick", ace .bind(this.onMouseDoubleClick, this)); ace.addMouseWheelListener(container, ace.bind(this.onMouseWheel, this)); - ace.addTripleClickListener(container, ace.bind(this.selectCurrentLine, + ace.addTripleClickListener(container, ace.bind(this.selectLine, this)); this.doc = doc; @@ -221,7 +229,7 @@ ace.Editor.prototype.onMouseDown = function(e) { this.textInput.focus(); var pos = this.renderer.screenToTextCoordinates(e.pageX, e.pageY); - this.moveCursorTo(pos.row, pos.column); + this.moveCursorToPosition(pos); this.setSelectionAnchor(pos.row, pos.column); this.renderer.scrollCursorIntoView(); @@ -245,7 +253,7 @@ ace.Editor.prototype.onMouseDown = function(e) { mousePageY); _self._moveSelection(function() { - _self.moveCursorTo(selectionLead.row, selectionLead.column); + _self.moveCursorToPosition(selectionLead); }); _self.renderer.scrollCursorIntoView(); }; @@ -311,79 +319,57 @@ ace.Editor.prototype.getCopyText = function() { ace.Editor.prototype.onCut = function() { if (this.hasSelection()) { - this.cursor = this.doc.remove(this.getSelectionRange()); + this.moveCursorToPosition(this.doc.remove(this.getSelectionRange())); this.clearSelection(); - this.renderer.updateCursor(this.cursor); } }; ace.Editor.prototype.onTextInput = function(text) { if (this.hasSelection()) { - this.cursor = this.doc.replace(this.getSelectionRange(), text); + this.moveCursorToPosition(this.doc.replace(this.getSelectionRange(), text)); this.clearSelection(); } else { - this.cursor = this.doc.insert(this.cursor, text); + this.moveCursorToPosition(this.doc.insert(this.cursor, text)); } - this.renderer.updateCursor(this.cursor); this.renderer.scrollCursorIntoView(); }; ace.Editor.prototype.removeRight = function() { - if (this.hasSelection()) { - this.cursor = this.doc.remove(this.getSelectionRange()); - this.renderer.updateCursor(this.cursor); - this.clearSelection(); - } - else { - var rangeEnd = { - row : this.cursor.row, - column : this.cursor.column + 1 - }; - if (rangeEnd.column > this.doc.getLine(this.cursor.row).length) { - rangeEnd.row += 1; - rangeEnd.column = 0; - } - this.doc.remove( { - start : this.cursor, - end : renageEnd - }); + if (!this.hasSelection()) { + this.selectRight(); } + this.moveCursorToPosition(this.doc.remove(this.getSelectionRange())); + this.clearSelection(); this.renderer.scrollCursorIntoView(); }; - ace.Editor.prototype.removeLeft = function() { - if (this.hasSelection()) { - this.cursor = this.doc.remove(this.getSelectionRange()); - this.clearSelection(); - } - else { - if (this.cursor.row == 0 && this.cursor.column == 0) { return; } +ace.Editor.prototype.removeLeft = function() { + if (!this.hasSelection()) { + this.selectLeft(); + } + this.moveCursorToPosition(this.doc.remove(this.getSelectionRange())); + this.clearSelection(); - var rangeStart = { - row : this.cursor.row, - column : this.cursor.column + -1 - }; - if (rangeStart.column < 0) { - rangeStart.row -= 1; - rangeStart.column = this.doc - .getLine(this.cursor.row - 1).length; - } - this.cursor = this.doc.remove( { - start : rangeStart, - end : this.cursor - }); - } + this.renderer.scrollCursorIntoView(); +}, - this.renderer.updateCursor(this.cursor); - this.renderer.scrollCursorIntoView(); - }, +ace.Editor.prototype.removeLine = function() { + this.selectLine(); + this.moveCursorToPosition(this.doc.remove(this.getSelectionRange())); + this.clearSelection(); - ace.Editor.prototype.onCompositionStart = function() { - this.renderer.showComposition(this.cursor); - this.onTextInput(" "); - }; + if (this.cursor.row == this.doc.getLength() - 1) { + this.removeLeft(); + this.moveCursorLineStart(); + } +}; + +ace.Editor.prototype.onCompositionStart = function() { + this.renderer.showComposition(this.cursor); + this.onTextInput(" "); +}; ace.Editor.prototype.onCompositionUpdate = function(text) { this.renderer.setCompositionText(text); @@ -440,7 +426,7 @@ ace.Editor.prototype.navigateDown = function() { ace.Editor.prototype.navigateLeft = function() { if (this.hasSelection()) { var selectionStart = this.getSelectionRange().start; - this.moveCursorTo(selectionStart.row, selectionStart.column); + this.moveCursorToPosition(selectionStart); } else { this.moveCursorLeft(); @@ -453,7 +439,7 @@ ace.Editor.prototype.navigateLeft = function() { ace.Editor.prototype.navigateRight = function() { if (this.hasSelection()) { var selectionEnd = this.getSelectionRange().end; - this.moveCursorTo(selectionEnd.row, selectionEnd.column); + this.moveCursorToPosition(selectionEnd); } else { this.moveCursorRight(); @@ -605,6 +591,11 @@ ace.Editor.prototype.moveCursorBy = function(rows, chars) { this.moveCursorTo(this.cursor.row + rows, this.cursor.column + chars); }; + +ace.Editor.prototype.moveCursorToPosition = function(position) { + this.moveCursorTo(position.row, position.column); +}; + ace.Editor.prototype.moveCursorTo = function(row, column) { if (row >= this.doc.getLength()) { this.cursor.row = this.doc.getLength() - 1; @@ -774,7 +765,7 @@ ace.Editor.prototype.selectWordLeft = function() { this._moveSelection(this.moveCursorWordLeft); }; -ace.Editor.prototype.selectCurrentLine = function() { +ace.Editor.prototype.selectLine = function() { this.setSelectionAnchor(this.cursor.row, 0); this._moveSelection(function() { this.moveCursorTo(this.cursor.row + 1, 0); diff --git a/src/TextDocument.js b/src/TextDocument.js index ab1cee94..85932671 100644 --- a/src/TextDocument.js +++ b/src/TextDocument.js @@ -12,6 +12,10 @@ ace.TextDocument.prototype._split = function(text) { return text.split(/[\n\r]/); }; +ace.TextDocument.prototype.toString = function() { + return this.lines.join("\n"); +}; + ace.TextDocument.prototype.addChangeListener = function(listener) { this.listeners.push(listener); }; @@ -19,8 +23,7 @@ ace.TextDocument.prototype.addChangeListener = function(listener) { ace.TextDocument.prototype.fireChangeEvent = function(firstRow, lastRow) { for ( var i = 0; i < this.listeners.length; i++) { this.listeners[i](firstRow, lastRow); - } - ; + }; }; ace.TextDocument.prototype.getWidth = function() { @@ -141,12 +144,12 @@ ace.TextDocument.prototype._insert = function(position, text) { }; ace.TextDocument.prototype.remove = function(range) { - var end = this._remove(range); + this._remove(range); this.fireChangeEvent(range.start.row, range.end.row == range.start.row ? range.start.row : undefined); - return end; + return range.start; }; ace.TextDocument.prototype._remove = function(range) { diff --git a/test/MockRenderer.js b/test/MockRenderer.js index c16c2107..a634693a 100644 --- a/test/MockRenderer.js +++ b/test/MockRenderer.js @@ -58,5 +58,8 @@ MockRenderer.prototype.scrollToRow = function(row) { MockRenderer.prototype.draw = function() { }; +MockRenderer.prototype.updateLines = function(startRow, endRow) { +}; + MockRenderer.prototype.addMarker = function() { }; diff --git a/test/NavigationTest.js b/test/NavigationTest.js index f570c613..b06578fd 100644 --- a/test/NavigationTest.js +++ b/test/NavigationTest.js @@ -6,19 +6,12 @@ var NavigationTest = TestCase("NavigationTest", return new ace.TextDocument(text); }, - assertPosition : function(row, column, cursor) { - assertEquals(row, cursor.row); - assertEquals(column, cursor.column); - }, - - // End of file, start of files tests - "test: navigate to end of file should place the cursor on last row and column" : function() { var editor = new ace.Editor(this.createTextDocument(200, 10), new MockRenderer()); editor.navigateFileEnd(); - this.assertPosition(199, 10, editor.getCursorPosition()); + assertPosition(199, 10, editor.getCursorPosition()); }, "test: navigate to end of file should scroll the last line into view" : function() { @@ -37,7 +30,7 @@ var NavigationTest = TestCase("NavigationTest", new MockRenderer()); editor.navigateFileStart(); - this.assertPosition(0, 0, editor.getCursorPosition()); + assertPosition(0, 0, editor.getCursorPosition()); }, "test: navigate to start of file should scroll the first row into view" : function() { @@ -59,8 +52,8 @@ var NavigationTest = TestCase("NavigationTest", var selection = editor.getSelectionRange(); - this.assertPosition(100, 5, selection.start); - this.assertPosition(199, 10, selection.end); + assertPosition(100, 5, selection.start); + assertPosition(199, 10, selection.end); }, "test: move selection lead to start of file" : function() { @@ -72,8 +65,8 @@ var NavigationTest = TestCase("NavigationTest", var selection = editor.getSelectionRange(); - this.assertPosition(0, 0, selection.start); - this.assertPosition(100, 5, selection.end); + assertPosition(0, 0, selection.start); + assertPosition(100, 5, selection.end); }, "test: navigate word right" : function() { @@ -82,38 +75,38 @@ var NavigationTest = TestCase("NavigationTest", var editor = new ace.Editor(doc, new MockRenderer()); editor.navigateDown(); - this.assertPosition(1, 0, editor.getCursorPosition()); + assertPosition(1, 0, editor.getCursorPosition()); editor.navigateWordRight(); - this.assertPosition(1, 1, editor.getCursorPosition()); + assertPosition(1, 1, editor.getCursorPosition()); editor.navigateWordRight(); - this.assertPosition(1, 5, editor.getCursorPosition()); + assertPosition(1, 5, editor.getCursorPosition()); editor.navigateWordRight(); - this.assertPosition(1, 6, editor.getCursorPosition()); + assertPosition(1, 6, editor.getCursorPosition()); editor.navigateWordRight(); - this.assertPosition(1, 13, editor.getCursorPosition()); + assertPosition(1, 13, editor.getCursorPosition()); editor.navigateWordRight(); - this.assertPosition(1, 15, editor.getCursorPosition()); + assertPosition(1, 15, editor.getCursorPosition()); editor.navigateWordRight(); - this.assertPosition(1, 18, editor.getCursorPosition()); + assertPosition(1, 18, editor.getCursorPosition()); editor.navigateWordRight(); - this.assertPosition(1, 20, editor.getCursorPosition()); + assertPosition(1, 20, editor.getCursorPosition()); editor.navigateWordRight(); - this.assertPosition(1, 22, editor.getCursorPosition()); + assertPosition(1, 22, editor.getCursorPosition()); editor.navigateWordRight(); - this.assertPosition(1, 23, editor.getCursorPosition()); + assertPosition(1, 23, editor.getCursorPosition()); // wrap line editor.navigateWordRight(); - this.assertPosition(2, 0, editor.getCursorPosition()); + assertPosition(2, 0, editor.getCursorPosition()); }, "test: select word right if cursor in word" : function() { @@ -123,7 +116,7 @@ var NavigationTest = TestCase("NavigationTest", editor.moveCursorTo(0, 2); editor.navigateWordRight(); - this.assertPosition(0, 4, editor.getCursorPosition()); + assertPosition(0, 4, editor.getCursorPosition()); }, "test: navigate word left" : function() { @@ -133,38 +126,38 @@ var NavigationTest = TestCase("NavigationTest", editor.navigateDown(); editor.navigateLineEnd(); - this.assertPosition(1, 23, editor.getCursorPosition()); + assertPosition(1, 23, editor.getCursorPosition()); editor.navigateWordLeft(); - this.assertPosition(1, 22, editor.getCursorPosition()); + assertPosition(1, 22, editor.getCursorPosition()); editor.navigateWordLeft(); - this.assertPosition(1, 20, editor.getCursorPosition()); + assertPosition(1, 20, editor.getCursorPosition()); editor.navigateWordLeft(); - this.assertPosition(1, 18, editor.getCursorPosition()); + assertPosition(1, 18, editor.getCursorPosition()); editor.navigateWordLeft(); - this.assertPosition(1, 15, editor.getCursorPosition()); + assertPosition(1, 15, editor.getCursorPosition()); editor.navigateWordLeft(); - this.assertPosition(1, 13, editor.getCursorPosition()); + assertPosition(1, 13, editor.getCursorPosition()); editor.navigateWordLeft(); - this.assertPosition(1, 6, editor.getCursorPosition()); + assertPosition(1, 6, editor.getCursorPosition()); editor.navigateWordLeft(); - this.assertPosition(1, 5, editor.getCursorPosition()); + assertPosition(1, 5, editor.getCursorPosition()); editor.navigateWordLeft(); - this.assertPosition(1, 1, editor.getCursorPosition()); + assertPosition(1, 1, editor.getCursorPosition()); editor.navigateWordLeft(); - this.assertPosition(1, 0, editor.getCursorPosition()); + assertPosition(1, 0, editor.getCursorPosition()); // wrap line editor.navigateWordLeft(); - this.assertPosition(0, 2, editor.getCursorPosition()); + assertPosition(0, 2, editor.getCursorPosition()); }, "test: select word left if cursor in word" : function() { @@ -174,7 +167,7 @@ var NavigationTest = TestCase("NavigationTest", editor.moveCursorTo(0, 8); editor.navigateWordLeft(); - this.assertPosition(0, 5, editor.getCursorPosition()); + assertPosition(0, 5, editor.getCursorPosition()); }, "test: select word right and select" : function() { @@ -186,8 +179,8 @@ var NavigationTest = TestCase("NavigationTest", var selection = editor.getSelectionRange(); - this.assertPosition(0, 0, selection.start); - this.assertPosition(0, 4, selection.end); + assertPosition(0, 0, selection.start); + assertPosition(0, 4, selection.end); }, "test: select word left and select" : function() { @@ -199,7 +192,7 @@ var NavigationTest = TestCase("NavigationTest", var selection = editor.getSelectionRange(); - this.assertPosition(0, 0, selection.start); - this.assertPosition(0, 3, selection.end); + assertPosition(0, 0, selection.start); + assertPosition(0, 3, selection.end); } }); diff --git a/test/TextEditTest.js b/test/TextEditTest.js new file mode 100644 index 00000000..0a1e5b82 --- /dev/null +++ b/test/TextEditTest.js @@ -0,0 +1,34 @@ +var TextEditTest = TestCase("TextEditTest", +{ + "test: delete line from the middle" : function() { + var doc = new ace.TextDocument(["a", "b", "c", "d"].join("\n")); + var editor = new ace.Editor(doc, new MockRenderer()); + + editor.moveCursorTo(1, 1); + editor.removeLine(); + + assertEquals("a\nc\nd", doc.toString()); + assertPosition(1, 0, editor.getCursorPosition()); + }, + + "test: delete first line" : function() { + var doc = new ace.TextDocument(["a", "b", "c"].join("\n")); + var editor = new ace.Editor(doc, new MockRenderer()); + + editor.removeLine(); + + assertEquals("b\nc", doc.toString()); + assertPosition(0, 0, editor.getCursorPosition()); + }, + + "test: delete last" : function() { + var doc = new ace.TextDocument(["a", "b", "c"].join("\n")); + var editor = new ace.Editor(doc, new MockRenderer()); + + editor.moveCursorTo(2, 1); + editor.removeLine(); + + assertEquals("a\nb", doc.toString()); + assertPosition(1, 0, editor.getCursorPosition()); + } +}); \ No newline at end of file diff --git a/test/assertions.js b/test/assertions.js new file mode 100644 index 00000000..c575bf5d --- /dev/null +++ b/test/assertions.js @@ -0,0 +1,4 @@ +assertPosition = function(row, column, cursor) { + assertEquals(row, cursor.row); + assertEquals(column, cursor.column); +};