From 60367772a9fc18e68ae7a3e8303cb863579967f9 Mon Sep 17 00:00:00 2001 From: DanyaPostfactum Date: Sun, 12 Oct 2014 01:56:19 +1000 Subject: [PATCH 1/3] Add wrap indent --- lib/ace/edit_session.js | 60 +++++++++++++++++++++++++++++++++++------ lib/ace/layer/marker.js | 3 ++- lib/ace/layer/text.js | 2 ++ 3 files changed, 56 insertions(+), 9 deletions(-) diff --git a/lib/ace/edit_session.js b/lib/ace/edit_session.js index 71cda95c..8ab76597 100644 --- a/lib/ace/edit_session.js +++ b/lib/ace/edit_session.js @@ -1840,7 +1840,7 @@ var EditSession = function(text, mode) { TAB_SPACE = 12; - this.$computeWrapSplits = function(tokens, wrapLimit) { + this.$computeWrapSplits = function(tokens, wrapLimit, tabSize) { if (tokens.length == 0) { return []; } @@ -1851,6 +1851,32 @@ var EditSession = function(text, mode) { var isCode = this.$wrapAsCode; + var indentSubsequentLines = true; + + var maxIndent = wrapLimit > 8 ? Math.floor(wrapLimit / 2) : 0; + + function getIndentation() { + var indentation = 0; + if (maxIndent === 0) + return indentation; + if (indentSubsequentLines) { + for (var i = 0; i < tokens.length; i++) { + var token = tokens[i]; + if (token == SPACE) + indentation += 1; + else if (token == TAB) + indentation += tabSize; + else if (token == TAB_SPACE) + continue; + else + break; + } + } + if (isCode) + indentation += tabSize; + return Math.min(indentation, maxIndent); + } + function addSplit(screenPos) { var displayed = tokens.slice(lastSplit, screenPos); @@ -1867,14 +1893,18 @@ var EditSession = function(text, mode) { len -= 1; }); + if (splits.length === 0) { + indent = getIndentation(); + splits.indent = indent; + } lastDocSplit += len; splits.push(lastDocSplit); lastSplit = screenPos; } - - while (displayLength - lastSplit > wrapLimit) { + var indent = 0; + while (displayLength - lastSplit > wrapLimit - indent) { // This is, where the split should be. - var split = lastSplit + wrapLimit; + var split = lastSplit + wrapLimit - indent; // If there is a space or tab at this split position, then making // a split is simple. @@ -1962,7 +1992,7 @@ var EditSession = function(text, mode) { // around -> force a split. if (tokens[split] == CHAR_EXT) split--; - addSplit(split); + addSplit(split - indent); } return splits; }; @@ -2069,6 +2099,17 @@ var EditSession = function(text, mode) { } }; + this.getRowWrapIndent = function(screenRow) { + if (!this.$useWrapMode) { + return 0; + } else { + var row = this.screenToDocumentPosition(screenRow, Number.MAX_VALUE).row; + var splits = this.$wrapData[row]; + var splitIndex = Math.floor(screenRow - row); + return splits.length && splitIndex > 0 ? splits.indent : 0; + } + } + /** * Returns the position (on screen) for the last character in the provided screen row. * @param {Number} screenRow The screen row to check @@ -2206,20 +2247,21 @@ var EditSession = function(text, mode) { line = this.getLine(docRow); foldLine = null; } - + var wrapIndent = 0; if (this.$useWrapMode) { var splits = this.$wrapData[docRow]; if (splits) { var splitIndex = Math.floor(screenRow - row); column = splits[splitIndex]; if(splitIndex > 0 && splits.length) { + wrapIndent = splits.indent; docColumn = splits[splitIndex - 1] || splits[splits.length - 1]; line = line.substring(docColumn); } } } - docColumn += this.$getStringScreenWidth(line, screenColumn)[1]; + docColumn += this.$getStringScreenWidth(line, screenColumn - wrapIndent)[1]; // We remove one character at the end so that the docColumn // position returned is not associated to the next row on the screen. @@ -2311,6 +2353,7 @@ var EditSession = function(text, mode) { textLine = this.getLine(docRow).substring(0, docColumn); foldStartRow = docRow; } + var wrapIndent = 0; // Clamp textLine if in wrapMode. if (this.$useWrapMode) { var wrapRow = this.$wrapData[foldStartRow]; @@ -2323,12 +2366,13 @@ var EditSession = function(text, mode) { textLine = textLine.substring( wrapRow[screenRowOffset - 1] || 0, textLine.length ); + wrapIndent = screenRowOffset > 0 ? wrapRow.indent : 0; } } return { row: screenRow, - column: this.$getStringScreenWidth(textLine)[0] + column: wrapIndent + this.$getStringScreenWidth(textLine)[0] }; }; diff --git a/lib/ace/layer/marker.js b/lib/ace/layer/marker.js index 37e038b5..60329d7b 100644 --- a/lib/ace/layer/marker.js +++ b/lib/ace/layer/marker.js @@ -113,11 +113,12 @@ var Marker = function(parentEl) { // selection end row = range.end.row; - lineRange = new Range(row, 0, row, range.end.column); + lineRange = new Range(row, this.session.getRowWrapIndent(row), row, range.end.column); this.drawSingleLineMarker(stringBuilder, lineRange, clazz, layerConfig, 0, extraStyle); for (row = range.start.row + 1; row < range.end.row; row++) { lineRange.start.row = row; + lineRange.start.column = this.session.getRowWrapIndent(row); lineRange.end.row = row; lineRange.end.column = this.session.getScreenLastRowColumn(row); this.drawSingleLineMarker(stringBuilder, lineRange, clazz, layerConfig, 1, extraStyle); diff --git a/lib/ace/layer/text.js b/lib/ace/layer/text.js index aeb74f1c..5080112f 100644 --- a/lib/ace/layer/text.js +++ b/lib/ace/layer/text.js @@ -420,6 +420,8 @@ var Text = function(parentEl) { ); } + stringBuilder.push(lang.stringRepeat("\xa0", splits.indent)); + split ++; screenColumn = 0; splitChars = splits[split] || Number.MAX_VALUE; From f625dfeea3bf2b7828c4cbccfbe0de9f4e5f92a3 Mon Sep 17 00:00:00 2001 From: DanyaPostfactum Date: Sun, 12 Oct 2014 18:37:20 +1000 Subject: [PATCH 2/3] Add indentSubsequentLines to options --- lib/ace/edit_session.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/ace/edit_session.js b/lib/ace/edit_session.js index 8ab76597..c7260158 100644 --- a/lib/ace/edit_session.js +++ b/lib/ace/edit_session.js @@ -1851,7 +1851,7 @@ var EditSession = function(text, mode) { var isCode = this.$wrapAsCode; - var indentSubsequentLines = true; + var indentSubsequentLines = this.$indentSubsequentLines; var maxIndent = wrapLimit > 8 ? Math.floor(wrapLimit / 2) : 0; @@ -2552,6 +2552,7 @@ config.defineOptions(EditSession.prototype, "session", { }, initialValue: "auto" }, + indentSubsequentLines: {initialValue: true}, firstLineNumber: { set: function() {this._signal("changeBreakpoint");}, initialValue: 1 From 6502a3d2cb35c7131e70831b95c9b006a38ee31d Mon Sep 17 00:00:00 2001 From: DanyaPostfactum Date: Sun, 12 Oct 2014 18:37:52 +1000 Subject: [PATCH 3/3] Update tests for wrap indent --- lib/ace/edit_session_test.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/lib/ace/edit_session_test.js b/lib/ace/edit_session_test.js index 87cc9567..bc4226f9 100644 --- a/lib/ace/edit_session_test.js +++ b/lib/ace/edit_session_test.js @@ -280,7 +280,7 @@ module.exports = { session.setUseWrapMode(true); session.setWrapLimitRange(12, 12); session.adjustWrapLimit(80); - + session.setOption("wrapMethod", "text"); assert.position(session.documentToScreenPosition(0, 11), 0, 11); assert.position(session.documentToScreenPosition(0, 12), 1, 0); }, @@ -388,26 +388,27 @@ module.exports = { } EditSession.prototype.$wrapAsCode = true; + EditSession.prototype.$indentSubsequentLines = false; // Basic splitting. computeAndAssert("foo bar foo bar", [ 12 ]); computeAndAssert("foo bar f bar", [ 12 ]); computeAndAssert("foo bar f r", [ 12 ]); // 14 if we enable - computeAndAssert("foo bar foo bar foo bara foo", [12, 25]); + computeAndAssert("foo bar foo bar foo bara foo", [12, 20]); // Don't split if there is only whitespaces/tabs at the end of the line. computeAndAssert("foo foo foo \t \t", [ ]); // If there is no space to split, force split. computeAndAssert("foooooooooooooo", [ 12 ]); - computeAndAssert("fooooooooooooooooooooooooooo", [12, 24]); - computeAndAssert("foo bar fooooooooooobooooooo", [8, 20]); + computeAndAssert("fooooooooooooooooooooooooooo", [12, 20]); + computeAndAssert("foo bar fooooooooooobooooooo", [8, 16, 24]); // Basic splitting + tabs. computeAndAssert("foo \t\tbar", [ 6 ]); computeAndAssert("foo \t \tbar", [ 7 ]); // Ignore spaces/tabs at beginning of split. - computeAndAssert("foo \t \t \t \t bar", [ 7 ]); // 14 + computeAndAssert("foo \t \t \t \t bar", [7, 13]); // 14 // Test wrapping for asian characters. computeAndAssert("ぁぁ", [1], 2);