diff --git a/lib/ace/edit_session.js b/lib/ace/edit_session.js index b35ea4e0..04b5e463 100644 --- a/lib/ace/edit_session.js +++ b/lib/ace/edit_session.js @@ -1835,7 +1835,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 []; } @@ -1846,6 +1846,32 @@ var EditSession = function(text, mode) { var isCode = this.$wrapAsCode; + var indentSubsequentLines = this.$indentSubsequentLines; + + 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); @@ -1862,14 +1888,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. @@ -1957,7 +1987,7 @@ var EditSession = function(text, mode) { // around -> force a split. if (tokens[split] == CHAR_EXT) split--; - addSplit(split); + addSplit(split - indent); } return splits; }; @@ -2064,6 +2094,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 @@ -2201,20 +2242,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. @@ -2306,6 +2348,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]; @@ -2318,12 +2361,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] }; }; @@ -2503,6 +2547,7 @@ config.defineOptions(EditSession.prototype, "session", { }, initialValue: "auto" }, + indentSubsequentLines: {initialValue: true}, firstLineNumber: { set: function() {this._signal("changeBreakpoint");}, initialValue: 1 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); diff --git a/lib/ace/layer/marker.js b/lib/ace/layer/marker.js index 5548ce51..bdd82e40 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 0ae6e83d..a105768d 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;