diff --git a/lib/ace/editor.js b/lib/ace/editor.js index 06ce384b..cecec203 100644 --- a/lib/ace/editor.js +++ b/lib/ace/editor.js @@ -660,7 +660,7 @@ var Editor = function(renderer, session) { if (this.$highlightActiveLine) { if ((this.$selectionStyle != "line" || !this.selection.isMultiLine())) highlight = this.getCursorPosition(); - if (this.renderer.$maxLines && this.session.getLength() === 1) + if (this.renderer.$maxLines && this.session.getLength() === 1 && !(this.renderer.$minLines > 1)) highlight = false; } @@ -846,14 +846,13 @@ var Editor = function(renderer, session) { * Inserts `text` into wherever the cursor is pointing. * @param {String} text The new text to add * - * **/ - this.insert = function(text) { + this.insert = function(text, pasted) { var session = this.session; var mode = session.getMode(); var cursor = this.getCursorPosition(); - if (this.getBehavioursEnabled()) { + if (this.getBehavioursEnabled() && !pasted) { // Get a transform if the current mode wants one. var transform = mode.transformAction(session.getState(cursor.row), 'insertion', this, session, text); if (transform) { diff --git a/lib/ace/mode/behaviour/cstyle.js b/lib/ace/mode/behaviour/cstyle.js index 5bdd997c..2709168e 100644 --- a/lib/ace/mode/behaviour/cstyle.js +++ b/lib/ace/mode/behaviour/cstyle.js @@ -41,89 +41,34 @@ var SAFE_INSERT_IN_TOKENS = var SAFE_INSERT_BEFORE_TOKENS = ["text", "paren.rparen", "punctuation.operator", "comment"]; +var context; +var contextCache = {} +var initContext = function(editor) { + var id = -1; + if (editor.multiSelect) { + id = editor.selection.id; + if (contextCache.rangeCount != editor.multiSelect.rangeCount) + contextCache = {rangeCount: editor.multiSelect.rangeCount}; + } + if (contextCache[id]) + return context = contextCache[id]; + context = contextCache[id] = { + autoInsertedBrackets: 0, + autoInsertedRow: -1, + autoInsertedLineEnd: "", + maybeInsertedBrackets: 0, + maybeInsertedRow: -1, + maybeInsertedLineStart: "", + maybeInsertedLineEnd: "" + }; +}; -var autoInsertedBrackets = 0; -var autoInsertedRow = -1; -var autoInsertedLineEnd = ""; -var maybeInsertedBrackets = 0; -var maybeInsertedRow = -1; -var maybeInsertedLineStart = ""; -var maybeInsertedLineEnd = ""; - -var CstyleBehaviour = function () { - - CstyleBehaviour.isSaneInsertion = function(editor, session) { - var cursor = editor.getCursorPosition(); - var iterator = new TokenIterator(session, cursor.row, cursor.column); - - // Don't insert in the middle of a keyword/identifier/lexical - if (!this.$matchTokenType(iterator.getCurrentToken() || "text", SAFE_INSERT_IN_TOKENS)) { - // Look ahead in case we're at the end of a token - var iterator2 = new TokenIterator(session, cursor.row, cursor.column + 1); - if (!this.$matchTokenType(iterator2.getCurrentToken() || "text", SAFE_INSERT_IN_TOKENS)) - return false; - } - - // Only insert in front of whitespace/comments - iterator.stepForward(); - return iterator.getCurrentTokenRow() !== cursor.row || - this.$matchTokenType(iterator.getCurrentToken() || "text", SAFE_INSERT_BEFORE_TOKENS); - }; - - CstyleBehaviour.$matchTokenType = function(token, types) { - return types.indexOf(token.type || token) > -1; - }; - - CstyleBehaviour.recordAutoInsert = function(editor, session, bracket) { - var cursor = editor.getCursorPosition(); - var line = session.doc.getLine(cursor.row); - // Reset previous state if text or context changed too much - if (!this.isAutoInsertedClosing(cursor, line, autoInsertedLineEnd[0])) - autoInsertedBrackets = 0; - autoInsertedRow = cursor.row; - autoInsertedLineEnd = bracket + line.substr(cursor.column); - autoInsertedBrackets++; - }; - - CstyleBehaviour.recordMaybeInsert = function(editor, session, bracket) { - var cursor = editor.getCursorPosition(); - var line = session.doc.getLine(cursor.row); - if (!this.isMaybeInsertedClosing(cursor, line)) - maybeInsertedBrackets = 0; - maybeInsertedRow = cursor.row; - maybeInsertedLineStart = line.substr(0, cursor.column) + bracket; - maybeInsertedLineEnd = line.substr(cursor.column); - maybeInsertedBrackets++; - }; - - CstyleBehaviour.isAutoInsertedClosing = function(cursor, line, bracket) { - return autoInsertedBrackets > 0 && - cursor.row === autoInsertedRow && - bracket === autoInsertedLineEnd[0] && - line.substr(cursor.column) === autoInsertedLineEnd; - }; - - CstyleBehaviour.isMaybeInsertedClosing = function(cursor, line) { - return maybeInsertedBrackets > 0 && - cursor.row === maybeInsertedRow && - line.substr(cursor.column) === maybeInsertedLineEnd && - line.substr(0, cursor.column) == maybeInsertedLineStart; - }; - - CstyleBehaviour.popAutoInsertedClosing = function() { - autoInsertedLineEnd = autoInsertedLineEnd.substr(1); - autoInsertedBrackets--; - }; - - CstyleBehaviour.clearMaybeInsertedClosing = function() { - maybeInsertedBrackets = 0; - maybeInsertedRow = -1; - }; - - this.add("braces", "insertion", function (state, action, editor, session, text) { +var CstyleBehaviour = function() { + this.add("braces", "insertion", function(state, action, editor, session, text) { var cursor = editor.getCursorPosition(); var line = session.doc.getLine(cursor.row); if (text == '{') { + initContext(editor); var selection = editor.getSelectionRange(); var selected = session.doc.getTextRange(selection); if (selected !== "" && selected !== "{" && editor.getWrapBehavioursEnabled()) { @@ -147,6 +92,7 @@ var CstyleBehaviour = function () { } } } else if (text == '}') { + initContext(editor); var rightChar = line.substring(cursor.column, cursor.column + 1); if (rightChar == '}') { var matching = session.$findOpeningBracket('}', {column: cursor.column + 1, row: cursor.row}); @@ -159,9 +105,10 @@ var CstyleBehaviour = function () { } } } else if (text == "\n" || text == "\r\n") { + initContext(editor); var closing = ""; if (CstyleBehaviour.isMaybeInsertedClosing(cursor, line)) { - closing = lang.stringRepeat("}", maybeInsertedBrackets); + closing = lang.stringRepeat("}", context.maybeInsertedBrackets); CstyleBehaviour.clearMaybeInsertedClosing(); } var rightChar = line.substring(cursor.column, cursor.column + 1); @@ -173,6 +120,7 @@ var CstyleBehaviour = function () { } else if (closing) { var next_indent = this.$getIndent(line); } else { + CstyleBehaviour.clearMaybeInsertedClosing(); return; } var indent = next_indent + session.getTabString(); @@ -186,22 +134,24 @@ var CstyleBehaviour = function () { } }); - this.add("braces", "deletion", function (state, action, editor, session, range) { + this.add("braces", "deletion", function(state, action, editor, session, range) { var selected = session.doc.getTextRange(range); if (!range.isMultiLine() && selected == '{') { + initContext(editor); var line = session.doc.getLine(range.start.row); var rightChar = line.substring(range.end.column, range.end.column + 1); if (rightChar == '}') { range.end.column++; return range; } else { - maybeInsertedBrackets--; + context.maybeInsertedBrackets--; } } }); - this.add("parens", "insertion", function (state, action, editor, session, text) { + this.add("parens", "insertion", function(state, action, editor, session, text) { if (text == '(') { + initContext(editor); var selection = editor.getSelectionRange(); var selected = session.doc.getTextRange(selection); if (selected !== "" && editor.getWrapBehavioursEnabled()) { @@ -217,6 +167,7 @@ var CstyleBehaviour = function () { }; } } else if (text == ')') { + initContext(editor); var cursor = editor.getCursorPosition(); var line = session.doc.getLine(cursor.row); var rightChar = line.substring(cursor.column, cursor.column + 1); @@ -233,9 +184,10 @@ var CstyleBehaviour = function () { } }); - this.add("parens", "deletion", function (state, action, editor, session, range) { + this.add("parens", "deletion", function(state, action, editor, session, range) { var selected = session.doc.getTextRange(range); if (!range.isMultiLine() && selected == '(') { + initContext(editor); var line = session.doc.getLine(range.start.row); var rightChar = line.substring(range.start.column + 1, range.start.column + 2); if (rightChar == ')') { @@ -245,8 +197,9 @@ var CstyleBehaviour = function () { } }); - this.add("brackets", "insertion", function (state, action, editor, session, text) { + this.add("brackets", "insertion", function(state, action, editor, session, text) { if (text == '[') { + initContext(editor); var selection = editor.getSelectionRange(); var selected = session.doc.getTextRange(selection); if (selected !== "" && editor.getWrapBehavioursEnabled()) { @@ -262,6 +215,7 @@ var CstyleBehaviour = function () { }; } } else if (text == ']') { + initContext(editor); var cursor = editor.getCursorPosition(); var line = session.doc.getLine(cursor.row); var rightChar = line.substring(cursor.column, cursor.column + 1); @@ -278,9 +232,10 @@ var CstyleBehaviour = function () { } }); - this.add("brackets", "deletion", function (state, action, editor, session, range) { + this.add("brackets", "deletion", function(state, action, editor, session, range) { var selected = session.doc.getTextRange(range); if (!range.isMultiLine() && selected == '[') { + initContext(editor); var line = session.doc.getLine(range.start.row); var rightChar = line.substring(range.start.column + 1, range.start.column + 2); if (rightChar == ']') { @@ -290,8 +245,9 @@ var CstyleBehaviour = function () { } }); - this.add("string_dquotes", "insertion", function (state, action, editor, session, text) { + this.add("string_dquotes", "insertion", function(state, action, editor, session, text) { if (text == '"' || text == "'") { + initContext(editor); var quote = text; var selection = editor.getSelectionRange(); var selected = session.doc.getTextRange(selection); @@ -350,9 +306,10 @@ var CstyleBehaviour = function () { } }); - this.add("string_dquotes", "deletion", function (state, action, editor, session, range) { + this.add("string_dquotes", "deletion", function(state, action, editor, session, range) { var selected = session.doc.getTextRange(range); if (!range.isMultiLine() && (selected == '"' || selected == "'")) { + initContext(editor); var line = session.doc.getLine(range.start.row); var rightChar = line.substring(range.start.column + 1, range.start.column + 2); if (rightChar == selected) { @@ -364,6 +321,79 @@ var CstyleBehaviour = function () { }; + +CstyleBehaviour.isSaneInsertion = function(editor, session) { + var cursor = editor.getCursorPosition(); + var iterator = new TokenIterator(session, cursor.row, cursor.column); + + // Don't insert in the middle of a keyword/identifier/lexical + if (!this.$matchTokenType(iterator.getCurrentToken() || "text", SAFE_INSERT_IN_TOKENS)) { + // Look ahead in case we're at the end of a token + var iterator2 = new TokenIterator(session, cursor.row, cursor.column + 1); + if (!this.$matchTokenType(iterator2.getCurrentToken() || "text", SAFE_INSERT_IN_TOKENS)) + return false; + } + + // Only insert in front of whitespace/comments + iterator.stepForward(); + return iterator.getCurrentTokenRow() !== cursor.row || + this.$matchTokenType(iterator.getCurrentToken() || "text", SAFE_INSERT_BEFORE_TOKENS); +}; + +CstyleBehaviour.$matchTokenType = function(token, types) { + return types.indexOf(token.type || token) > -1; +}; + +CstyleBehaviour.recordAutoInsert = function(editor, session, bracket) { + var cursor = editor.getCursorPosition(); + var line = session.doc.getLine(cursor.row); + // Reset previous state if text or context changed too much + if (!this.isAutoInsertedClosing(cursor, line, context.autoInsertedLineEnd[0])) + context.autoInsertedBrackets = 0; + context.autoInsertedRow = cursor.row; + context.autoInsertedLineEnd = bracket + line.substr(cursor.column); + context.autoInsertedBrackets++; +}; + +CstyleBehaviour.recordMaybeInsert = function(editor, session, bracket) { + var cursor = editor.getCursorPosition(); + var line = session.doc.getLine(cursor.row); + if (!this.isMaybeInsertedClosing(cursor, line)) + context.maybeInsertedBrackets = 0; + context.maybeInsertedRow = cursor.row; + context.maybeInsertedLineStart = line.substr(0, cursor.column) + bracket; + context.maybeInsertedLineEnd = line.substr(cursor.column); + context.maybeInsertedBrackets++; +}; + +CstyleBehaviour.isAutoInsertedClosing = function(cursor, line, bracket) { + return context.autoInsertedBrackets > 0 && + cursor.row === context.autoInsertedRow && + bracket === context.autoInsertedLineEnd[0] && + line.substr(cursor.column) === context.autoInsertedLineEnd; +}; + +CstyleBehaviour.isMaybeInsertedClosing = function(cursor, line) { + return context.maybeInsertedBrackets > 0 && + cursor.row === context.maybeInsertedRow && + line.substr(cursor.column) === context.maybeInsertedLineEnd && + line.substr(0, cursor.column) == context.maybeInsertedLineStart; +}; + +CstyleBehaviour.popAutoInsertedClosing = function() { + context.autoInsertedLineEnd = context.autoInsertedLineEnd.substr(1); + context.autoInsertedBrackets--; +}; + +CstyleBehaviour.clearMaybeInsertedClosing = function() { + if (context) { + context.maybeInsertedBrackets = 0; + context.maybeInsertedRow = -1; + } +}; + + + oop.inherits(CstyleBehaviour, Behaviour); exports.CstyleBehaviour = CstyleBehaviour;