From a931d239d762aa9c82dc42adbc2c18cea533a362 Mon Sep 17 00:00:00 2001 From: nightwing Date: Thu, 17 Nov 2011 20:55:54 +0400 Subject: [PATCH 1/8] fix rendering of wrapped foldlines --- lib/ace/edit_session.js | 54 ++++++++++++++++++++++------------------- lib/ace/layer/text.js | 9 ++++--- 2 files changed, 34 insertions(+), 29 deletions(-) diff --git a/lib/ace/edit_session.js b/lib/ace/edit_session.js index 7b7f9a7d..621a6211 100644 --- a/lib/ace/edit_session.js +++ b/lib/ace/edit_session.js @@ -1061,9 +1061,11 @@ var EditSession = function(text, mode) { var row = firstRow; lastRow = Math.min(lastRow, lines.length - 1); while (row <= lastRow) { - foldLine = this.getFoldLine(row); + foldLine = this.getFoldLine(row, foldLine); if (!foldLine) { tokens = this.$getDisplayTokens(lang.stringTrimRight(lines[row])); + wrapData[row] = this.$computeWrapSplits(tokens, wrapLimit, tabSize); + row ++; } else { tokens = []; foldLine.walk( @@ -1087,16 +1089,13 @@ var EditSession = function(text, mode) { lines[foldLine.end.row].length + 1 ); // Remove spaces/tabs from the back of the token array. - while (tokens.length != 0 - && tokens[tokens.length - 1] >= SPACE) - { + while (tokens.length != 0 && tokens[tokens.length - 1] >= SPACE) tokens.pop(); - } - } - wrapData[row] = - this.$computeWrapSplits(tokens, wrapLimit, tabSize); - row = this.getRowFoldEnd(row) + 1; + wrapData[foldLine.start.row] + = this.$computeWrapSplits(tokens, wrapLimit, tabSize); + row = foldLine.end.row + 1; + } } }; @@ -1414,18 +1413,18 @@ var EditSession = function(text, mode) { } } - if (foldLine && foldLine.start.row <= docRow) + if (foldLine && foldLine.start.row <= docRow) { line = this.getFoldDisplayLine(foldLine); - else { + docRow = foldLine.start.row; + } else { line = this.getLine(docRow); foldLine = null; } - var splits = []; if (this.$useWrapMode) { - splits = this.$wrapData[docRow]; + var splits = this.$wrapData[docRow]; if (splits) { - column = splits[screenRow - row] + column = splits[screenRow - row]; if(screenRow > row && splits.length) { docColumn = splits[screenRow - row - 1] || splits[splits.length - 1]; line = line.substring(docColumn); @@ -1436,7 +1435,7 @@ var EditSession = function(text, mode) { docColumn += this.$getStringScreenWidth(line, screenColumn)[1]; // clip row at the end of the document - if (row + splits.length < screenRow) + if (docRow > maxRow) docColumn = Number.MAX_VALUE; // Need to do some clamping action here. @@ -1577,24 +1576,29 @@ var EditSession = function(text, mode) { this.getScreenLength = function() { var screenRows = 0; - var lastFoldLine = null; - var foldLine = null; + var fold = null; if (!this.$useWrapMode) { screenRows = this.getLength(); // Remove the folded lines again. var foldData = this.$foldData; for (var i = 0; i < foldData.length; i++) { - foldLine = foldData[i]; - screenRows -= foldLine.end.row - foldLine.start.row; + fold = foldData[i]; + screenRows -= fold.end.row - fold.start.row; } } else { - for (var row = 0; row < this.$wrapData.length; row++) { - if (foldLine = this.getFoldLine(row, lastFoldLine)) { - row = foldLine.end.row; - screenRows += 1; - } else { - screenRows += this.$wrapData[row].length + 1; + var lastRow = this.$wrapData.length; + var row = 0, i = 0; + var fold = this.$foldData[i++]; + var foldStart = fold ? fold.start.row :Infinity; + + while (row < lastRow) { + screenRows += this.$wrapData[row].length + 1; + row ++; + if (row > foldStart) { + row = fold.end.row+1; + fold = this.$foldData[i++]; + foldStart = fold ?fold.start.row :Infinity; } } } diff --git a/lib/ace/layer/text.js b/lib/ace/layer/text.js index 5fccd803..98670b02 100644 --- a/lib/ace/layer/text.js +++ b/lib/ace/layer/text.js @@ -201,6 +201,7 @@ var Text = function(parentEl) { var foldLine = this.session.getFoldLine(row); if (foldLine) { if (foldLine.containsRow(first)) { + first = foldLine.start.row; break; } else { row = foldLine.end.row; @@ -264,12 +265,12 @@ var Text = function(parentEl) { foldStart = fold ?fold.start.row :Infinity; while (true) { - if(row > foldStart) { + if (row > foldStart) { row = fold.end.row+1; fold = this.session.getNextFoldLine(row, fold); foldStart = fold ?fold.start.row :Infinity; } - if(row > lastRow) + if (row > lastRow) break; var container = dom.createElement("div"); @@ -311,12 +312,12 @@ var Text = function(parentEl) { foldStart = fold ?fold.start.row :Infinity; while (true) { - if(row > foldStart) { + if (row > foldStart) { row = fold.end.row+1; fold = this.session.getNextFoldLine(row, fold); foldStart = fold ?fold.start.row :Infinity; } - if(row > lastRow) + if (row > lastRow) break; if (this.$useLineGroups()) From 41a1913235365664db8ef956fcde07009868b236 Mon Sep 17 00:00:00 2001 From: nightwing Date: Tue, 8 Nov 2011 10:30:29 +0400 Subject: [PATCH 2/8] findPrevious finds same text again and again if selection isn't backwards --- lib/ace/search.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/ace/search.js b/lib/ace/search.js index f7651ee6..0822697a 100644 --- a/lib/ace/search.js +++ b/lib/ace/search.js @@ -222,7 +222,7 @@ Search.SELECTION = 2; var searchSelection = this.$options.scope == Search.SELECTION; var range = this.$options.range || session.getSelection().getRange(); - var start = this.$options.start || session.getSelection().getCursor(); + var start = this.$options.start || range[searchSelection ? "start" : "end"]; var firstRow = searchSelection ? range.start.row : 0; var firstColumn = searchSelection ? range.start.column : 0; @@ -284,7 +284,7 @@ Search.SELECTION = 2; var searchSelection = this.$options.scope == Search.SELECTION; var range = this.$options.range || session.getSelection().getRange(); - var start = this.$options.start || session.getSelection().getCursor(); + var start = this.$options.start || range[searchSelection ? "end" : "start"]; var firstRow = searchSelection ? range.start.row : 0; var firstColumn = searchSelection ? range.start.column : 0; From 4a8a5bad59f3cdff0958f9f4df0673003643e580 Mon Sep 17 00:00:00 2001 From: nightwing Date: Tue, 8 Nov 2011 10:35:50 +0400 Subject: [PATCH 3/8] Fixed: selectAll+removeLines corrupts undo history --- lib/ace/editor.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ace/editor.js b/lib/ace/editor.js index 55f20c11..387757d6 100644 --- a/lib/ace/editor.js +++ b/lib/ace/editor.js @@ -852,7 +852,7 @@ var Editor = function(renderer, session) { var rows = this.$getSelectedRows(); var range; - if (rows.last == 0 || rows.last+1 < this.session.getLength()) + if (rows.first == 0 || rows.last+1 < this.session.getLength()) range = new Range(rows.first, 0, rows.last+1, 0); else range = new Range( From 647c7133251ae69bb2a4cdef5c59401000708f84 Mon Sep 17 00:00:00 2001 From: nightwing Date: Tue, 8 Nov 2011 10:44:26 +0400 Subject: [PATCH 4/8] do not lose cursor position while moving lines --- lib/ace/editor.js | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/lib/ace/editor.js b/lib/ace/editor.js index 387757d6..98d82c48 100644 --- a/lib/ace/editor.js +++ b/lib/ace/editor.js @@ -910,14 +910,24 @@ var Editor = function(renderer, session) { this.$moveLines = function(mover) { var rows = this.$getSelectedRows(); + var selection = this.selection; + if (!selection.isMultiLine()) { + var range = selection.getRange(); + var reverse = selection.isBackwards(); + } var linesMoved = mover.call(this, rows.first, rows.last); - var selection = this.selection; - selection.setSelectionAnchor(rows.last+linesMoved+1, 0); - selection.$moveSelection(function() { - selection.moveCursorTo(rows.first+linesMoved, 0); - }); + if (range) { + range.start.row += linesMoved; + range.end.row += linesMoved; + selection.setSelectionRange(range, reverse); + } else { + selection.setSelectionAnchor(rows.last+linesMoved+1, 0); + selection.$moveSelection(function() { + selection.moveCursorTo(rows.first+linesMoved, 0); + }); + } }; this.$getSelectedRows = function() { From 0d696cb25814c978e6eac84dcfd5c8dff90be82e Mon Sep 17 00:00:00 2001 From: nightwing Date: Thu, 17 Nov 2011 21:31:45 +0400 Subject: [PATCH 5/8] allow Numpad\d keys in commands --- lib/ace/lib/keys.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/lib/ace/lib/keys.js b/lib/ace/lib/keys.js index ce9285e7..19272a84 100644 --- a/lib/ace/lib/keys.js +++ b/lib/ace/lib/keys.js @@ -67,6 +67,16 @@ var Keys = (function() { 44 : "Print", 45 : "Insert", 46 : "Delete", + 96 : "Numpad0", + 97 : "Numpad1", + 98 : "Numpad2", + 99 : "Numpad3", + 100: "Numpad4", + 101: "Numpad5", + 102: "Numpad6", + 103: "Numpad7", + 104: "Numpad8", + 105: "Numpad9", 112: "F1", 113: "F2", 114: "F3", From be8cacfcc3bfcfb7b429fe32b2c17ee5e6466775 Mon Sep 17 00:00:00 2001 From: nightwing Date: Thu, 17 Nov 2011 21:58:07 +0400 Subject: [PATCH 6/8] useragent.js thinks firefox 11 is old :-) --- lib/ace/lib/useragent.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ace/lib/useragent.js b/lib/ace/lib/useragent.js index d98e7472..a544c4d1 100644 --- a/lib/ace/lib/useragent.js +++ b/lib/ace/lib/useragent.js @@ -60,7 +60,7 @@ exports.isOldIE = exports.isIE && exports.isIE < 9; exports.isGecko = exports.isMozilla = window.controllers && window.navigator.product === "Gecko"; /** oldGecko == rev < 2.0 **/ -exports.isOldGecko = exports.isGecko && /rv\:1/.test(navigator.userAgent); +exports.isOldGecko = exports.isGecko && parseInt((navigator.userAgent.match(/rv\:(\d+)/)||[])[1]) < 4; /** Is this Opera */ exports.isOpera = window.opera && Object.prototype.toString.call(window.opera) == "[object Opera]"; From e2d47c6a60807be3f1dff1137945c72b3f6a7209 Mon Sep 17 00:00:00 2001 From: nightwing Date: Fri, 18 Nov 2011 17:39:03 +0400 Subject: [PATCH 7/8] fix clipping at the boundaries, and add more tests --- lib/ace/edit_session.js | 12 ++++++------ lib/ace/edit_session_test.js | 8 ++++++++ 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/lib/ace/edit_session.js b/lib/ace/edit_session.js index 621a6211..9754f1b4 100644 --- a/lib/ace/edit_session.js +++ b/lib/ace/edit_session.js @@ -1386,9 +1386,7 @@ var EditSession = function(text, mode) { } var doCache = !rowCache.length || i == rowCache.length; - // clamp row before clamping column, for selection on last line var maxRow = this.getLength() - 1; - var foldLine = this.getNextFoldLine(docRow); var foldStart = foldLine ? foldLine.start.row : Infinity; @@ -1416,6 +1414,12 @@ var EditSession = function(text, mode) { if (foldLine && foldLine.start.row <= docRow) { line = this.getFoldDisplayLine(foldLine); docRow = foldLine.start.row; + } else if (row + rowLength <= screenRow || docRow > maxRow) { + // clip at the end of the document + return { + row: maxRow, + column: this.getLine(maxRow).length + } } else { line = this.getLine(docRow); foldLine = null; @@ -1434,10 +1438,6 @@ var EditSession = function(text, mode) { docColumn += this.$getStringScreenWidth(line, screenColumn)[1]; - // clip row at the end of the document - if (docRow > maxRow) - docColumn = Number.MAX_VALUE; - // Need to do some clamping action here. if (this.$useWrapMode) { if (docColumn >= column) { diff --git a/lib/ace/edit_session_test.js b/lib/ace/edit_session_test.js index a93c9ca2..aeb2cef6 100644 --- a/lib/ace/edit_session_test.js +++ b/lib/ace/edit_session_test.js @@ -363,6 +363,14 @@ module.exports = { assert.position(session.screenToDocumentPosition(1, 30), 1, 12); assert.position(session.screenToDocumentPosition(20, 50), 1, 12); assert.position(session.screenToDocumentPosition(20, 5), 1, 12); + + // and the same for folded rows + session.addFold("...", new Range(0,1,1,3)); + assert.position(session.screenToDocumentPosition(1, 2), 1, 12); + // for wrapped rows + session.setUseWrapMode(true); + session.setWrapLimitRange(5,5); + assert.position(session.screenToDocumentPosition(4, 1), 1, 12); }, "test: wrapLine split function" : function() { From 13bb7725ff8ec287c8d84d56e2fbe8b71baedb8a Mon Sep 17 00:00:00 2001 From: nightwing Date: Fri, 18 Nov 2011 17:39:56 +0400 Subject: [PATCH 8/8] adapt move line test to new behaviour --- lib/ace/editor_text_edit_test.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/ace/editor_text_edit_test.js b/lib/ace/editor_text_edit_test.js index e6a9ea04..90468ccb 100644 --- a/lib/ace/editor_text_edit_test.js +++ b/lib/ace/editor_text_edit_test.js @@ -301,7 +301,7 @@ module.exports = { assert.position(editor.getSelection().getSelectionLead(), 0, 0); }, - "test: move line without active selection should move cursor to start of the moved line" : function() + "test: move line without active selection should not move cursor relative to the moved line" : function() { var session = new EditSession(["11", "22", "33", "44"].join("\n")); var editor = new Editor(new MockRenderer(), session); @@ -311,13 +311,13 @@ module.exports = { editor.moveLinesDown(); assert.equal(["11", "33", "22", "44"].join("\n"), session.toString()); - assert.position(editor.getCursorPosition(), 2, 0); + assert.position(editor.getCursorPosition(), 2, 1); editor.clearSelection(); editor.moveLinesUp(); assert.equal(["11", "22", "33", "44"].join("\n"), session.toString()); - assert.position(editor.getCursorPosition(), 1, 0); + assert.position(editor.getCursorPosition(), 1, 1); }, "test: copy lines down should select lines and place cursor at the selection start" : function() {