Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Selective bracket insertion/skipping for quotes #1065

Merged
merged 8 commits into from Nov 12, 2012
2 changes: 1 addition & 1 deletion build
Submodule build updated 416 files
4 changes: 2 additions & 2 deletions lib/ace/edit_session/bracket_match.js
Expand Up @@ -37,10 +37,10 @@ var Range = require("../range").Range;

function BracketMatch() {

this.findMatchingBracket = function(position) {
this.findMatchingBracket = function(position, char) {
if (position.column == 0) return null;

var charBeforeCursor = this.getLine(position.row).charAt(position.column-1);
var charBeforeCursor = char || this.getLine(position.row).charAt(position.column-1);
if (charBeforeCursor == "") return null;

var match = charBeforeCursor.match(/([\(\[\{])|([\)\]\}])/);
Expand Down
87 changes: 68 additions & 19 deletions lib/ace/mode/behaviour/cstyle.js
Expand Up @@ -34,10 +34,21 @@ define(function(require, exports, module) {
var oop = require("../../lib/oop");
var Behaviour = require("../behaviour").Behaviour;
var TokenIterator = require("../../token_iterator").TokenIterator;
var lang = require("../../lib/lang");

var SAFE_INSERT_IN_TOKENS =
["text", "paren.rparen", "punctuation.operator"];
var SAFE_INSERT_BEFORE_TOKENS =
["text", "paren.rparen", "punctuation.operator", "comment"];


var autoInsertedBrackets = 0;
var autoInsertedRow = -1;
var autoInsertedLineEnd = "";
var maybeInsertedBrackets = 0;
var maybeInsertedRow = -1;
var maybeInsertedLineStart = "";
var maybeInsertedLineEnd = "";

var CstyleBehaviour = function () {

Expand All @@ -46,17 +57,17 @@ var CstyleBehaviour = function () {
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", ["text", "paren.rparen"])) {
if (!this.$matchTokenType(iterator.getCurrentToken() || "text", SAFE_INSERT_IN_TOKENS)) {
// Look ahead in case we're at the end of a token
iterator = new TokenIterator(session, cursor.row, cursor.column + 1);
if (!this.$matchTokenType(iterator.getCurrentToken() || "text", ["text", "paren.rparen"]))
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", ["text", "comment", "paren.rparen"]);
this.$matchTokenType(iterator.getCurrentToken() || "text", SAFE_INSERT_BEFORE_TOKENS);
};

CstyleBehaviour.$matchTokenType = function(token, types) {
Expand All @@ -74,19 +85,44 @@ var CstyleBehaviour = function () {
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 cursor = editor.getCursorPosition();
var line = session.doc.getLine(cursor.row);
if (text == '{') {
var selection = editor.getSelectionRange();
var selected = session.doc.getTextRange(selection);
Expand All @@ -96,15 +132,21 @@ var CstyleBehaviour = function () {
selection: false
};
} else if (CstyleBehaviour.isSaneInsertion(editor, session)) {
CstyleBehaviour.recordAutoInsert(editor, session, "}");
return {
text: '{}',
selection: [1, 1]
};
if (/[\]\}\)]/.test(line[cursor.column])) {
CstyleBehaviour.recordAutoInsert(editor, session, "}");
return {
text: '{}',
selection: [1, 1]
};
} else {
CstyleBehaviour.recordMaybeInsert(editor, session, "{");
return {
text: '{',
selection: [1, 1]
};
}
}
} else if (text == '}') {
var cursor = editor.getCursorPosition();
var line = session.doc.getLine(cursor.row);
var rightChar = line.substring(cursor.column, cursor.column + 1);
if (rightChar == '}') {
var matching = session.$findOpeningBracket('}', {column: cursor.column + 1, row: cursor.row});
Expand All @@ -117,19 +159,22 @@ var CstyleBehaviour = function () {
}
}
} else if (text == "\n" || text == "\r\n") {
var cursor = editor.getCursorPosition();
var line = session.doc.getLine(cursor.row);
var closing = "";
if (CstyleBehaviour.isMaybeInsertedClosing(cursor, line)) {
closing = lang.stringRepeat("}", maybeInsertedBrackets);
CstyleBehaviour.clearMaybeInsertedClosing();
}
var rightChar = line.substring(cursor.column, cursor.column + 1);
if (rightChar == '}') {
var openBracePos = session.findMatchingBracket({row: cursor.row, column: cursor.column + 1});
if (rightChar == '}' || closing !== "") {
var openBracePos = session.findMatchingBracket({row: cursor.row, column: cursor.column}, '}');
if (!openBracePos)
return null;

var indent = this.getNextLineIndent(state, line.substring(0, line.length - 1), session.getTabString());
var next_indent = this.$getIndent(session.doc.getLine(openBracePos.row));
var indent = this.getNextLineIndent(state, line.substring(0, cursor.column), session.getTabString());
var next_indent = this.$getIndent(line);

return {
text: '\n' + indent + '\n' + next_indent,
text: '\n' + indent + '\n' + next_indent + closing,
selection: [1, indent.length, 1, indent.length]
};
}
Expand All @@ -144,6 +189,8 @@ var CstyleBehaviour = function () {
if (rightChar == '}') {
range.end.column++;
return range;
} else {
maybeInsertedBrackets--;
}
}
});
Expand Down Expand Up @@ -243,7 +290,7 @@ var CstyleBehaviour = function () {
var quote = text;
var selection = editor.getSelectionRange();
var selected = session.doc.getTextRange(selection);
if (selected !== "") {
if (selected !== "" && selected !== "'" && selected != '"') {
return {
text: quote + selected + quote,
selection: false
Expand Down Expand Up @@ -278,6 +325,8 @@ var CstyleBehaviour = function () {

// Try and be smart about when we auto insert.
if (!token || (quotepos < 0 && token.type !== "comment" && (token.type !== "string" || ((selection.start.column !== token.value.length+col-1) && token.value.lastIndexOf(quote) === token.value.length-1)))) {
if (!CstyleBehaviour.isSaneInsertion(editor, session))
return;
return {
text: quote + quote,
selection: [1,1]
Expand Down