Remember Column during navigation
This commit is contained in:
parent
b0f9097d3b
commit
1d7ed0d3dd
6 changed files with 174 additions and 126 deletions
|
|
@ -562,4 +562,51 @@ ace.Document = function(text, mode) {
|
|||
return Math.max(0, Math.min(row, this.lines.length-1));
|
||||
};
|
||||
|
||||
this.documentToScreenColumn = function(row, docColumn) {
|
||||
var tabSize = this.getTabSize();
|
||||
|
||||
var screenColumn = 0;
|
||||
var remaining = docColumn;
|
||||
|
||||
var line = this.getLine(row).split("\t");
|
||||
for (var i=0; i<line.length; i++) {
|
||||
var len = line[i].length;
|
||||
if (remaining > len) {
|
||||
remaining -= (len + 1);
|
||||
screenColumn += len + tabSize;
|
||||
}
|
||||
else {
|
||||
screenColumn += remaining;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return screenColumn;
|
||||
};
|
||||
|
||||
this.screenToDocumentColumn = function(row, screenColumn) {
|
||||
var tabSize = this.getTabSize();
|
||||
|
||||
var docColumn = 0;
|
||||
var remaining = screenColumn;
|
||||
|
||||
var line = this.getLine(row).split("\t");
|
||||
for (var i=0; i<line.length; i++) {
|
||||
var len = line[i].length;
|
||||
if (remaining >= len + tabSize) {
|
||||
remaining -= (len + tabSize);
|
||||
docColumn += (len + 1);
|
||||
}
|
||||
else if (remaining > len){
|
||||
docColumn += len;
|
||||
break;
|
||||
}
|
||||
else {
|
||||
docColumn += remaining;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return docColumn;
|
||||
};
|
||||
|
||||
}).call(ace.Document.prototype);
|
||||
|
|
|
|||
|
|
@ -93,6 +93,7 @@ ace.Editor = function(renderer, doc) {
|
|||
this.doc.addEventListener("changeBreakpoint", this.$onDocumentChangeBreakpoint);
|
||||
|
||||
this.selection = doc.getSelection();
|
||||
this.$desiredColumn = 0;
|
||||
|
||||
this.$onCursorChange = ace.bind(this.onCursorChange, this);
|
||||
this.selection.addEventListener("changeCursor", this.$onCursorChange);
|
||||
|
|
@ -279,10 +280,12 @@ ace.Editor = function(renderer, doc) {
|
|||
|
||||
this.onMouseDoubleClick = function(e) {
|
||||
this.selection.selectWord();
|
||||
this.$updateDesiredColumn();
|
||||
};
|
||||
|
||||
this.onMouseTripleClick = function(e) {
|
||||
this.selection.selectLine();
|
||||
this.$updateDesiredColumn();
|
||||
};
|
||||
|
||||
this.onMouseWheel = function(e) {
|
||||
|
|
@ -467,6 +470,7 @@ ace.Editor = function(renderer, doc) {
|
|||
var addedColumns = this.doc.indentRows(this.getSelectionRange(), indentString);
|
||||
|
||||
this.selection.shiftSelection(addedColumns);
|
||||
this.$updateDesiredColumn();
|
||||
};
|
||||
|
||||
this.blockOutdent = function(indentString) {
|
||||
|
|
@ -477,6 +481,7 @@ ace.Editor = function(renderer, doc) {
|
|||
var addedColumns = this.doc.outdentRows(this.getSelectionRange(), indentString);
|
||||
|
||||
this.selection.shiftSelection(addedColumns);
|
||||
this.$updateDesiredColumn();
|
||||
};
|
||||
|
||||
this.toggleCommentLines = function() {
|
||||
|
|
@ -656,14 +661,17 @@ ace.Editor = function(renderer, doc) {
|
|||
|
||||
this.clearSelection = function() {
|
||||
this.selection.clearSelection();
|
||||
this.$updateDesiredColumn();
|
||||
};
|
||||
|
||||
this.moveCursorTo = function(row, column) {
|
||||
this.selection.moveCursorTo(row, column);
|
||||
this.$updateDesiredColumn();
|
||||
};
|
||||
|
||||
this.moveCursorToPosition = function(pos) {
|
||||
this.selection.moveCursorToPosition(pos);
|
||||
this.$updateDesiredColumn();
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -680,16 +688,34 @@ ace.Editor = function(renderer, doc) {
|
|||
this.navigateTo = function(row, column) {
|
||||
this.clearSelection();
|
||||
this.moveCursorTo(row, column);
|
||||
this.$updateDesiredColumn(column);
|
||||
};
|
||||
|
||||
this.navigateUp = function() {
|
||||
this.clearSelection();
|
||||
this.selection.moveCursorUp();
|
||||
this.selection.clearSelection();
|
||||
this.selection.moveCursorBy(-1, 0);
|
||||
|
||||
if (this.$desiredColumn) {
|
||||
var cursor = this.getCursorPosition();
|
||||
var column = this.doc.screenToDocumentColumn(cursor.row, this.$desiredColumn);
|
||||
this.selection.moveCursorTo(cursor.row, column);
|
||||
}
|
||||
};
|
||||
|
||||
this.navigateDown = function() {
|
||||
this.clearSelection();
|
||||
this.selection.moveCursorDown();
|
||||
this.selection.clearSelection();
|
||||
this.selection.moveCursorBy(1, 0);
|
||||
|
||||
if (this.$desiredColumn) {
|
||||
var cursor = this.getCursorPosition();
|
||||
var column = this.doc.screenToDocumentColumn(cursor.row, this.$desiredColumn);
|
||||
this.selection.moveCursorTo(cursor.row, column);
|
||||
}
|
||||
};
|
||||
|
||||
this.$updateDesiredColumn = function() {
|
||||
var cursor = this.getCursorPosition();
|
||||
this.$desiredColumn = this.doc.documentToScreenColumn(cursor.row, cursor.column);
|
||||
};
|
||||
|
||||
this.navigateLeft = function() {
|
||||
|
|
@ -715,39 +741,40 @@ ace.Editor = function(renderer, doc) {
|
|||
};
|
||||
|
||||
this.navigateLineStart = function() {
|
||||
this.clearSelection();
|
||||
this.selection.moveCursorLineStart();
|
||||
this.clearSelection();
|
||||
};
|
||||
|
||||
this.navigateLineEnd = function() {
|
||||
this.clearSelection();
|
||||
this.selection.moveCursorLineEnd();
|
||||
this.clearSelection();
|
||||
};
|
||||
|
||||
this.navigateFileEnd = function() {
|
||||
this.clearSelection();
|
||||
this.selection.moveCursorFileEnd();
|
||||
this.clearSelection();
|
||||
};
|
||||
|
||||
this.navigateFileStart = function() {
|
||||
this.clearSelection();
|
||||
this.selection.moveCursorFileStart();
|
||||
this.clearSelection();
|
||||
};
|
||||
|
||||
this.navigateWordRight = function() {
|
||||
this.clearSelection();
|
||||
this.selection.moveCursorWordRight();
|
||||
this.clearSelection();
|
||||
};
|
||||
|
||||
this.navigateWordLeft = function() {
|
||||
this.clearSelection();
|
||||
this.selection.moveCursorWordLeft();
|
||||
this.clearSelection();
|
||||
};
|
||||
|
||||
this.replace = function(replacement) {
|
||||
var range = this.$tryReplace(this.getSelectionRange(), replacement);
|
||||
if (range !== null)
|
||||
this.selection.setSelectionRange(range);
|
||||
this.$updateDesiredColumn();
|
||||
},
|
||||
|
||||
this.replaceAll = function(replacement) {
|
||||
|
|
@ -763,6 +790,7 @@ ace.Editor = function(renderer, doc) {
|
|||
this.$tryReplace(range, replacement);
|
||||
}
|
||||
this.selection.setSelectionRange(range);
|
||||
this.$updateDesiredColumn();
|
||||
},
|
||||
|
||||
this.$tryReplace = function(range, replacement) {
|
||||
|
|
@ -800,8 +828,10 @@ ace.Editor = function(renderer, doc) {
|
|||
});
|
||||
|
||||
var range = this.$search.find(this.doc);
|
||||
if (range)
|
||||
if (range) {
|
||||
this.selection.setSelectionRange(range);
|
||||
this.$updateDesiredColumn();
|
||||
}
|
||||
};
|
||||
|
||||
this.undo = function() {
|
||||
|
|
|
|||
|
|
@ -250,57 +250,10 @@ ace.VirtualRenderer = function(container) {
|
|||
this.$documentToScreenPosition = function(pos) {
|
||||
return {
|
||||
row: pos.row,
|
||||
column: this.$documentToScreenColumn(pos.row, pos.column)
|
||||
column: this.doc.documentToScreenColumn(pos.row, pos.column)
|
||||
};
|
||||
};
|
||||
|
||||
this.$documentToScreenColumn = function(row, docColumn) {
|
||||
var tabSize = this.doc.getTabSize();
|
||||
|
||||
var screenColumn = 0;
|
||||
var remaining = docColumn;
|
||||
|
||||
var line = this.doc.getLine(row).split("\t");
|
||||
for (var i=0; i<line.length; i++) {
|
||||
var len = line[i].length;
|
||||
if (remaining > len) {
|
||||
remaining -= (len + 1);
|
||||
screenColumn += len + tabSize;
|
||||
}
|
||||
else {
|
||||
screenColumn += remaining;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return screenColumn;
|
||||
};
|
||||
|
||||
this.$screenToDocumentColumn = function(row, screenColumn) {
|
||||
var tabSize = this.doc.getTabSize();
|
||||
|
||||
var docColumn = 0;
|
||||
var remaining = screenColumn;
|
||||
|
||||
var line = this.doc.getLine(row).split("\t");
|
||||
for (var i=0; i<line.length; i++) {
|
||||
var len = line[i].length;
|
||||
if (remaining >= len + tabSize) {
|
||||
remaining -= (len + tabSize);
|
||||
docColumn += (len + 1);
|
||||
}
|
||||
else if (remaining > len){
|
||||
docColumn += len;
|
||||
break;
|
||||
}
|
||||
else {
|
||||
docColumn += remaining;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return docColumn;
|
||||
};
|
||||
|
||||
this.hideCursor = function() {
|
||||
this.$cursorLayer.hideCursor();
|
||||
};
|
||||
|
|
@ -369,7 +322,7 @@ ace.VirtualRenderer = function(container) {
|
|||
|
||||
return {
|
||||
row : row,
|
||||
column : this.$screenToDocumentColumn(Math.max(0, Math.min(row, this.doc.getLength()-1)), col)
|
||||
column : this.doc.screenToDocumentColumn(Math.max(0, Math.min(row, this.doc.getLength()-1)), col)
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -162,5 +162,51 @@ var TextDocumentTest = new TestCase("TextDocumentTest", {
|
|||
undoManager.undo();
|
||||
doc.$informUndoManager.call();
|
||||
assertEquals(initialText, doc.toString());
|
||||
},
|
||||
|
||||
"test: convert document to screen coordinates" : function() {
|
||||
var doc = new ace.Document("01234\t567890\t1234");
|
||||
doc.setTabSize(4);
|
||||
|
||||
assertEquals(0, doc.documentToScreenColumn(0, 0));
|
||||
assertEquals(4, doc.documentToScreenColumn(0, 4));
|
||||
assertEquals(5, doc.documentToScreenColumn(0, 5));
|
||||
assertEquals(9, doc.documentToScreenColumn(0, 6));
|
||||
assertEquals(15, doc.documentToScreenColumn(0, 12));
|
||||
assertEquals(19, doc.documentToScreenColumn(0, 13));
|
||||
|
||||
doc.setTabSize(2);
|
||||
|
||||
assertEquals(0, doc.documentToScreenColumn(0, 0));
|
||||
assertEquals(4, doc.documentToScreenColumn(0, 4));
|
||||
assertEquals(5, doc.documentToScreenColumn(0, 5));
|
||||
assertEquals(7, doc.documentToScreenColumn(0, 6));
|
||||
assertEquals(13, doc.documentToScreenColumn(0, 12));
|
||||
assertEquals(15, doc.documentToScreenColumn(0, 13));
|
||||
},
|
||||
|
||||
"test: convert document to scrren coordinates with leading tabs": function() {
|
||||
var doc = new ace.Document("\t\t123");
|
||||
doc.setTabSize(4);
|
||||
|
||||
assertEquals(0, doc.documentToScreenColumn(0, 0));
|
||||
assertEquals(4, doc.documentToScreenColumn(0, 1));
|
||||
assertEquals(8, doc.documentToScreenColumn(0, 2));
|
||||
assertEquals(9, doc.documentToScreenColumn(0, 3));
|
||||
},
|
||||
|
||||
"test: convert screen to document coordinates" : function() {
|
||||
var doc = new ace.Document("01234\t567890\t1234");
|
||||
doc.setTabSize(4);
|
||||
|
||||
assertEquals(0, doc.screenToDocumentColumn(0, 0));
|
||||
assertEquals(4, doc.screenToDocumentColumn(0, 4));
|
||||
assertEquals(5, doc.screenToDocumentColumn(0, 5));
|
||||
assertEquals(5, doc.screenToDocumentColumn(0, 6));
|
||||
assertEquals(5, doc.screenToDocumentColumn(0, 7));
|
||||
assertEquals(5, doc.screenToDocumentColumn(0, 8));
|
||||
assertEquals(6, doc.screenToDocumentColumn(0, 9));
|
||||
assertEquals(12, doc.screenToDocumentColumn(0, 15));
|
||||
assertEquals(13, doc.screenToDocumentColumn(0, 19));
|
||||
}
|
||||
});
|
||||
|
|
@ -11,7 +11,7 @@ var NavigationTest = TestCase("NavigationTest",
|
|||
var editor = new ace.Editor(new MockRenderer(), doc);
|
||||
|
||||
editor.navigateFileEnd();
|
||||
var cursor = editor.getSelection().getCursor();
|
||||
var cursor = editor.getCursorPosition();
|
||||
|
||||
assertTrue(editor.getFirstVisibleRow() <= cursor.row);
|
||||
assertTrue(editor.getLastVisibleRow() >= cursor.row);
|
||||
|
|
@ -32,32 +32,32 @@ var NavigationTest = TestCase("NavigationTest",
|
|||
|
||||
editor.navigateTo(0, 0);
|
||||
editor.gotoLine(101);
|
||||
assertPosition(100, 0, editor.getSelection().getCursor());
|
||||
assertPosition(100, 0, editor.getCursorPosition());
|
||||
assertEquals(90, editor.getFirstVisibleRow());
|
||||
|
||||
editor.navigateTo(100, 0);
|
||||
editor.gotoLine(11);
|
||||
assertPosition(10, 0, editor.getSelection().getCursor());
|
||||
assertPosition(10, 0, editor.getCursorPosition());
|
||||
assertEquals(0, editor.getFirstVisibleRow());
|
||||
|
||||
editor.navigateTo(100, 0);
|
||||
editor.gotoLine(6);
|
||||
assertPosition(5, 0, editor.getSelection().getCursor());
|
||||
assertPosition(5, 0, editor.getCursorPosition());
|
||||
assertEquals(0, editor.getFirstVisibleRow());
|
||||
|
||||
editor.navigateTo(100, 0);
|
||||
editor.gotoLine(1);
|
||||
assertPosition(0, 0, editor.getSelection().getCursor());
|
||||
assertPosition(0, 0, editor.getCursorPosition());
|
||||
assertEquals(0, editor.getFirstVisibleRow());
|
||||
|
||||
editor.navigateTo(0, 0);
|
||||
editor.gotoLine(191);
|
||||
assertPosition(190, 0, editor.getSelection().getCursor());
|
||||
assertPosition(190, 0, editor.getCursorPosition());
|
||||
assertEquals(180, editor.getFirstVisibleRow());
|
||||
|
||||
editor.navigateTo(0, 0);
|
||||
editor.gotoLine(196);
|
||||
assertPosition(195, 0, editor.getSelection().getCursor());
|
||||
assertPosition(195, 0, editor.getCursorPosition());
|
||||
assertEquals(180, editor.getFirstVisibleRow());
|
||||
},
|
||||
|
||||
|
|
@ -66,12 +66,41 @@ var NavigationTest = TestCase("NavigationTest",
|
|||
|
||||
editor.navigateTo(0, 0);
|
||||
editor.gotoLine(12);
|
||||
assertPosition(11, 0, editor.getSelection().getCursor());
|
||||
assertPosition(11, 0, editor.getCursorPosition());
|
||||
assertEquals(0, editor.getFirstVisibleRow());
|
||||
|
||||
editor.navigateTo(30, 0);
|
||||
editor.gotoLine(33);
|
||||
assertPosition(32, 0, editor.getSelection().getCursor());
|
||||
assertPosition(32, 0, editor.getCursorPosition());
|
||||
assertEquals(30, editor.getFirstVisibleRow());
|
||||
},
|
||||
|
||||
"test: navigate from the end of a long line down to a short line and back should maintain the curser column": function() {
|
||||
var editor = new ace.Editor(new MockRenderer(), new ace.Document(["123456", "1"]));
|
||||
|
||||
editor.navigateTo(0, 6);
|
||||
assertPosition(0, 6, editor.getCursorPosition());
|
||||
|
||||
editor.navigateDown();
|
||||
assertPosition(1, 1, editor.getCursorPosition());
|
||||
|
||||
editor.navigateUp();
|
||||
assertPosition(0, 6, editor.getCursorPosition());
|
||||
},
|
||||
|
||||
"test: reset desired column on navigate left or right": function() {
|
||||
var editor = new ace.Editor(new MockRenderer(), new ace.Document(["123456", "12"]));
|
||||
|
||||
editor.navigateTo(0, 6);
|
||||
assertPosition(0, 6, editor.getCursorPosition());
|
||||
|
||||
editor.navigateDown();
|
||||
assertPosition(1, 2, editor.getCursorPosition());
|
||||
|
||||
editor.navigateLeft();
|
||||
assertPosition(1, 1, editor.getCursorPosition());
|
||||
|
||||
editor.navigateUp();
|
||||
assertPosition(0, 1, editor.getCursorPosition());
|
||||
}
|
||||
});
|
||||
|
|
@ -1,62 +1,5 @@
|
|||
var VirtualRendererTest = new TestCase("VirtualRendererTest", {
|
||||
|
||||
"test: convert document to screen coordinates" : function() {
|
||||
var el = document.createElement("div");
|
||||
var renderer = new ace.VirtualRenderer(el);
|
||||
|
||||
var doc = new ace.Document("01234\t567890\t1234");
|
||||
doc.setTabSize(4);
|
||||
renderer.setDocument(doc);
|
||||
|
||||
assertEquals(0, renderer.$documentToScreenColumn(0, 0));
|
||||
assertEquals(4, renderer.$documentToScreenColumn(0, 4));
|
||||
assertEquals(5, renderer.$documentToScreenColumn(0, 5));
|
||||
assertEquals(9, renderer.$documentToScreenColumn(0, 6));
|
||||
assertEquals(15, renderer.$documentToScreenColumn(0, 12));
|
||||
assertEquals(19, renderer.$documentToScreenColumn(0, 13));
|
||||
|
||||
doc.setTabSize(2);
|
||||
|
||||
assertEquals(0, renderer.$documentToScreenColumn(0, 0));
|
||||
assertEquals(4, renderer.$documentToScreenColumn(0, 4));
|
||||
assertEquals(5, renderer.$documentToScreenColumn(0, 5));
|
||||
assertEquals(7, renderer.$documentToScreenColumn(0, 6));
|
||||
assertEquals(13, renderer.$documentToScreenColumn(0, 12));
|
||||
assertEquals(15, renderer.$documentToScreenColumn(0, 13));
|
||||
},
|
||||
|
||||
"test: convert document to scrren coordinates with leading tabs": function() {
|
||||
var el = document.createElement("div");
|
||||
var renderer = new ace.VirtualRenderer(el);
|
||||
|
||||
var doc = new ace.Document("\t\t123");
|
||||
doc.setTabSize(4);
|
||||
renderer.setDocument(doc);
|
||||
assertEquals(0, renderer.$documentToScreenColumn(0, 0));
|
||||
assertEquals(4, renderer.$documentToScreenColumn(0, 1));
|
||||
assertEquals(8, renderer.$documentToScreenColumn(0, 2));
|
||||
assertEquals(9, renderer.$documentToScreenColumn(0, 3));
|
||||
},
|
||||
|
||||
"test: convert screen to document coordinates" : function() {
|
||||
var el = document.createElement("div");
|
||||
var renderer = new ace.VirtualRenderer(el);
|
||||
|
||||
var doc = new ace.Document("01234\t567890\t1234");
|
||||
doc.setTabSize(4);
|
||||
renderer.setDocument(doc);
|
||||
|
||||
assertEquals(0, renderer.$screenToDocumentColumn(0, 0));
|
||||
assertEquals(4, renderer.$screenToDocumentColumn(0, 4));
|
||||
assertEquals(5, renderer.$screenToDocumentColumn(0, 5));
|
||||
assertEquals(5, renderer.$screenToDocumentColumn(0, 6));
|
||||
assertEquals(5, renderer.$screenToDocumentColumn(0, 7));
|
||||
assertEquals(5, renderer.$screenToDocumentColumn(0, 8));
|
||||
assertEquals(6, renderer.$screenToDocumentColumn(0, 9));
|
||||
assertEquals(12, renderer.$screenToDocumentColumn(0, 15));
|
||||
assertEquals(13, renderer.$screenToDocumentColumn(0, 19));
|
||||
},
|
||||
|
||||
"test: screen2text the column should be rounded to the next character edge" : function() {
|
||||
var el = document.createElement("div");
|
||||
el.style.left = "0px";
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue