From 09c873c7808e6fcef85648da4fffa4ad8a2d6208 Mon Sep 17 00:00:00 2001 From: Fabian Jakobs Date: Tue, 13 Apr 2010 10:10:56 +0200 Subject: [PATCH] goto line functionality --- src/Editor.js | 28 ++++++++++++++++++++--- src/KeyBinding.js | 13 ++++++++++- test/MockRenderer.js | 4 ++-- test/NavigationTest.js | 50 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 89 insertions(+), 6 deletions(-) diff --git a/src/Editor.js b/src/Editor.js index af0e11b0..eda02314 100644 --- a/src/Editor.js +++ b/src/Editor.js @@ -21,7 +21,7 @@ ace.Editor = function(doc, renderer) { renderer.setDocument(doc); this.tokenizer = new ace.BackgroundTokenizer(new ace.Tokenizer( - ace.XML.RULES), ace.bind(this.onTokenizerUpdate, this)); + ace.JavaScript.RULES), ace.bind(this.onTokenizerUpdate, this)); this.tokenizer.setLines(doc.lines); renderer.setTokenizer(this.tokenizer); @@ -31,6 +31,8 @@ ace.Editor = function(doc, renderer) { column : 0 }; + + this.selectionAnchor = null; this.selectionLead = null; this.selection = null; @@ -260,6 +262,14 @@ ace.Editor.prototype.getLastVisibleRow = function() { return this.renderer.getLastVisibleRow(); }; +ace.Editor.prototype.isRowVisible = function(row) { + return (row >= this.getFirstVisibleRow() && row <= this.getLastVisibleRow()); +}; + +ace.Editor.prototype.getVisibleRowCount = function() { + return this.getLastVisibleRow() - this.getFirstVisibleRow() + 1; +}; + ace.Editor.prototype.getPageDownRow = function() { return this.renderer.getLastVisibleRow() - 1; }; @@ -283,6 +293,12 @@ ace.Editor.prototype.scrollToRow = function(row) { this.renderer.scrollToRow(row); }; +ace.Editor.prototype.navigateTo = function(row, column) { + this.clearSelection(); + this.moveCursorTo(row, column); + this.renderer.scrollCursorIntoView(); +}; + ace.Editor.prototype.navigateUp = function() { this.clearSelection(); this.moveCursorUp(); @@ -486,6 +502,13 @@ ace.Editor.prototype.moveCursorTo = function(row, column) { this.updateCursor(); }; +ace.Editor.prototype.gotoLine = function(lineNumber) { + this.moveCursorTo(lineNumber, 0); + if (!this.isRowVisible(this.cursor.row)) { + this.scrollToRow(lineNumber - Math.floor(this.getVisibleRowCount() / 2)); + } +}, + ace.Editor.prototype.getCursorPosition = function() { return { row : this.cursor.row, @@ -609,8 +632,7 @@ ace.Editor.prototype.selectLineEnd = function() { }; ace.Editor.prototype.selectPageDown = function() { - var visibleRows = this.getLastVisibleRow() - this.getFirstVisibleRow(); - var row = this.getPageDownRow() + Math.round(visibleRows / 2); + var row = this.getPageDownRow() + Math.floor(this.getVisibleRowCount() / 2); this.scrollPageDown(); diff --git a/src/KeyBinding.js b/src/KeyBinding.js index a347f6f6..1e09a731 100644 --- a/src/KeyBinding.js +++ b/src/KeyBinding.js @@ -16,7 +16,8 @@ var keys = { BACKSPACE : 8, TAB : 9, A : 65, - D: 68 + D: 68, + L: 76 }; ace.KeyBinding = function(element, host) { @@ -38,6 +39,16 @@ ace.KeyBinding = function(element, host) { } break; + case keys.L: + if (e.metaKey) { + var line = parseInt(prompt("Enter line number:")); + if (!isNaN(line)) { + host.gotoLine(line); + return ace.stopEvent(e); + } + } + break; + case keys.UP: if (e.metaKey && e.shiftKey) { host.selectFileStart(); diff --git a/test/MockRenderer.js b/test/MockRenderer.js index a634693a..dfe202ee 100644 --- a/test/MockRenderer.js +++ b/test/MockRenderer.js @@ -1,11 +1,11 @@ -MockRenderer = function() { +MockRenderer = function(visibleRowCount) { this.container = document.createElement("div"); this.cursor = { row : 0, column : 0 }; - this.visibleRowCount = 20; + this.visibleRowCount = visibleRowCount || 20; this.layerConfig = { firstVisibleRow : 0, diff --git a/test/NavigationTest.js b/test/NavigationTest.js index b06578fd..1d71fc0e 100644 --- a/test/NavigationTest.js +++ b/test/NavigationTest.js @@ -194,5 +194,55 @@ var NavigationTest = TestCase("NavigationTest", assertPosition(0, 0, selection.start); assertPosition(0, 3, selection.end); + }, + + "test: goto hidden line should scroll the line into the middle of the viewport" : function() { + var editor = new ace.Editor(this.createTextDocument(200, 5), + new MockRenderer()); + + editor.navigateTo(0, 0); + editor.gotoLine(100); + assertPosition(100, 0, editor.getCursorPosition()); + assertEquals(90, editor.getFirstVisibleRow()); + + editor.navigateTo(100, 0); + editor.gotoLine(10); + assertPosition(10, 0, editor.getCursorPosition()); + assertEquals(0, editor.getFirstVisibleRow()); + + editor.navigateTo(100, 0); + editor.gotoLine(5); + assertPosition(5, 0, editor.getCursorPosition()); + assertEquals(0, editor.getFirstVisibleRow()); + + editor.navigateTo(100, 0); + editor.gotoLine(0); + assertPosition(0, 0, editor.getCursorPosition()); + assertEquals(0, editor.getFirstVisibleRow()); + + editor.navigateTo(0, 0); + editor.gotoLine(190); + assertPosition(190, 0, editor.getCursorPosition()); + assertEquals(180, editor.getFirstVisibleRow()); + + editor.navigateTo(0, 0); + editor.gotoLine(195); + assertPosition(195, 0, editor.getCursorPosition()); + assertEquals(180, editor.getFirstVisibleRow()); + }, + + "test: goto visible line should only move the cursor and not scroll": function() { + var editor = new ace.Editor(this.createTextDocument(200, 5), + new MockRenderer()); + + editor.navigateTo(0, 0); + editor.gotoLine(11); + assertPosition(11, 0, editor.getCursorPosition()); + assertEquals(0, editor.getFirstVisibleRow()); + + editor.navigateTo(30, 0); + editor.gotoLine(32); + assertPosition(32, 0, editor.getCursorPosition()); + assertEquals(30, editor.getFirstVisibleRow()); } });