diff --git a/media/editors/codemirror/addon/comment/comment.js b/media/editors/codemirror/addon/comment/comment.js index d7f569cc00534..2dd114d332dc9 100644 --- a/media/editors/codemirror/addon/comment/comment.js +++ b/media/editors/codemirror/addon/comment/comment.js @@ -109,7 +109,7 @@ CodeMirror.defineExtension("uncomment", function(from, to, options) { if (!options) options = noOptions; var self = this, mode = self.getModeAt(from); - var end = Math.min(to.line, self.lastLine()), start = Math.min(from.line, end); + var end = Math.min(to.ch != 0 || to.line == from.line ? to.line : to.line - 1, self.lastLine()), start = Math.min(from.line, end); // Try finding line comments var lineString = options.lineComment || mode.lineComment, lines = []; diff --git a/media/editors/codemirror/addon/comment/index.html b/media/editors/codemirror/addon/comment/index.html new file mode 100644 index 0000000000000..2efb97f319a35 --- /dev/null +++ b/media/editors/codemirror/addon/comment/index.html @@ -0,0 +1 @@ + diff --git a/media/editors/codemirror/addon/dialog/dialog.js b/media/editors/codemirror/addon/dialog/dialog.js index 35a6103c2d786..5a88d99e64f8d 100644 --- a/media/editors/codemirror/addon/dialog/dialog.js +++ b/media/editors/codemirror/addon/dialog/dialog.js @@ -56,7 +56,10 @@ var inp = dialog.getElementsByTagName("input")[0], button; if (inp) { - if (options.value) inp.value = options.value; + if (options.value) { + inp.value = options.value; + inp.select(); + } if (options.onInput) CodeMirror.on(inp, "input", function(e) { options.onInput(e, inp.value, close);}); diff --git a/media/editors/codemirror/addon/dialog/index.html b/media/editors/codemirror/addon/dialog/index.html new file mode 100644 index 0000000000000..2efb97f319a35 --- /dev/null +++ b/media/editors/codemirror/addon/dialog/index.html @@ -0,0 +1 @@ + diff --git a/media/editors/codemirror/addon/display/index.html b/media/editors/codemirror/addon/display/index.html new file mode 100644 index 0000000000000..2efb97f319a35 --- /dev/null +++ b/media/editors/codemirror/addon/display/index.html @@ -0,0 +1 @@ + diff --git a/media/editors/codemirror/addon/edit/closebrackets.js b/media/editors/codemirror/addon/edit/closebrackets.js index 1a04f3664ef07..f6b42f02d3b34 100644 --- a/media/editors/codemirror/addon/edit/closebrackets.js +++ b/media/editors/codemirror/addon/edit/closebrackets.js @@ -71,31 +71,32 @@ }; var closingBrackets = ""; for (var i = 0; i < pairs.length; i += 2) (function(left, right) { - if (left != right) closingBrackets += right; + closingBrackets += right; map["'" + left + "'"] = function(cm) { if (cm.getOption("disableInput")) return CodeMirror.Pass; var ranges = cm.listSelections(), type, next; for (var i = 0; i < ranges.length; i++) { var range = ranges[i], cur = range.head, curType; var next = cm.getRange(cur, Pos(cur.line, cur.ch + 1)); - if (!range.empty()) + if (!range.empty()) { curType = "surround"; - else if (left == right && next == right) { + } else if (left == right && next == right) { if (cm.getRange(cur, Pos(cur.line, cur.ch + 3)) == left + left + left) curType = "skipThree"; else curType = "skip"; } else if (left == right && cur.ch > 1 && cm.getRange(Pos(cur.line, cur.ch - 2), cur) == left + left && - (cur.ch <= 2 || cm.getRange(Pos(cur.line, cur.ch - 3), Pos(cur.line, cur.ch - 2)) != left)) + (cur.ch <= 2 || cm.getRange(Pos(cur.line, cur.ch - 3), Pos(cur.line, cur.ch - 2)) != left)) { curType = "addFour"; - else if (left == '"' || left == "'") { + } else if (left == '"' || left == "'") { if (!CodeMirror.isWordChar(next) && enteringString(cm, cur, left)) curType = "both"; else return CodeMirror.Pass; - } else if (cm.getLine(cur.line).length == cur.ch || closingBrackets.indexOf(next) >= 0 || SPACE_CHAR_REGEX.test(next)) + } else if (cm.getLine(cur.line).length == cur.ch || closingBrackets.indexOf(next) >= 0 || SPACE_CHAR_REGEX.test(next)) { curType = "both"; - else + } else { return CodeMirror.Pass; + } if (!type) type = curType; else if (type != curType) return CodeMirror.Pass; } diff --git a/media/editors/codemirror/addon/edit/continuelist.js b/media/editors/codemirror/addon/edit/continuelist.js index 8cee761aeeae9..9ad0a98fa097e 100644 --- a/media/editors/codemirror/addon/edit/continuelist.js +++ b/media/editors/codemirror/addon/edit/continuelist.js @@ -11,7 +11,8 @@ })(function(CodeMirror) { "use strict"; - var listRE = /^(\s*)([*+-]|(\d+)\.)(\s+)/, + var listRE = /^(\s*)([> ]+|[*+-]|(\d+)\.)(\s+)/, + emptyListRE = /^(\s*)([> ]+|[*+-]|(\d+)\.)(\s*)$/, unorderedBullets = "*+-"; CodeMirror.commands.newlineAndIndentContinueMarkdownList = function(cm) { @@ -19,18 +20,30 @@ var ranges = cm.listSelections(), replacements = []; for (var i = 0; i < ranges.length; i++) { var pos = ranges[i].head, match; - var inList = cm.getStateAfter(pos.line).list !== false; + var eolState = cm.getStateAfter(pos.line); + var inList = eolState.list !== false; + var inQuote = eolState.quote !== false; - if (!ranges[i].empty() || !inList || !(match = cm.getLine(pos.line).match(listRE))) { + if (!ranges[i].empty() || (!inList && !inQuote) || !(match = cm.getLine(pos.line).match(listRE))) { cm.execCommand("newlineAndIndent"); return; } - var indent = match[1], after = match[4]; - var bullet = unorderedBullets.indexOf(match[2]) >= 0 - ? match[2] - : (parseInt(match[3], 10) + 1) + "."; + if (cm.getLine(pos.line).match(emptyListRE)) { + cm.replaceRange("", { + line: pos.line, ch: 0 + }, { + line: pos.line, ch: pos.ch + 1 + }); + replacements[i] = "\n"; - replacements[i] = "\n" + indent + bullet + after; + } else { + var indent = match[1], after = match[4]; + var bullet = unorderedBullets.indexOf(match[2]) >= 0 || match[2].indexOf(">") >= 0 + ? match[2] + : (parseInt(match[3], 10) + 1) + "."; + + replacements[i] = "\n" + indent + bullet + after; + } } cm.replaceSelections(replacements); diff --git a/media/editors/codemirror/addon/edit/index.html b/media/editors/codemirror/addon/edit/index.html new file mode 100644 index 0000000000000..2efb97f319a35 --- /dev/null +++ b/media/editors/codemirror/addon/edit/index.html @@ -0,0 +1 @@ + diff --git a/media/editors/codemirror/addon/fold/index.html b/media/editors/codemirror/addon/fold/index.html new file mode 100644 index 0000000000000..2efb97f319a35 --- /dev/null +++ b/media/editors/codemirror/addon/fold/index.html @@ -0,0 +1 @@ + diff --git a/media/editors/codemirror/addon/hint/index.html b/media/editors/codemirror/addon/hint/index.html new file mode 100644 index 0000000000000..2efb97f319a35 --- /dev/null +++ b/media/editors/codemirror/addon/hint/index.html @@ -0,0 +1 @@ + diff --git a/media/editors/codemirror/addon/hint/javascript-hint.js b/media/editors/codemirror/addon/hint/javascript-hint.js index c7292468a0094..f6c2440062289 100644 --- a/media/editors/codemirror/addon/hint/javascript-hint.js +++ b/media/editors/codemirror/addon/hint/javascript-hint.js @@ -93,7 +93,7 @@ "if in instanceof isnt new no not null of off on or return switch then throw true try typeof until void while with yes").split(" "); function getCompletions(token, context, keywords, options) { - var found = [], start = token.string; + var found = [], start = token.string, global = options && options.globalScope || window; function maybeAdd(str) { if (str.lastIndexOf(start, 0) == 0 && !arrayContains(found, str)) found.push(str); } @@ -112,28 +112,28 @@ if (options && options.additionalContext) base = options.additionalContext[obj.string]; if (!options || options.useGlobalScope !== false) - base = base || window[obj.string]; + base = base || global[obj.string]; } else if (obj.type == "string") { base = ""; } else if (obj.type == "atom") { base = 1; } else if (obj.type == "function") { - if (window.jQuery != null && (obj.string == '$' || obj.string == 'jQuery') && - (typeof window.jQuery == 'function')) - base = window.jQuery(); - else if (window._ != null && (obj.string == '_') && (typeof window._ == 'function')) - base = window._(); + if (global.jQuery != null && (obj.string == '$' || obj.string == 'jQuery') && + (typeof global.jQuery == 'function')) + base = global.jQuery(); + else if (global._ != null && (obj.string == '_') && (typeof global._ == 'function')) + base = global._(); } while (base != null && context.length) base = base[context.pop().string]; if (base != null) gatherCompletions(base); } else { - // If not, just look in the window object and any local scope + // If not, just look in the global object and any local scope // (reading into JS mode internals to get at the local and global variables) for (var v = token.state.localVars; v; v = v.next) maybeAdd(v.name); for (var v = token.state.globalVars; v; v = v.next) maybeAdd(v.name); if (!options || options.useGlobalScope !== false) - gatherCompletions(window); + gatherCompletions(global); forEach(keywords, maybeAdd); } return found; diff --git a/media/editors/codemirror/addon/hint/sql-hint.js b/media/editors/codemirror/addon/hint/sql-hint.js index 20653b5318f28..c2b511fa2fc5e 100644 --- a/media/editors/codemirror/addon/hint/sql-hint.js +++ b/media/editors/codemirror/addon/hint/sql-hint.js @@ -12,6 +12,7 @@ "use strict"; var tables; + var defaultTable; var keywords; var CONS = { QUERY_DIV: ";", @@ -43,18 +44,55 @@ } } - function columnCompletion(result, editor) { + function nameCompletion(result, editor) { var cur = editor.getCursor(); var token = editor.getTokenAt(cur); + var useBacktick = (token.string.charAt(0) == "`"); var string = token.string.substr(1); - var prevCur = Pos(cur.line, token.start); - var table = editor.getTokenAt(prevCur).string; - if (!tables.hasOwnProperty(table)) - table = findTableByAlias(table, editor); - var columns = tables[table]; - if (!columns) return; - - addMatches(result, string, columns, function(w) {return "." + w;}); + var prevToken = editor.getTokenAt(Pos(cur.line, token.start)); + if (token.string.charAt(0) == "." || prevToken.string == "."){ + //Suggest colunm names + if (prevToken.string == ".") { + var prevToken = editor.getTokenAt(Pos(cur.line, token.start - 1)); + } + var table = prevToken.string; + //Check if backtick is used in table name. If yes, use it for columns too. + var useBacktickTable = false; + if (table.match(/`/g)) { + useBacktickTable = true; + table = table.replace(/`/g, ""); + } + //Check if table is available. If not, find table by Alias + if (!tables.hasOwnProperty(table)) + table = findTableByAlias(table, editor); + var columns = tables[table]; + if (!columns) return; + + if (useBacktick) { + addMatches(result, string, columns, function(w) {return "`" + w + "`";}); + } + else if(useBacktickTable) { + addMatches(result, string, columns, function(w) {return ".`" + w + "`";}); + } + else { + addMatches(result, string, columns, function(w) {return "." + w;}); + } + } + else { + //Suggest table names or colums in defaultTable + while (token.start && string.charAt(0) == ".") { + token = editor.getTokenAt(Pos(cur.line, token.start - 1)); + string = token.string + string; + } + if (useBacktick) { + addMatches(result, string, tables, function(w) {return "`" + w + "`";}); + addMatches(result, string, defaultTable, function(w) {return "`" + w + "`";}); + } + else { + addMatches(result, string, tables, function(w) {return w;}); + addMatches(result, string, defaultTable, function(w) {return w;}); + } + } } function eachWord(lineText, f) { @@ -128,11 +166,14 @@ CodeMirror.registerHelper("hint", "sql", function(editor, options) { tables = (options && options.tables) || {}; + var defaultTableName = options && options.defaultTable; + defaultTable = (defaultTableName && tables[defaultTableName] || []); keywords = keywords || getKeywords(editor); + var cur = editor.getCursor(); var result = []; var token = editor.getTokenAt(cur), start, end, search; - if (token.string.match(/^[.\w@]\w*$/)) { + if (token.string.match(/^[.`\w@]\w*$/)) { search = token.string; start = token.start; end = token.end; @@ -140,18 +181,11 @@ start = end = cur.ch; search = ""; } - if (search.charAt(0) == ".") { - columnCompletion(result, editor); - if (!result.length) { - while (start && search.charAt(0) == ".") { - token = editor.getTokenAt(Pos(cur.line, token.start - 1)); - start = token.start; - search = token.string + search; - } - addMatches(result, search, tables, function(w) {return w;}); - } + if (search.charAt(0) == "." || search.charAt(0) == "`") { + nameCompletion(result, editor); } else { addMatches(result, search, tables, function(w) {return w;}); + addMatches(result, search, defaultTable, function(w) {return w;}); addMatches(result, search, keywords, function(w) {return w.toUpperCase();}); } diff --git a/media/editors/codemirror/addon/hint/xml-hint.js b/media/editors/codemirror/addon/hint/xml-hint.js index e31b09b5fc8ec..cc95b20f34452 100644 --- a/media/editors/codemirror/addon/hint/xml-hint.js +++ b/media/editors/codemirror/addon/hint/xml-hint.js @@ -18,10 +18,17 @@ var quote = (options && options.quoteChar) || '"'; if (!tags) return; var cur = cm.getCursor(), token = cm.getTokenAt(cur); + if (/^<\/?$/.test(token.string) && token.end == cur.ch) { + var nextToken = cm.getTokenAt(Pos(cur.line, cur.ch + 1)); + if (nextToken.start == cur.ch && /\btag\b/.test(nextToken.type)) + token = nextToken; + } var inner = CodeMirror.innerMode(cm.getMode(), token.state); if (inner.mode.name != "xml") return; var result = [], replaceToken = false, prefix; - var tag = /\btag\b/.test(token.type), tagName = tag && /^\w/.test(token.string), tagStart; + var tag = /\btag\b/.test(token.type) && !/>$/.test(token.string); + var tagName = tag && /^\w/.test(token.string), tagStart; + if (tagName) { var before = cm.getLine(cur.line).slice(Math.max(0, token.start - 2), token.start); var tagType = /<\/$/.test(before) ? "close" : /<$/.test(before) ? "open" : null; @@ -31,6 +38,7 @@ } else if (tag && token.string == " diff --git a/media/editors/codemirror/addon/lint/index.html b/media/editors/codemirror/addon/lint/index.html new file mode 100644 index 0000000000000..2efb97f319a35 --- /dev/null +++ b/media/editors/codemirror/addon/lint/index.html @@ -0,0 +1 @@ + diff --git a/media/editors/codemirror/addon/lint/lint.js b/media/editors/codemirror/addon/lint/lint.js index a87e70c09eae2..66f187e22eac8 100644 --- a/media/editors/codemirror/addon/lint/lint.js +++ b/media/editors/codemirror/addon/lint/lint.js @@ -118,10 +118,11 @@ function startLinting(cm) { var state = cm.state.lint, options = state.options; + var passOptions = options.options || options; // Support deprecated passing of `options` property in options if (options.async) - options.getAnnotations(cm, updateLinting, options); + options.getAnnotations(cm.getValue(), updateLinting, passOptions, cm); else - updateLinting(cm, options.getAnnotations(cm.getValue(), options.options)); + updateLinting(cm, options.getAnnotations(cm.getValue(), passOptions, cm)); } function updateLinting(cm, annotationsNotSorted) { @@ -170,20 +171,14 @@ showTooltipFor(e, annotationTooltip(ann), target); } - // When the mouseover fires, the cursor might not actually be over - // the character itself yet. These pairs of x,y offsets are used to - // probe a few nearby points when no suitable marked range is found. - var nearby = [0, 0, 0, 5, 0, -5, 5, 0, -5, 0]; - function onMouseOver(cm, e) { - if (!/\bCodeMirror-lint-mark-/.test((e.target || e.srcElement).className)) return; - for (var i = 0; i < nearby.length; i += 2) { - var spans = cm.findMarksAt(cm.coordsChar({left: e.clientX + nearby[i], - top: e.clientY + nearby[i + 1]}, "client")); - for (var j = 0; j < spans.length; ++j) { - var span = spans[j], ann = span.__annotation; - if (ann) return popupSpanTooltip(ann, e); - } + var target = e.target || e.srcElement; + if (!/\bCodeMirror-lint-mark-/.test(target.className)) return; + var box = target.getBoundingClientRect(), x = (box.left + box.right) / 2, y = (box.top + box.bottom) / 2; + var spans = cm.findMarksAt(cm.coordsChar({left: x, top: y}, "client")); + for (var i = 0; i < spans.length; ++i) { + var ann = spans[i].__annotation; + if (ann) return popupSpanTooltip(ann, e); } } diff --git a/media/editors/codemirror/addon/merge/index.html b/media/editors/codemirror/addon/merge/index.html new file mode 100644 index 0000000000000..2efb97f319a35 --- /dev/null +++ b/media/editors/codemirror/addon/merge/index.html @@ -0,0 +1 @@ + diff --git a/media/editors/codemirror/addon/mode/index.html b/media/editors/codemirror/addon/mode/index.html new file mode 100644 index 0000000000000..2efb97f319a35 --- /dev/null +++ b/media/editors/codemirror/addon/mode/index.html @@ -0,0 +1 @@ + diff --git a/media/editors/codemirror/addon/mode/loadmode.js b/media/editors/codemirror/addon/mode/loadmode.js index 804215877fd0e..10117ec22f250 100644 --- a/media/editors/codemirror/addon/mode/loadmode.js +++ b/media/editors/codemirror/addon/mode/loadmode.js @@ -3,12 +3,12 @@ (function(mod) { if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); + mod(require("../../lib/codemirror"), "cjs"); else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); + define(["../../lib/codemirror"], function(CM) { mod(CM, "amd"); }); else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { + mod(CodeMirror, "plain"); +})(function(CodeMirror, env) { if (!CodeMirror.modeURL) CodeMirror.modeURL = "../mode/%N/%N.js"; var loading = {}; @@ -35,21 +35,24 @@ if (CodeMirror.modes.hasOwnProperty(mode)) return ensureDeps(mode, cont); if (loading.hasOwnProperty(mode)) return loading[mode].push(cont); - var script = document.createElement("script"); - script.src = CodeMirror.modeURL.replace(/%N/g, mode); - var others = document.getElementsByTagName("script")[0]; - others.parentNode.insertBefore(script, others); - var list = loading[mode] = [cont]; - var count = 0, poll = setInterval(function() { - if (++count > 100) return clearInterval(poll); - if (CodeMirror.modes.hasOwnProperty(mode)) { - clearInterval(poll); - loading[mode] = null; + var file = CodeMirror.modeURL.replace(/%N/g, mode); + if (env == "plain") { + var script = document.createElement("script"); + script.src = file; + var others = document.getElementsByTagName("script")[0]; + var list = loading[mode] = [cont]; + CodeMirror.on(script, "load", function() { ensureDeps(mode, function() { for (var i = 0; i < list.length; ++i) list[i](); }); - } - }, 200); + }); + others.parentNode.insertBefore(script, others); + } else if (env == "cjs") { + require(file); + cont(); + } else if (env == "amd") { + requirejs([file], cont); + } }; CodeMirror.autoLoadMode = function(instance, mode) { diff --git a/media/editors/codemirror/addon/mode/overlay.js b/media/editors/codemirror/addon/mode/overlay.js index 393054dfa4417..e1b9ed37530ad 100644 --- a/media/editors/codemirror/addon/mode/overlay.js +++ b/media/editors/codemirror/addon/mode/overlay.js @@ -28,7 +28,7 @@ CodeMirror.overlayMode = function(base, overlay, combine) { overlay: CodeMirror.startState(overlay), basePos: 0, baseCur: null, overlayPos: 0, overlayCur: null, - lineSeen: null + streamSeen: null }; }, copyState: function(state) { @@ -41,9 +41,9 @@ CodeMirror.overlayMode = function(base, overlay, combine) { }, token: function(stream, state) { - if (stream.sol() || stream.string != state.lineSeen || + if (stream != state.streamSeen || Math.min(state.basePos, state.overlayPos) < stream.start) { - state.lineSeen = stream.string; + state.streamSeen = stream; state.basePos = state.overlayPos = stream.start; } diff --git a/media/editors/codemirror/addon/mode/simple.js b/media/editors/codemirror/addon/mode/simple.js new file mode 100644 index 0000000000000..a4a86b9a657d2 --- /dev/null +++ b/media/editors/codemirror/addon/mode/simple.js @@ -0,0 +1,210 @@ +// CodeMirror, copyright (c) by Marijn Haverbeke and others +// Distributed under an MIT license: http://codemirror.net/LICENSE + +(function(mod) { + if (typeof exports == "object" && typeof module == "object") // CommonJS + mod(require("../../lib/codemirror")); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror"], mod); + else // Plain browser env + mod(CodeMirror); +})(function(CodeMirror) { + "use strict"; + + CodeMirror.defineSimpleMode = function(name, states, props) { + CodeMirror.defineMode(name, function(config) { + return CodeMirror.simpleMode(config, states, props); + }); + }; + + CodeMirror.simpleMode = function(config, states) { + ensureState(states, "start"); + var states_ = {}, meta = states.meta || {}, hasIndentation = false; + for (var state in states) if (state != meta && states.hasOwnProperty(state)) { + var list = states_[state] = [], orig = states[state]; + for (var i = 0; i < orig.length; i++) { + var data = orig[i]; + list.push(new Rule(data, states)); + if (data.indent || data.dedent) hasIndentation = true; + } + } + var mode = { + startState: function() { + return {state: "start", pending: null, + local: null, localState: null, + indent: hasIndentation ? [] : null}; + }, + copyState: function(state) { + var s = {state: state.state, pending: state.pending, + local: state.local, localState: null, + indent: state.indent && state.indent.slice(0)}; + if (state.localState) + s.localState = CodeMirror.copyState(state.local.mode, state.localState); + if (state.stack) + s.stack = state.stack.slice(0); + for (var pers = state.persistentStates; pers; pers = pers.next) + s.persistentStates = {mode: pers.mode, + spec: pers.spec, + state: pers.state == state.localState ? s.localState : CodeMirror.copyState(pers.mode, pers.state), + next: s.persistentStates}; + return s; + }, + token: tokenFunction(states_, config), + innerMode: function(state) { return state.local && {mode: state.local.mode, state: state.localState}; }, + indent: indentFunction(states_, meta) + }; + if (meta) for (var prop in meta) if (meta.hasOwnProperty(prop)) + mode[prop] = meta[prop]; + return mode; + }; + + function ensureState(states, name) { + if (!states.hasOwnProperty(name)) + throw new Error("Undefined state " + name + "in simple mode"); + } + + function toRegex(val, caret) { + if (!val) return /(?:)/; + var flags = ""; + if (val instanceof RegExp) { + if (val.ignoreCase) flags = "i"; + val = val.source; + } else { + val = String(val); + } + return new RegExp((caret === false ? "" : "^") + "(?:" + val + ")", flags); + } + + function asToken(val) { + if (!val) return null; + if (typeof val == "string") return val.replace(/\./g, " "); + var result = []; + for (var i = 0; i < val.length; i++) + result.push(val[i] && val[i].replace(/\./g, " ")); + return result; + } + + function Rule(data, states) { + if (data.next || data.push) ensureState(states, data.next || data.push); + this.regex = toRegex(data.regex); + this.token = asToken(data.token); + this.data = data; + } + + function tokenFunction(states, config) { + return function(stream, state) { + if (state.pending) { + var pend = state.pending.shift(); + if (state.pending.length == 0) state.pending = null; + stream.pos += pend.text.length; + return pend.token; + } + + if (state.local) { + if (state.local.end && stream.match(state.local.end)) { + var tok = state.local.endToken || null; + state.local = state.localState = null; + return tok; + } else { + var tok = state.local.mode.token(stream, state.localState), m; + if (state.local.endScan && (m = state.local.endScan.exec(stream.current()))) + stream.pos = stream.start + m.index; + return tok; + } + } + + var curState = states[state.state]; + for (var i = 0; i < curState.length; i++) { + var rule = curState[i]; + var matches = stream.match(rule.regex); + if (matches) { + if (rule.data.next) { + state.state = rule.data.next; + } else if (rule.data.push) { + (state.stack || (state.stack = [])).push(state.state); + state.state = rule.data.push; + } else if (rule.data.pop && state.stack && state.stack.length) { + state.state = state.stack.pop(); + } + + if (rule.data.mode) + enterLocalMode(config, state, rule.data.mode, rule.token); + if (rule.data.indent) + state.indent.push(stream.indentation() + config.indentUnit); + if (rule.data.dedent) + state.indent.pop(); + if (matches.length > 2) { + state.pending = []; + for (var j = 2; j < matches.length; j++) + if (matches[j]) + state.pending.push({text: matches[j], token: rule.token[j - 1]}); + stream.backUp(matches[0].length - (matches[1] ? matches[1].length : 0)); + return rule.token[0]; + } else if (rule.token && rule.token.join) { + return rule.token[0]; + } else { + return rule.token; + } + } + } + stream.next(); + return null; + }; + } + + function cmp(a, b) { + if (a === b) return true; + if (!a || typeof a != "object" || !b || typeof b != "object") return false; + var props = 0; + for (var prop in a) if (a.hasOwnProperty(prop)) { + if (!b.hasOwnProperty(prop) || !cmp(a[prop], b[prop])) return false; + props++; + } + for (var prop in b) if (b.hasOwnProperty(prop)) props--; + return props == 0; + } + + function enterLocalMode(config, state, spec, token) { + var pers; + if (spec.persistent) for (var p = state.persistentStates; p && !pers; p = p.next) + if (spec.spec ? cmp(spec.spec, p.spec) : spec.mode == p.mode) pers = p; + var mode = pers ? pers.mode : spec.mode || CodeMirror.getMode(config, spec.spec); + var lState = pers ? pers.state : CodeMirror.startState(mode); + if (spec.persistent && !pers) + state.persistentStates = {mode: mode, spec: spec.spec, state: lState, next: state.persistentStates}; + + state.localState = lState; + state.local = {mode: mode, + end: spec.end && toRegex(spec.end), + endScan: spec.end && spec.forceEnd !== false && toRegex(spec.end, false), + endToken: token && token.join ? token[token.length - 1] : token}; + } + + function indexOf(val, arr) { + for (var i = 0; i < arr.length; i++) if (arr[i] === val) return true; + } + + function indentFunction(states, meta) { + return function(state, textAfter, line) { + if (state.local && state.local.mode.indent) + return state.local.mode.indent(state.localState, textAfter, line); + if (state.indent == null || state.local || meta.dontIndentStates && indexOf(state.state, meta.dontIndentStates) > -1) + return CodeMirror.Pass; + + var pos = state.indent.length - 1, rules = states[state.state]; + scan: for (;;) { + for (var i = 0; i < rules.length; i++) { + var rule = rules[i], m = rule.regex.exec(textAfter); + if (m && m[0]) { + if (rule.data.dedent && rule.data.dedentIfLineStart !== false) pos--; + if (rule.next || rule.push) rules = states[rule.next || rule.push]; + textAfter = textAfter.slice(m[0].length); + continue scan; + } + } + break; + } + return pos < 0 ? 0 : state.indent[pos]; + }; + } +}); diff --git a/media/editors/codemirror/addon/runmode/index.html b/media/editors/codemirror/addon/runmode/index.html new file mode 100644 index 0000000000000..2efb97f319a35 --- /dev/null +++ b/media/editors/codemirror/addon/runmode/index.html @@ -0,0 +1 @@ + diff --git a/media/editors/codemirror/addon/runmode/runmode-standalone.js b/media/editors/codemirror/addon/runmode/runmode-standalone.js index 0dd0c289b058c..f4f352c803524 100644 --- a/media/editors/codemirror/addon/runmode/runmode-standalone.js +++ b/media/editors/codemirror/addon/runmode/runmode-standalone.js @@ -74,7 +74,11 @@ CodeMirror.startState = function (mode, a1, a2) { }; var modes = CodeMirror.modes = {}, mimeModes = CodeMirror.mimeModes = {}; -CodeMirror.defineMode = function (name, mode) { modes[name] = mode; }; +CodeMirror.defineMode = function (name, mode) { + if (arguments.length > 2) + mode.dependencies = Array.prototype.slice.call(arguments, 2); + modes[name] = mode; +}; CodeMirror.defineMIME = function (mime, spec) { mimeModes[mime] = spec; }; CodeMirror.resolveMode = function(spec) { if (typeof spec == "string" && mimeModes.hasOwnProperty(spec)) { diff --git a/media/editors/codemirror/addon/runmode/runmode.node.js b/media/editors/codemirror/addon/runmode/runmode.node.js index f64b8a152d3d0..8b8140b4c1ae4 100644 --- a/media/editors/codemirror/addon/runmode/runmode.node.js +++ b/media/editors/codemirror/addon/runmode/runmode.node.js @@ -74,10 +74,8 @@ exports.startState = function(mode, a1, a2) { var modes = exports.modes = {}, mimeModes = exports.mimeModes = {}; exports.defineMode = function(name, mode) { - if (arguments.length > 2) { - mode.dependencies = []; - for (var i = 2; i < arguments.length; ++i) mode.dependencies.push(arguments[i]); - } + if (arguments.length > 2) + mode.dependencies = Array.prototype.slice.call(arguments, 2); modes[name] = mode; }; exports.defineMIME = function(mime, spec) { mimeModes[mime] = spec; }; diff --git a/media/editors/codemirror/addon/scroll/index.html b/media/editors/codemirror/addon/scroll/index.html new file mode 100644 index 0000000000000..2efb97f319a35 --- /dev/null +++ b/media/editors/codemirror/addon/scroll/index.html @@ -0,0 +1 @@ + diff --git a/media/editors/codemirror/addon/search/index.html b/media/editors/codemirror/addon/search/index.html new file mode 100644 index 0000000000000..2efb97f319a35 --- /dev/null +++ b/media/editors/codemirror/addon/search/index.html @@ -0,0 +1 @@ + diff --git a/media/editors/codemirror/addon/selection/index.html b/media/editors/codemirror/addon/selection/index.html new file mode 100644 index 0000000000000..2efb97f319a35 --- /dev/null +++ b/media/editors/codemirror/addon/selection/index.html @@ -0,0 +1 @@ + diff --git a/media/editors/codemirror/addon/tern/index.html b/media/editors/codemirror/addon/tern/index.html new file mode 100644 index 0000000000000..2efb97f319a35 --- /dev/null +++ b/media/editors/codemirror/addon/tern/index.html @@ -0,0 +1 @@ + diff --git a/media/editors/codemirror/addon/tern/tern.js b/media/editors/codemirror/addon/tern/tern.js index 4ec976db12df0..9bd69446a2e4a 100644 Binary files a/media/editors/codemirror/addon/tern/tern.js and b/media/editors/codemirror/addon/tern/tern.js differ diff --git a/media/editors/codemirror/addon/wrap/index.html b/media/editors/codemirror/addon/wrap/index.html new file mode 100644 index 0000000000000..2efb97f319a35 --- /dev/null +++ b/media/editors/codemirror/addon/wrap/index.html @@ -0,0 +1 @@ + diff --git a/media/editors/codemirror/keymap/emacs.js b/media/editors/codemirror/keymap/emacs.js index ba8149c70ecd8..4acfd601a0fd9 100644 --- a/media/editors/codemirror/keymap/emacs.js +++ b/media/editors/codemirror/keymap/emacs.js @@ -256,7 +256,7 @@ // Actual keymap - var keyMap = CodeMirror.keyMap.emacs = { + var keyMap = CodeMirror.keyMap.emacs = CodeMirror.normalizeKeyMap({ "Ctrl-W": function(cm) {kill(cm, cm.getCursor("start"), cm.getCursor("end"));}, "Ctrl-K": repeated(function(cm) { var start = cm.getCursor(), end = cm.clipPos(Pos(start.line)); @@ -353,27 +353,7 @@ "Alt-/": "autocomplete", "Ctrl-J": "newlineAndIndent", "Enter": false, "Tab": "indentAuto", - "Alt-G": function(cm) {cm.setOption("keyMap", "emacs-Alt-G");}, - "Ctrl-X": function(cm) {cm.setOption("keyMap", "emacs-Ctrl-X");}, - "Ctrl-Q": function(cm) {cm.setOption("keyMap", "emacs-Ctrl-Q");}, - "Ctrl-U": addPrefixMap - }; - - CodeMirror.keyMap["emacs-Ctrl-X"] = { - "Tab": function(cm) { - cm.indentSelection(getPrefix(cm, true) || cm.getOption("indentUnit")); - }, - "Ctrl-X": function(cm) { - cm.setSelection(cm.getCursor("head"), cm.getCursor("anchor")); - }, - - "Ctrl-S": "save", "Ctrl-W": "save", "S": "saveAll", "F": "open", "U": repeated("undo"), "K": "close", - "Delete": function(cm) { kill(cm, cm.getCursor(), bySentence(cm, cm.getCursor(), 1), true); }, - auto: "emacs", nofallthrough: true, disableInput: true - }; - - CodeMirror.keyMap["emacs-Alt-G"] = { - "G": function(cm) { + "Alt-G G": function(cm) { var prefix = getPrefix(cm, true); if (prefix != null && prefix > 0) return cm.setCursor(prefix - 1); @@ -383,13 +363,24 @@ cm.setCursor(num - 1); }); }, - auto: "emacs", nofallthrough: true, disableInput: true - }; - CodeMirror.keyMap["emacs-Ctrl-Q"] = { - "Tab": repeated("insertTab"), - auto: "emacs", nofallthrough: true - }; + "Ctrl-X Tab": function(cm) { + cm.indentSelection(getPrefix(cm, true) || cm.getOption("indentUnit")); + }, + "Ctrl-X Ctrl-X": function(cm) { + cm.setSelection(cm.getCursor("head"), cm.getCursor("anchor")); + }, + "Ctrl-X Ctrl-S": "save", + "Ctrl-X Ctrl-W": "save", + "Ctrl-X S": "saveAll", + "Ctrl-X F": "open", + "Ctrl-X U": repeated("undo"), + "Ctrl-X K": "close", + "Ctrl-X Delete": function(cm) { kill(cm, cm.getCursor(), bySentence(cm, cm.getCursor(), 1), true); }, + + "Ctrl-Q Tab": repeated("insertTab"), + "Ctrl-U": addPrefixMap + }); var prefixMap = {"Ctrl-G": clearPrefix}; function regPrefix(d) { diff --git a/media/editors/codemirror/keymap/index.html b/media/editors/codemirror/keymap/index.html new file mode 100644 index 0000000000000..2efb97f319a35 --- /dev/null +++ b/media/editors/codemirror/keymap/index.html @@ -0,0 +1 @@ + diff --git a/media/editors/codemirror/keymap/sublime.js b/media/editors/codemirror/keymap/sublime.js index f70a1f98f293b..45936c362892e 100644 --- a/media/editors/codemirror/keymap/sublime.js +++ b/media/editors/codemirror/keymap/sublime.js @@ -386,9 +386,7 @@ map["Alt-Q"] = "wrapLines"; - var mapK = CodeMirror.keyMap["sublime-Ctrl-K"] = {auto: "sublime", nofallthrough: true}; - - map[ctrl + "K"] = function(cm) {cm.setOption("keyMap", "sublime-Ctrl-K");}; + var cK = ctrl + "K "; function modifyWordOrSelection(cm, mod) { cm.operation(function() { @@ -409,9 +407,9 @@ }); } - mapK[ctrl + "Backspace"] = "delLineLeft"; + map[cK + ctrl + "Backspace"] = "delLineLeft"; - cmds[mapK[ctrl + "K"] = "delLineRight"] = function(cm) { + cmds[map[cK + ctrl + "K"] = "delLineRight"] = function(cm) { cm.operation(function() { var ranges = cm.listSelections(); for (var i = ranges.length - 1; i >= 0; i--) @@ -420,22 +418,22 @@ }); }; - cmds[mapK[ctrl + "U"] = "upcaseAtCursor"] = function(cm) { + cmds[map[cK + ctrl + "U"] = "upcaseAtCursor"] = function(cm) { modifyWordOrSelection(cm, function(str) { return str.toUpperCase(); }); }; - cmds[mapK[ctrl + "L"] = "downcaseAtCursor"] = function(cm) { + cmds[map[cK + ctrl + "L"] = "downcaseAtCursor"] = function(cm) { modifyWordOrSelection(cm, function(str) { return str.toLowerCase(); }); }; - cmds[mapK[ctrl + "Space"] = "setSublimeMark"] = function(cm) { + cmds[map[cK + ctrl + "Space"] = "setSublimeMark"] = function(cm) { if (cm.state.sublimeMark) cm.state.sublimeMark.clear(); cm.state.sublimeMark = cm.setBookmark(cm.getCursor()); }; - cmds[mapK[ctrl + "A"] = "selectToSublimeMark"] = function(cm) { + cmds[map[cK + ctrl + "A"] = "selectToSublimeMark"] = function(cm) { var found = cm.state.sublimeMark && cm.state.sublimeMark.find(); if (found) cm.setSelection(cm.getCursor(), found); }; - cmds[mapK[ctrl + "W"] = "deleteToSublimeMark"] = function(cm) { + cmds[map[cK + ctrl + "W"] = "deleteToSublimeMark"] = function(cm) { var found = cm.state.sublimeMark && cm.state.sublimeMark.find(); if (found) { var from = cm.getCursor(), to = found; @@ -444,7 +442,7 @@ cm.replaceRange("", from, to); } }; - cmds[mapK[ctrl + "X"] = "swapWithSublimeMark"] = function(cm) { + cmds[map[cK + ctrl + "X"] = "swapWithSublimeMark"] = function(cm) { var found = cm.state.sublimeMark && cm.state.sublimeMark.find(); if (found) { cm.state.sublimeMark.clear(); @@ -452,13 +450,13 @@ cm.setCursor(found); } }; - cmds[mapK[ctrl + "Y"] = "sublimeYank"] = function(cm) { + cmds[map[cK + ctrl + "Y"] = "sublimeYank"] = function(cm) { if (cm.state.sublimeKilled != null) cm.replaceSelection(cm.state.sublimeKilled, null, "paste"); }; - mapK[ctrl + "G"] = "clearBookmarks"; - cmds[mapK[ctrl + "C"] = "showInCenter"] = function(cm) { + map[cK + ctrl + "G"] = "clearBookmarks"; + cmds[map[cK + ctrl + "C"] = "showInCenter"] = function(cm) { var pos = cm.cursorCoords(null, "local"); cm.scrollTo(null, (pos.top + pos.bottom) / 2 - cm.getScrollInfo().clientHeight / 2); }; @@ -530,7 +528,7 @@ map["Shift-" + ctrl + "["] = "fold"; map["Shift-" + ctrl + "]"] = "unfold"; - mapK[ctrl + "0"] = mapK[ctrl + "j"] = "unfoldAll"; + map[cK + ctrl + "0"] = map[cK + ctrl + "j"] = "unfoldAll"; map[ctrl + "I"] = "findIncremental"; map["Shift-" + ctrl + "I"] = "findIncrementalReverse"; @@ -538,4 +536,5 @@ map["F3"] = "findNext"; map["Shift-F3"] = "findPrev"; + CodeMirror.normalizeKeyMap(map); }); diff --git a/media/editors/codemirror/keymap/vim.js b/media/editors/codemirror/keymap/vim.js index 0bf2c78248891..c5b945cd67520 100644 --- a/media/editors/codemirror/keymap/vim.js +++ b/media/editors/codemirror/keymap/vim.js @@ -72,305 +72,253 @@ var defaultKeymap = [ // Key to key mapping. This goes first to make it possible to override // existing mappings. - { keys: [''], type: 'keyToKey', toKeys: ['h'] }, - { keys: [''], type: 'keyToKey', toKeys: ['l'] }, - { keys: [''], type: 'keyToKey', toKeys: ['k'] }, - { keys: [''], type: 'keyToKey', toKeys: ['j'] }, - { keys: [''], type: 'keyToKey', toKeys: ['l'] }, - { keys: [''], type: 'keyToKey', toKeys: ['h'] }, - { keys: [''], type: 'keyToKey', toKeys: ['W'] }, - { keys: [''], type: 'keyToKey', toKeys: ['B'] }, - { keys: [''], type: 'keyToKey', toKeys: ['w'] }, - { keys: [''], type: 'keyToKey', toKeys: ['b'] }, - { keys: [''], type: 'keyToKey', toKeys: ['j'] }, - { keys: [''], type: 'keyToKey', toKeys: ['k'] }, - { keys: [''], type: 'keyToKey', toKeys: [''] }, - { keys: [''], type: 'keyToKey', toKeys: [''] }, - { keys: ['s'], type: 'keyToKey', toKeys: ['c', 'l'], context: 'normal' }, - { keys: ['s'], type: 'keyToKey', toKeys: ['x', 'i'], context: 'visual'}, - { keys: ['S'], type: 'keyToKey', toKeys: ['c', 'c'], context: 'normal' }, - { keys: ['S'], type: 'keyToKey', toKeys: ['d', 'c', 'c'], context: 'visual' }, - { keys: [''], type: 'keyToKey', toKeys: ['0'] }, - { keys: [''], type: 'keyToKey', toKeys: ['$'] }, - { keys: [''], type: 'keyToKey', toKeys: [''] }, - { keys: [''], type: 'keyToKey', toKeys: [''] }, - { keys: [''], type: 'keyToKey', toKeys: ['j', '^'], context: 'normal' }, + { keys: '', type: 'keyToKey', toKeys: 'h' }, + { keys: '', type: 'keyToKey', toKeys: 'l' }, + { keys: '', type: 'keyToKey', toKeys: 'k' }, + { keys: '', type: 'keyToKey', toKeys: 'j' }, + { keys: '', type: 'keyToKey', toKeys: 'l' }, + { keys: '', type: 'keyToKey', toKeys: 'h' }, + { keys: '', type: 'keyToKey', toKeys: 'W' }, + { keys: '', type: 'keyToKey', toKeys: 'B' }, + { keys: '', type: 'keyToKey', toKeys: 'w' }, + { keys: '', type: 'keyToKey', toKeys: 'b' }, + { keys: '', type: 'keyToKey', toKeys: 'j' }, + { keys: '', type: 'keyToKey', toKeys: 'k' }, + { keys: '', type: 'keyToKey', toKeys: '' }, + { keys: '', type: 'keyToKey', toKeys: '' }, + { keys: '', type: 'keyToKey', toKeys: '', context: 'insert' }, + { keys: '', type: 'keyToKey', toKeys: '', context: 'insert' }, + { keys: 's', type: 'keyToKey', toKeys: 'cl', context: 'normal' }, + { keys: 's', type: 'keyToKey', toKeys: 'xi', context: 'visual'}, + { keys: 'S', type: 'keyToKey', toKeys: 'cc', context: 'normal' }, + { keys: 'S', type: 'keyToKey', toKeys: 'dcc', context: 'visual' }, + { keys: '', type: 'keyToKey', toKeys: '0' }, + { keys: '', type: 'keyToKey', toKeys: '$' }, + { keys: '', type: 'keyToKey', toKeys: '' }, + { keys: '', type: 'keyToKey', toKeys: '' }, + { keys: '', type: 'keyToKey', toKeys: 'j^', context: 'normal' }, // Motions - { keys: ['H'], type: 'motion', - motion: 'moveToTopLine', - motionArgs: { linewise: true, toJumplist: true }}, - { keys: ['M'], type: 'motion', - motion: 'moveToMiddleLine', - motionArgs: { linewise: true, toJumplist: true }}, - { keys: ['L'], type: 'motion', - motion: 'moveToBottomLine', - motionArgs: { linewise: true, toJumplist: true }}, - { keys: ['h'], type: 'motion', - motion: 'moveByCharacters', - motionArgs: { forward: false }}, - { keys: ['l'], type: 'motion', - motion: 'moveByCharacters', - motionArgs: { forward: true }}, - { keys: ['j'], type: 'motion', - motion: 'moveByLines', - motionArgs: { forward: true, linewise: true }}, - { keys: ['k'], type: 'motion', - motion: 'moveByLines', - motionArgs: { forward: false, linewise: true }}, - { keys: ['g','j'], type: 'motion', - motion: 'moveByDisplayLines', - motionArgs: { forward: true }}, - { keys: ['g','k'], type: 'motion', - motion: 'moveByDisplayLines', - motionArgs: { forward: false }}, - { keys: ['w'], type: 'motion', - motion: 'moveByWords', - motionArgs: { forward: true, wordEnd: false }}, - { keys: ['W'], type: 'motion', - motion: 'moveByWords', - motionArgs: { forward: true, wordEnd: false, bigWord: true }}, - { keys: ['e'], type: 'motion', - motion: 'moveByWords', - motionArgs: { forward: true, wordEnd: true, inclusive: true }}, - { keys: ['E'], type: 'motion', - motion: 'moveByWords', - motionArgs: { forward: true, wordEnd: true, bigWord: true, - inclusive: true }}, - { keys: ['b'], type: 'motion', - motion: 'moveByWords', - motionArgs: { forward: false, wordEnd: false }}, - { keys: ['B'], type: 'motion', - motion: 'moveByWords', - motionArgs: { forward: false, wordEnd: false, bigWord: true }}, - { keys: ['g', 'e'], type: 'motion', - motion: 'moveByWords', - motionArgs: { forward: false, wordEnd: true, inclusive: true }}, - { keys: ['g', 'E'], type: 'motion', - motion: 'moveByWords', - motionArgs: { forward: false, wordEnd: true, bigWord: true, - inclusive: true }}, - { keys: ['{'], type: 'motion', motion: 'moveByParagraph', - motionArgs: { forward: false, toJumplist: true }}, - { keys: ['}'], type: 'motion', motion: 'moveByParagraph', - motionArgs: { forward: true, toJumplist: true }}, - { keys: [''], type: 'motion', - motion: 'moveByPage', motionArgs: { forward: true }}, - { keys: [''], type: 'motion', - motion: 'moveByPage', motionArgs: { forward: false }}, - { keys: [''], type: 'motion', - motion: 'moveByScroll', - motionArgs: { forward: true, explicitRepeat: true }}, - { keys: [''], type: 'motion', - motion: 'moveByScroll', - motionArgs: { forward: false, explicitRepeat: true }}, - { keys: ['g', 'g'], type: 'motion', - motion: 'moveToLineOrEdgeOfDocument', - motionArgs: { forward: false, explicitRepeat: true, linewise: true, toJumplist: true }}, - { keys: ['G'], type: 'motion', - motion: 'moveToLineOrEdgeOfDocument', - motionArgs: { forward: true, explicitRepeat: true, linewise: true, toJumplist: true }}, - { keys: ['0'], type: 'motion', motion: 'moveToStartOfLine' }, - { keys: ['^'], type: 'motion', - motion: 'moveToFirstNonWhiteSpaceCharacter' }, - { keys: ['+'], type: 'motion', - motion: 'moveByLines', - motionArgs: { forward: true, toFirstChar:true }}, - { keys: ['-'], type: 'motion', - motion: 'moveByLines', - motionArgs: { forward: false, toFirstChar:true }}, - { keys: ['_'], type: 'motion', - motion: 'moveByLines', - motionArgs: { forward: true, toFirstChar:true, repeatOffset:-1 }}, - { keys: ['$'], type: 'motion', - motion: 'moveToEol', - motionArgs: { inclusive: true }}, - { keys: ['%'], type: 'motion', - motion: 'moveToMatchedSymbol', - motionArgs: { inclusive: true, toJumplist: true }}, - { keys: ['f', 'character'], type: 'motion', - motion: 'moveToCharacter', - motionArgs: { forward: true , inclusive: true }}, - { keys: ['F', 'character'], type: 'motion', - motion: 'moveToCharacter', - motionArgs: { forward: false }}, - { keys: ['t', 'character'], type: 'motion', - motion: 'moveTillCharacter', - motionArgs: { forward: true, inclusive: true }}, - { keys: ['T', 'character'], type: 'motion', - motion: 'moveTillCharacter', - motionArgs: { forward: false }}, - { keys: [';'], type: 'motion', motion: 'repeatLastCharacterSearch', - motionArgs: { forward: true }}, - { keys: [','], type: 'motion', motion: 'repeatLastCharacterSearch', - motionArgs: { forward: false }}, - { keys: ['\'', 'character'], type: 'motion', motion: 'goToMark', - motionArgs: {toJumplist: true, linewise: true}}, - { keys: ['`', 'character'], type: 'motion', motion: 'goToMark', - motionArgs: {toJumplist: true}}, - { keys: [']', '`'], type: 'motion', motion: 'jumpToMark', motionArgs: { forward: true } }, - { keys: ['[', '`'], type: 'motion', motion: 'jumpToMark', motionArgs: { forward: false } }, - { keys: [']', '\''], type: 'motion', motion: 'jumpToMark', motionArgs: { forward: true, linewise: true } }, - { keys: ['[', '\''], type: 'motion', motion: 'jumpToMark', motionArgs: { forward: false, linewise: true } }, + { keys: 'H', type: 'motion', motion: 'moveToTopLine', motionArgs: { linewise: true, toJumplist: true }}, + { keys: 'M', type: 'motion', motion: 'moveToMiddleLine', motionArgs: { linewise: true, toJumplist: true }}, + { keys: 'L', type: 'motion', motion: 'moveToBottomLine', motionArgs: { linewise: true, toJumplist: true }}, + { keys: 'h', type: 'motion', motion: 'moveByCharacters', motionArgs: { forward: false }}, + { keys: 'l', type: 'motion', motion: 'moveByCharacters', motionArgs: { forward: true }}, + { keys: 'j', type: 'motion', motion: 'moveByLines', motionArgs: { forward: true, linewise: true }}, + { keys: 'k', type: 'motion', motion: 'moveByLines', motionArgs: { forward: false, linewise: true }}, + { keys: 'gj', type: 'motion', motion: 'moveByDisplayLines', motionArgs: { forward: true }}, + { keys: 'gk', type: 'motion', motion: 'moveByDisplayLines', motionArgs: { forward: false }}, + { keys: 'w', type: 'motion', motion: 'moveByWords', motionArgs: { forward: true, wordEnd: false }}, + { keys: 'W', type: 'motion', motion: 'moveByWords', motionArgs: { forward: true, wordEnd: false, bigWord: true }}, + { keys: 'e', type: 'motion', motion: 'moveByWords', motionArgs: { forward: true, wordEnd: true, inclusive: true }}, + { keys: 'E', type: 'motion', motion: 'moveByWords', motionArgs: { forward: true, wordEnd: true, bigWord: true, inclusive: true }}, + { keys: 'b', type: 'motion', motion: 'moveByWords', motionArgs: { forward: false, wordEnd: false }}, + { keys: 'B', type: 'motion', motion: 'moveByWords', motionArgs: { forward: false, wordEnd: false, bigWord: true }}, + { keys: 'ge', type: 'motion', motion: 'moveByWords', motionArgs: { forward: false, wordEnd: true, inclusive: true }}, + { keys: 'gE', type: 'motion', motion: 'moveByWords', motionArgs: { forward: false, wordEnd: true, bigWord: true, inclusive: true }}, + { keys: '{', type: 'motion', motion: 'moveByParagraph', motionArgs: { forward: false, toJumplist: true }}, + { keys: '}', type: 'motion', motion: 'moveByParagraph', motionArgs: { forward: true, toJumplist: true }}, + { keys: '', type: 'motion', motion: 'moveByPage', motionArgs: { forward: true }}, + { keys: '', type: 'motion', motion: 'moveByPage', motionArgs: { forward: false }}, + { keys: '', type: 'motion', motion: 'moveByScroll', motionArgs: { forward: true, explicitRepeat: true }}, + { keys: '', type: 'motion', motion: 'moveByScroll', motionArgs: { forward: false, explicitRepeat: true }}, + { keys: 'gg', type: 'motion', motion: 'moveToLineOrEdgeOfDocument', motionArgs: { forward: false, explicitRepeat: true, linewise: true, toJumplist: true }}, + { keys: 'G', type: 'motion', motion: 'moveToLineOrEdgeOfDocument', motionArgs: { forward: true, explicitRepeat: true, linewise: true, toJumplist: true }}, + { keys: '0', type: 'motion', motion: 'moveToStartOfLine' }, + { keys: '^', type: 'motion', motion: 'moveToFirstNonWhiteSpaceCharacter' }, + { keys: '+', type: 'motion', motion: 'moveByLines', motionArgs: { forward: true, toFirstChar:true }}, + { keys: '-', type: 'motion', motion: 'moveByLines', motionArgs: { forward: false, toFirstChar:true }}, + { keys: '_', type: 'motion', motion: 'moveByLines', motionArgs: { forward: true, toFirstChar:true, repeatOffset:-1 }}, + { keys: '$', type: 'motion', motion: 'moveToEol', motionArgs: { inclusive: true }}, + { keys: '%', type: 'motion', motion: 'moveToMatchedSymbol', motionArgs: { inclusive: true, toJumplist: true }}, + { keys: 'f', type: 'motion', motion: 'moveToCharacter', motionArgs: { forward: true , inclusive: true }}, + { keys: 'F', type: 'motion', motion: 'moveToCharacter', motionArgs: { forward: false }}, + { keys: 't', type: 'motion', motion: 'moveTillCharacter', motionArgs: { forward: true, inclusive: true }}, + { keys: 'T', type: 'motion', motion: 'moveTillCharacter', motionArgs: { forward: false }}, + { keys: ';', type: 'motion', motion: 'repeatLastCharacterSearch', motionArgs: { forward: true }}, + { keys: ',', type: 'motion', motion: 'repeatLastCharacterSearch', motionArgs: { forward: false }}, + { keys: '\'', type: 'motion', motion: 'goToMark', motionArgs: {toJumplist: true, linewise: true}}, + { keys: '`', type: 'motion', motion: 'goToMark', motionArgs: {toJumplist: true}}, + { keys: ']`', type: 'motion', motion: 'jumpToMark', motionArgs: { forward: true } }, + { keys: '[`', type: 'motion', motion: 'jumpToMark', motionArgs: { forward: false } }, + { keys: ']\'', type: 'motion', motion: 'jumpToMark', motionArgs: { forward: true, linewise: true } }, + { keys: '[\'', type: 'motion', motion: 'jumpToMark', motionArgs: { forward: false, linewise: true } }, // the next two aren't motions but must come before more general motion declarations - { keys: [']', 'p'], type: 'action', action: 'paste', isEdit: true, - actionArgs: { after: true, isEdit: true, matchIndent: true}}, - { keys: ['[', 'p'], type: 'action', action: 'paste', isEdit: true, - actionArgs: { after: false, isEdit: true, matchIndent: true}}, - { keys: [']', 'character'], type: 'motion', - motion: 'moveToSymbol', - motionArgs: { forward: true, toJumplist: true}}, - { keys: ['[', 'character'], type: 'motion', - motion: 'moveToSymbol', - motionArgs: { forward: false, toJumplist: true}}, - { keys: ['|'], type: 'motion', - motion: 'moveToColumn', - motionArgs: { }}, - { keys: ['o'], type: 'motion', motion: 'moveToOtherHighlightedEnd', motionArgs: { }, context:'visual'}, - { keys: ['O'], type: 'motion', motion: 'moveToOtherHighlightedEnd', motionArgs: {sameLine: true}, context:'visual'}, + { keys: ']p', type: 'action', action: 'paste', isEdit: true, actionArgs: { after: true, isEdit: true, matchIndent: true}}, + { keys: '[p', type: 'action', action: 'paste', isEdit: true, actionArgs: { after: false, isEdit: true, matchIndent: true}}, + { keys: ']', type: 'motion', motion: 'moveToSymbol', motionArgs: { forward: true, toJumplist: true}}, + { keys: '[', type: 'motion', motion: 'moveToSymbol', motionArgs: { forward: false, toJumplist: true}}, + { keys: '|', type: 'motion', motion: 'moveToColumn'}, + { keys: 'o', type: 'motion', motion: 'moveToOtherHighlightedEnd', context:'visual'}, + { keys: 'O', type: 'motion', motion: 'moveToOtherHighlightedEnd', motionArgs: {sameLine: true}, context:'visual'}, // Operators - { keys: ['d'], type: 'operator', operator: 'delete' }, - { keys: ['y'], type: 'operator', operator: 'yank' }, - { keys: ['c'], type: 'operator', operator: 'change' }, - { keys: ['>'], type: 'operator', operator: 'indent', - operatorArgs: { indentRight: true }}, - { keys: ['<'], type: 'operator', operator: 'indent', - operatorArgs: { indentRight: false }}, - { keys: ['g', '~'], type: 'operator', operator: 'swapcase' }, - { keys: ['n'], type: 'motion', motion: 'findNext', - motionArgs: { forward: true, toJumplist: true }}, - { keys: ['N'], type: 'motion', motion: 'findNext', - motionArgs: { forward: false, toJumplist: true }}, + { keys: 'd', type: 'operator', operator: 'delete' }, + { keys: 'y', type: 'operator', operator: 'yank' }, + { keys: 'c', type: 'operator', operator: 'change' }, + { keys: '>', type: 'operator', operator: 'indent', operatorArgs: { indentRight: true }}, + { keys: '<', type: 'operator', operator: 'indent', operatorArgs: { indentRight: false }}, + { keys: 'g~', type: 'operator', operator: 'changeCase' }, + { keys: 'gu', type: 'operator', operator: 'changeCase', operatorArgs: {toLower: true}, isEdit: true }, + { keys: 'gU', type: 'operator', operator: 'changeCase', operatorArgs: {toLower: false}, isEdit: true }, + { keys: 'n', type: 'motion', motion: 'findNext', motionArgs: { forward: true, toJumplist: true }}, + { keys: 'N', type: 'motion', motion: 'findNext', motionArgs: { forward: false, toJumplist: true }}, // Operator-Motion dual commands - { keys: ['x'], type: 'operatorMotion', operator: 'delete', - motion: 'moveByCharacters', motionArgs: { forward: true }, - operatorMotionArgs: { visualLine: false }}, - { keys: ['X'], type: 'operatorMotion', operator: 'delete', - motion: 'moveByCharacters', motionArgs: { forward: false }, - operatorMotionArgs: { visualLine: true }}, - { keys: ['D'], type: 'operatorMotion', operator: 'delete', - motion: 'moveToEol', motionArgs: { inclusive: true }, - operatorMotionArgs: { visualLine: true }}, - { keys: ['Y'], type: 'operatorMotion', operator: 'yank', - motion: 'moveToEol', motionArgs: { inclusive: true }, - operatorMotionArgs: { visualLine: true }}, - { keys: ['C'], type: 'operatorMotion', - operator: 'change', - motion: 'moveToEol', motionArgs: { inclusive: true }, - operatorMotionArgs: { visualLine: true }}, - { keys: ['~'], type: 'operatorMotion', - operator: 'swapcase', operatorArgs: { shouldMoveCursor: true }, - motion: 'moveByCharacters', motionArgs: { forward: true }}, + { keys: 'x', type: 'operatorMotion', operator: 'delete', motion: 'moveByCharacters', motionArgs: { forward: true }, operatorMotionArgs: { visualLine: false }}, + { keys: 'X', type: 'operatorMotion', operator: 'delete', motion: 'moveByCharacters', motionArgs: { forward: false }, operatorMotionArgs: { visualLine: true }}, + { keys: 'D', type: 'operatorMotion', operator: 'delete', motion: 'moveToEol', motionArgs: { inclusive: true }, context: 'normal'}, + { keys: 'D', type: 'operator', operator: 'delete', operatorArgs: { linewise: true }, context: 'visual'}, + { keys: 'Y', type: 'operatorMotion', operator: 'yank', motion: 'moveToEol', motionArgs: { inclusive: true }, context: 'normal'}, + { keys: 'Y', type: 'operator', operator: 'yank', operatorArgs: { linewise: true }, context: 'visual'}, + { keys: 'C', type: 'operatorMotion', operator: 'change', motion: 'moveToEol', motionArgs: { inclusive: true }, context: 'normal'}, + { keys: 'C', type: 'operator', operator: 'change', operatorArgs: { linewise: true }, context: 'visual'}, + { keys: '~', type: 'operatorMotion', operator: 'changeCase', motion: 'moveByCharacters', motionArgs: { forward: true }, operatorArgs: { shouldMoveCursor: true }, context: 'normal'}, + { keys: '~', type: 'operator', operator: 'changeCase', context: 'visual'}, + { keys: '', type: 'operatorMotion', operator: 'delete', motion: 'moveByWords', motionArgs: { forward: false, wordEnd: false }, context: 'insert' }, // Actions - { keys: [''], type: 'action', action: 'jumpListWalk', - actionArgs: { forward: true }}, - { keys: [''], type: 'action', action: 'jumpListWalk', - actionArgs: { forward: false }}, - { keys: [''], type: 'action', - action: 'scroll', - actionArgs: { forward: true, linewise: true }}, - { keys: [''], type: 'action', - action: 'scroll', - actionArgs: { forward: false, linewise: true }}, - { keys: ['a'], type: 'action', action: 'enterInsertMode', isEdit: true, - actionArgs: { insertAt: 'charAfter' }}, - { keys: ['A'], type: 'action', action: 'enterInsertMode', isEdit: true, - actionArgs: { insertAt: 'eol' }}, - { keys: ['A'], type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'endOfSelectedArea' }, context: 'visual' }, - { keys: ['i'], type: 'action', action: 'enterInsertMode', isEdit: true, - actionArgs: { insertAt: 'inplace' }}, - { keys: ['I'], type: 'action', action: 'enterInsertMode', isEdit: true, - actionArgs: { insertAt: 'firstNonBlank' }}, - { keys: ['o'], type: 'action', action: 'newLineAndEnterInsertMode', - isEdit: true, interlaceInsertRepeat: true, - actionArgs: { after: true }}, - { keys: ['O'], type: 'action', action: 'newLineAndEnterInsertMode', - isEdit: true, interlaceInsertRepeat: true, - actionArgs: { after: false }}, - { keys: ['v'], type: 'action', action: 'toggleVisualMode' }, - { keys: ['V'], type: 'action', action: 'toggleVisualMode', - actionArgs: { linewise: true }}, - { keys: [''], type: 'action', action: 'toggleVisualMode', - actionArgs: { blockwise: true }}, - { keys: ['g', 'v'], type: 'action', action: 'reselectLastSelection' }, - { keys: ['J'], type: 'action', action: 'joinLines', isEdit: true }, - { keys: ['p'], type: 'action', action: 'paste', isEdit: true, - actionArgs: { after: true, isEdit: true }}, - { keys: ['P'], type: 'action', action: 'paste', isEdit: true, - actionArgs: { after: false, isEdit: true }}, - { keys: ['r', 'character'], type: 'action', action: 'replace', isEdit: true }, - { keys: ['@', 'character'], type: 'action', action: 'replayMacro' }, - { keys: ['q', 'character'], type: 'action', action: 'enterMacroRecordMode' }, + { keys: '', type: 'action', action: 'jumpListWalk', actionArgs: { forward: true }}, + { keys: '', type: 'action', action: 'jumpListWalk', actionArgs: { forward: false }}, + { keys: '', type: 'action', action: 'scroll', actionArgs: { forward: true, linewise: true }}, + { keys: '', type: 'action', action: 'scroll', actionArgs: { forward: false, linewise: true }}, + { keys: 'a', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'charAfter' }, context: 'normal' }, + { keys: 'A', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'eol' }, context: 'normal' }, + { keys: 'A', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'endOfSelectedArea' }, context: 'visual' }, + { keys: 'i', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'inplace' }, context: 'normal' }, + { keys: 'I', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'firstNonBlank'}, context: 'normal' }, + { keys: 'I', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'startOfSelectedArea' }, context: 'visual' }, + { keys: 'o', type: 'action', action: 'newLineAndEnterInsertMode', isEdit: true, interlaceInsertRepeat: true, actionArgs: { after: true }, context: 'normal' }, + { keys: 'O', type: 'action', action: 'newLineAndEnterInsertMode', isEdit: true, interlaceInsertRepeat: true, actionArgs: { after: false }, context: 'normal' }, + { keys: 'v', type: 'action', action: 'toggleVisualMode' }, + { keys: 'V', type: 'action', action: 'toggleVisualMode', actionArgs: { linewise: true }}, + { keys: '', type: 'action', action: 'toggleVisualMode', actionArgs: { blockwise: true }}, + { keys: 'gv', type: 'action', action: 'reselectLastSelection' }, + { keys: 'J', type: 'action', action: 'joinLines', isEdit: true }, + { keys: 'p', type: 'action', action: 'paste', isEdit: true, actionArgs: { after: true, isEdit: true }}, + { keys: 'P', type: 'action', action: 'paste', isEdit: true, actionArgs: { after: false, isEdit: true }}, + { keys: 'r', type: 'action', action: 'replace', isEdit: true }, + { keys: '@', type: 'action', action: 'replayMacro' }, + { keys: 'q', type: 'action', action: 'enterMacroRecordMode' }, // Handle Replace-mode as a special case of insert mode. - { keys: ['R'], type: 'action', action: 'enterInsertMode', isEdit: true, - actionArgs: { replace: true }}, - { keys: ['u'], type: 'action', action: 'undo' }, - { keys: ['u'], type: 'action', action: 'changeCase', actionArgs: {toLower: true}, context: 'visual', isEdit: true }, - { keys: ['U'],type: 'action', action: 'changeCase', actionArgs: {toLower: false}, context: 'visual', isEdit: true }, - { keys: [''], type: 'action', action: 'redo' }, - { keys: ['m', 'character'], type: 'action', action: 'setMark' }, - { keys: ['"', 'character'], type: 'action', action: 'setRegister' }, - { keys: ['z', 'z'], type: 'action', action: 'scrollToCursor', - actionArgs: { position: 'center' }}, - { keys: ['z', '.'], type: 'action', action: 'scrollToCursor', - actionArgs: { position: 'center' }, - motion: 'moveToFirstNonWhiteSpaceCharacter' }, - { keys: ['z', 't'], type: 'action', action: 'scrollToCursor', - actionArgs: { position: 'top' }}, - { keys: ['z', ''], type: 'action', action: 'scrollToCursor', - actionArgs: { position: 'top' }, - motion: 'moveToFirstNonWhiteSpaceCharacter' }, - { keys: ['z', '-'], type: 'action', action: 'scrollToCursor', - actionArgs: { position: 'bottom' }}, - { keys: ['z', 'b'], type: 'action', action: 'scrollToCursor', - actionArgs: { position: 'bottom' }, - motion: 'moveToFirstNonWhiteSpaceCharacter' }, - { keys: ['.'], type: 'action', action: 'repeatLastEdit' }, - { keys: [''], type: 'action', action: 'incrementNumberToken', - isEdit: true, - actionArgs: {increase: true, backtrack: false}}, - { keys: [''], type: 'action', action: 'incrementNumberToken', - isEdit: true, - actionArgs: {increase: false, backtrack: false}}, + { keys: 'R', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { replace: true }}, + { keys: 'u', type: 'action', action: 'undo', context: 'normal' }, + { keys: 'u', type: 'operator', operator: 'changeCase', operatorArgs: {toLower: true}, context: 'visual', isEdit: true }, + { keys: 'U', type: 'operator', operator: 'changeCase', operatorArgs: {toLower: false}, context: 'visual', isEdit: true }, + { keys: '', type: 'action', action: 'redo' }, + { keys: 'm', type: 'action', action: 'setMark' }, + { keys: '"', type: 'action', action: 'setRegister' }, + { keys: 'zz', type: 'action', action: 'scrollToCursor', actionArgs: { position: 'center' }}, + { keys: 'z.', type: 'action', action: 'scrollToCursor', actionArgs: { position: 'center' }, motion: 'moveToFirstNonWhiteSpaceCharacter' }, + { keys: 'zt', type: 'action', action: 'scrollToCursor', actionArgs: { position: 'top' }}, + { keys: 'z', type: 'action', action: 'scrollToCursor', actionArgs: { position: 'top' }, motion: 'moveToFirstNonWhiteSpaceCharacter' }, + { keys: 'z-', type: 'action', action: 'scrollToCursor', actionArgs: { position: 'bottom' }}, + { keys: 'zb', type: 'action', action: 'scrollToCursor', actionArgs: { position: 'bottom' }, motion: 'moveToFirstNonWhiteSpaceCharacter' }, + { keys: '.', type: 'action', action: 'repeatLastEdit' }, + { keys: '', type: 'action', action: 'incrementNumberToken', isEdit: true, actionArgs: {increase: true, backtrack: false}}, + { keys: '', type: 'action', action: 'incrementNumberToken', isEdit: true, actionArgs: {increase: false, backtrack: false}}, // Text object motions - { keys: ['a', 'character'], type: 'motion', - motion: 'textObjectManipulation' }, - { keys: ['i', 'character'], type: 'motion', - motion: 'textObjectManipulation', - motionArgs: { textObjectInner: true }}, + { keys: 'a', type: 'motion', motion: 'textObjectManipulation' }, + { keys: 'i', type: 'motion', motion: 'textObjectManipulation', motionArgs: { textObjectInner: true }}, // Search - { keys: ['/'], type: 'search', - searchArgs: { forward: true, querySrc: 'prompt', toJumplist: true }}, - { keys: ['?'], type: 'search', - searchArgs: { forward: false, querySrc: 'prompt', toJumplist: true }}, - { keys: ['*'], type: 'search', - searchArgs: { forward: true, querySrc: 'wordUnderCursor', wholeWordOnly: true, toJumplist: true }}, - { keys: ['#'], type: 'search', - searchArgs: { forward: false, querySrc: 'wordUnderCursor', wholeWordOnly: true, toJumplist: true }}, - { keys: ['g', '*'], type: 'search', searchArgs: { forward: true, querySrc: 'wordUnderCursor', toJumplist: true }}, - { keys: ['g', '#'], type: 'search', searchArgs: { forward: false, querySrc: 'wordUnderCursor', toJumplist: true }}, + { keys: '/', type: 'search', searchArgs: { forward: true, querySrc: 'prompt', toJumplist: true }}, + { keys: '?', type: 'search', searchArgs: { forward: false, querySrc: 'prompt', toJumplist: true }}, + { keys: '*', type: 'search', searchArgs: { forward: true, querySrc: 'wordUnderCursor', wholeWordOnly: true, toJumplist: true }}, + { keys: '#', type: 'search', searchArgs: { forward: false, querySrc: 'wordUnderCursor', wholeWordOnly: true, toJumplist: true }}, + { keys: 'g*', type: 'search', searchArgs: { forward: true, querySrc: 'wordUnderCursor', toJumplist: true }}, + { keys: 'g#', type: 'search', searchArgs: { forward: false, querySrc: 'wordUnderCursor', toJumplist: true }}, // Ex command - { keys: [':'], type: 'ex' } + { keys: ':', type: 'ex' } ]; var Pos = CodeMirror.Pos; + var modifierCodes = [16, 17, 18, 91]; + var specialKey = {Enter:'CR',Backspace:'BS',Delete:'Del'}; + var mac = /Mac/.test(navigator.platform); var Vim = function() { - CodeMirror.defineOption('vimMode', false, function(cm, val) { - if (val) { - cm.setOption('keyMap', 'vim'); - cm.setOption('disableInput', true); - cm.setOption('showCursorWhenSelecting', false); - CodeMirror.signal(cm, "vim-mode-change", {mode: "normal"}); - cm.on('cursorActivity', onCursorActivity); - maybeInitVimState(cm); - CodeMirror.on(cm.getInputField(), 'paste', getOnPasteFn(cm)); - } else if (cm.state.vim) { - cm.setOption('keyMap', 'default'); - cm.setOption('disableInput', false); - cm.off('cursorActivity', onCursorActivity); - CodeMirror.off(cm.getInputField(), 'paste', getOnPasteFn(cm)); - cm.state.vim = null; + function lookupKey(e) { + var keyCode = e.keyCode; + if (modifierCodes.indexOf(keyCode) != -1) { return; } + var hasModifier = e.ctrlKey || e.metaKey; + var key = CodeMirror.keyNames[keyCode]; + key = specialKey[key] || key; + var name = ''; + if (e.ctrlKey) { name += 'C-'; } + if (e.altKey) { name += 'A-'; } + if (mac && e.metaKey || (!hasModifier && e.shiftKey) && key.length < 2) { + // Shift key bindings can only specified for special characters. + return; + } else if (e.shiftKey && !/^[A-Za-z]$/.test(key)) { + name += 'S-'; + } + if (key.length == 1) { key = key.toLowerCase(); } + name += key; + if (name.length > 1) { name = '<' + name + '>'; } + return name; + } + // Keys with modifiers are handled using keydown due to limitations of + // keypress event. + function handleKeyDown(cm, e) { + var name = lookupKey(e); + if (!name) { return; } + + CodeMirror.signal(cm, 'vim-keypress', name); + if (CodeMirror.Vim.handleKey(cm, name, 'user')) { + CodeMirror.e_stop(e); } + } + // Keys without modifiers are handled using keypress to work best with + // non-standard keyboard layouts. + function handleKeyPress(cm, e) { + var code = e.charCode || e.keyCode; + if (e.ctrlKey || e.metaKey || e.altKey || + e.shiftKey && code < 32) { return; } + var name = String.fromCharCode(code); + + CodeMirror.signal(cm, 'vim-keypress', name); + if (CodeMirror.Vim.handleKey(cm, name, 'user')) { + CodeMirror.e_stop(e); + } + } + + function enterVimMode(cm) { + cm.setOption('disableInput', true); + cm.setOption('showCursorWhenSelecting', false); + CodeMirror.signal(cm, "vim-mode-change", {mode: "normal"}); + cm.on('cursorActivity', onCursorActivity); + maybeInitVimState(cm); + CodeMirror.on(cm.getInputField(), 'paste', getOnPasteFn(cm)); + cm.on('keypress', handleKeyPress); + cm.on('keydown', handleKeyDown); + } + + function leaveVimMode(cm) { + cm.setOption('disableInput', false); + cm.off('cursorActivity', onCursorActivity); + CodeMirror.off(cm.getInputField(), 'paste', getOnPasteFn(cm)); + cm.state.vim = null; + cm.off('keypress', handleKeyPress); + cm.off('keydown', handleKeyDown); + } + + function detachVimMap(cm, next) { + if (this == CodeMirror.keyMap.vim) + CodeMirror.rmClass(cm.getWrapperElement(), "cm-fat-cursor"); + + if (!next || next.attach != attachVimMap) + leaveVimMode(cm, false); + } + function attachVimMap(cm, prev) { + if (this == CodeMirror.keyMap.vim) + CodeMirror.addClass(cm.getWrapperElement(), "cm-fat-cursor"); + + if (!prev || prev.attach != attachVimMap) + enterVimMode(cm); + } + + // Deprecated, simply setting the keymap works again. + CodeMirror.defineOption('vimMode', false, function(cm, val, prev) { + if (val && cm.getOption("keyMap") != "vim") + cm.setOption("keyMap", "vim"); + else if (!val && prev != CodeMirror.Init && /^vim/.test(cm.getOption("keyMap"))) + cm.setOption("keyMap", "default"); }); function getOnPasteFn(cm) { var vim = cm.state.vim; @@ -397,9 +345,6 @@ var upperCaseAlphabet = makeKeyRange(65, 26); var lowerCaseAlphabet = makeKeyRange(97, 26); var numbers = makeKeyRange(48, 10); - var specialSymbols = '~`!@#$%^&*()_-+=[{}]\\|/?.,<>:;"\''.split(''); - var specialKeys = ['Left', 'Right', 'Up', 'Down', 'Space', 'Backspace', - 'Esc', 'Home', 'End', 'PageUp', 'PageDown', 'Enter']; var validMarks = [].concat(upperCaseAlphabet, lowerCaseAlphabet, numbers, ['<', '>']); var validRegisters = [].concat(upperCaseAlphabet, lowerCaseAlphabet, numbers, ['-', '"', '.', ':', '/']); @@ -617,8 +562,8 @@ visualBlock: false, lastSelection: null, lastPastedText: null, - // Used by two-character ESC keymap routines. Should not be changed from false here. - awaitingEscapeSecondCharacter: false + sel: { + } }; } return cm.state.vim; @@ -648,6 +593,7 @@ } } + var lastInsertModeKeyTimer; var vimApi= { buildKeyMap: function() { // TODO: Convert keymap into dictionary format for fast lookup. @@ -685,58 +631,121 @@ }, // This is the outermost function called by CodeMirror, after keys have // been mapped to their Vim equivalents. - handleKey: function(cm, key) { - var command; + handleKey: function(cm, key, origin) { var vim = maybeInitVimState(cm); - var macroModeState = vimGlobalState.macroModeState; - if (macroModeState.isRecording) { - if (key == 'q') { - macroModeState.exitMacroRecordMode(); + function handleMacroRecording() { + var macroModeState = vimGlobalState.macroModeState; + if (macroModeState.isRecording) { + if (key == 'q') { + macroModeState.exitMacroRecordMode(); + clearInputState(cm); + return true; + } + if (origin != 'mapping') { + logKey(macroModeState, key); + } + } + } + function handleEsc() { + if (key == '') { + // Clear input state and get back to normal mode. clearInputState(cm); - return; + if (vim.visualMode) { + exitVisualMode(cm); + } else if (vim.insertMode) { + exitInsertMode(cm); + } + return true; } } - if (key == '') { - // Clear input state and get back to normal mode. - clearInputState(cm); - if (vim.visualMode) { - exitVisualMode(cm); + function doKeyToKey(keys) { + // TODO: prevent infinite recursion. + var match; + while (keys) { + // Pull off one command key, which is either a single character + // or a special sequence wrapped in '<' and '>', e.g. ''. + match = (/<\w+-.+?>|<\w+>|./).exec(keys); + key = match[0]; + keys = keys.substring(match.index + key.length); + CodeMirror.Vim.handleKey(cm, key, 'mapping'); } - return; } - // Enter visual mode when the mouse selects text. - if (!vim.visualMode && - !cursorEqual(cm.getCursor('head'), cm.getCursor('anchor'))) { - vim.visualMode = true; - vim.visualLine = false; - CodeMirror.signal(cm, "vim-mode-change", {mode: "visual"}); - cm.on('mousedown', exitVisualMode); - } - if (key != '0' || (key == '0' && vim.inputState.getRepeat() === 0)) { - // Have to special case 0 since it's both a motion and a number. - command = commandDispatcher.matchCommand(key, defaultKeymap, vim); - } - if (!command) { - if (isNumber(key)) { - // Increment count unless count is 0 and key is 0. - vim.inputState.pushRepeatDigit(key); + + function handleKeyInsertMode() { + if (handleEsc()) { return true; } + var keys = vim.inputState.keyBuffer = vim.inputState.keyBuffer + key; + var keysAreChars = key.length == 1; + var match = commandDispatcher.matchCommand(keys, defaultKeymap, vim.inputState, 'insert'); + // Need to check all key substrings in insert mode. + while (keys.length > 1 && match.type != 'full') { + var keys = vim.inputState.keyBuffer = keys.slice(1); + var thisMatch = commandDispatcher.matchCommand(keys, defaultKeymap, vim.inputState, 'insert'); + if (thisMatch.type != 'none') { match = thisMatch; } } - if (macroModeState.isRecording) { - logKey(macroModeState, key); + if (match.type == 'none') { clearInputState(cm); return false; } + else if (match.type == 'partial') { + if (lastInsertModeKeyTimer) { window.clearTimeout(lastInsertModeKeyTimer); } + lastInsertModeKeyTimer = window.setTimeout( + function() { if (vim.insertMode && vim.inputState.keyBuffer) { clearInputState(cm); } }, + getOption('insertModeEscKeysTimeout')); + return !keysAreChars; } - return; + + if (lastInsertModeKeyTimer) { window.clearTimeout(lastInsertModeKeyTimer); } + if (keysAreChars) { + var here = cm.getCursor(); + cm.replaceRange('', offsetCursor(here, 0, -(keys.length - 1)), here, '+input'); + } + clearInputState(cm); + var command = match.command; + if (command.type == 'keyToKey') { + doKeyToKey(command.toKeys); + } else { + commandDispatcher.processCommand(cm, vim, command); + } + return true; } - if (command.type == 'keyToKey') { - // TODO: prevent infinite recursion. - for (var i = 0; i < command.toKeys.length; i++) { - this.handleKey(cm, command.toKeys[i]); + + function handleKeyNonInsertMode() { + if (handleMacroRecording() || handleEsc()) { return true; }; + + var keys = vim.inputState.keyBuffer = vim.inputState.keyBuffer + key; + if (/^[1-9]\d*$/.test(keys)) { return true; } + + var keysMatcher = /^(\d*)(.*)$/.exec(keys); + if (!keysMatcher) { clearInputState(cm); return false; } + var context = vim.visualMode ? 'visual' : + 'normal'; + var match = commandDispatcher.matchCommand(keysMatcher[2] || keysMatcher[1], defaultKeymap, vim.inputState, context); + if (match.type == 'none') { clearInputState(cm); return false; } + else if (match.type == 'partial') { return true; } + + vim.inputState.keyBuffer = ''; + var command = match.command; + var keysMatcher = /^(\d*)(.*)$/.exec(keys); + if (keysMatcher[1] && keysMatcher[1] != '0') { + vim.inputState.pushRepeatDigit(keysMatcher[1]); } - } else { - if (macroModeState.isRecording) { - logKey(macroModeState, key); + if (command.type == 'keyToKey') { + doKeyToKey(command.toKeys); + } else { + commandDispatcher.processCommand(cm, vim, command); } - commandDispatcher.processCommand(cm, vim, command); + return true; } + + return cm.operation(function() { + cm.curOp.isVimOp = true; + try { + if (vim.insertMode) { return handleKeyInsertMode(); } + else { return handleKeyNonInsertMode(); } + } catch (e) { + // clear VIM state in case it's in a bad state. + cm.state.vim = undefined; + maybeInitVimState(cm); + throw e; + } + }); }, handleEx: function(cm, input) { exCommandDispatcher.processCommand(cm, input); @@ -953,83 +962,25 @@ } }; var commandDispatcher = { - matchCommand: function(key, keyMap, vim) { - var inputState = vim.inputState; - var keys = inputState.keyBuffer.concat(key); - var matchedCommands = []; - var selectedCharacter; - for (var i = 0; i < keyMap.length; i++) { - var command = keyMap[i]; - if (matchKeysPartial(keys, command.keys)) { - if (inputState.operator && command.type == 'action') { - // Ignore matched action commands after an operator. Operators - // only operate on motions. This check is really for text - // objects since aW, a[ etcs conflicts with a. - continue; - } - // Match commands that take as an argument. - if (command.keys[keys.length - 1] == 'character') { - selectedCharacter = keys[keys.length - 1]; - if (selectedCharacter.length>1){ - switch(selectedCharacter){ - case '': - selectedCharacter='\n'; - break; - case '': - selectedCharacter=' '; - break; - default: - continue; - } - } - } - // Add the command to the list of matched commands. Choose the best - // command later. - matchedCommands.push(command); - } + matchCommand: function(keys, keyMap, inputState, context) { + var matches = commandMatches(keys, keyMap, context, inputState); + if (!matches.full && !matches.partial) { + return {type: 'none'}; + } else if (!matches.full && matches.partial) { + return {type: 'partial'}; } - // Returns the command if it is a full match, or null if not. - function getFullyMatchedCommandOrNull(command) { - if (keys.length < command.keys.length) { - // Matches part of a multi-key command. Buffer and wait for next - // stroke. - inputState.keyBuffer.push(key); - return null; - } else { - if (command.keys[keys.length - 1] == 'character') { - inputState.selectedCharacter = selectedCharacter; - } - // Clear the buffer since a full match was found. - inputState.keyBuffer = []; - return command; + var bestMatch; + for (var i = 0; i < matches.full.length; i++) { + var match = matches.full[i]; + if (!bestMatch) { + bestMatch = match; } } - - if (!matchedCommands.length) { - // Clear the buffer since there were no matches. - inputState.keyBuffer = []; - return null; - } else if (matchedCommands.length == 1) { - return getFullyMatchedCommandOrNull(matchedCommands[0]); - } else { - // Find the best match in the list of matchedCommands. - var context = vim.visualMode ? 'visual' : 'normal'; - var bestMatch; // Default to first in the list. - for (var i = 0; i < matchedCommands.length; i++) { - var current = matchedCommands[i]; - if (current.context == context) { - bestMatch = current; - break; - } else if (!bestMatch && !current.context) { - // Only set an imperfect match to best match if no best match is - // set and the imperfect match is not restricted to another - // context. - bestMatch = current; - } - } - return getFullyMatchedCommandOrNull(bestMatch); + if (bestMatch.keys.slice(-11) == '') { + inputState.selectedCharacter = lastChar(keys); } + return {type: 'full', command: bestMatch}; }, processCommand: function(cm, vim, command) { vim.inputState.repeatOverride = command.repeatOverride; @@ -1048,10 +999,12 @@ break; case 'search': this.processSearch(cm, vim, command); + clearInputState(cm); break; case 'ex': case 'keyToEx': this.processEx(cm, vim, command); + clearInputState(cm); break; default: break; @@ -1293,13 +1246,13 @@ var operator = inputState.operator; var operatorArgs = inputState.operatorArgs || {}; var registerName = inputState.registerName; - var selectionEnd = copyCursor(cm.getCursor('head')); - var selectionStart = copyCursor(cm.getCursor('anchor')); - // The difference between cur and selection cursors are that cur is - // being operated on and ignores that there is a selection. - var curStart = copyCursor(selectionEnd); - var curOriginal = copyCursor(curStart); - var curEnd; + var sel = vim.sel; + // TODO: Make sure cm and vim selections are identical outside visual mode. + var origHead = copyCursor(vim.visualMode ? sel.head: cm.getCursor('head')); + var origAnchor = copyCursor(vim.visualMode ? sel.anchor : cm.getCursor('anchor')); + var oldHead = copyCursor(origHead); + var oldAnchor = copyCursor(origAnchor); + var newHead, newAnchor; var repeat; if (operator) { this.recordLastEdit(vim, inputState); @@ -1326,7 +1279,7 @@ motionArgs.repeat = repeat; clearInputState(cm); if (motion) { - var motionResult = motions[motion](cm, motionArgs, vim); + var motionResult = motions[motion](cm, origHead, motionArgs, vim); vim.lastMotion = motions[motion]; if (!motionResult) { return; @@ -1339,159 +1292,139 @@ recordJumpPosition(cm, cachedCursor, motionResult); delete jumpList.cachedCursor; } else { - recordJumpPosition(cm, curOriginal, motionResult); + recordJumpPosition(cm, origHead, motionResult); } } if (motionResult instanceof Array) { - curStart = motionResult[0]; - curEnd = motionResult[1]; + newAnchor = motionResult[0]; + newHead = motionResult[1]; } else { - curEnd = motionResult; + newHead = motionResult; } // TODO: Handle null returns from motion commands better. - if (!curEnd) { - curEnd = Pos(curStart.line, curStart.ch); + if (!newHead) { + newHead = copyCursor(origHead); } if (vim.visualMode) { - // Check if the selection crossed over itself. Will need to shift - // the start point if that happened. - // offset is set to -1 or 1 to shift the curEnd - // left or right - var offset = 0; - if (cursorIsBefore(selectionStart, selectionEnd) && - (cursorEqual(selectionStart, curEnd) || - cursorIsBefore(curEnd, selectionStart))) { - // The end of the selection has moved from after the start to - // before the start. We will shift the start right by 1. - selectionStart.ch += 1; - offset = -1; - } else if (cursorIsBefore(selectionEnd, selectionStart) && - (cursorEqual(selectionStart, curEnd) || - cursorIsBefore(selectionStart, curEnd))) { - // The opposite happened. We will shift the start left by 1. - selectionStart.ch -= 1; - offset = 1; - } - // in case of visual Block selectionStart and curEnd - // may not be on the same line, - // Also, In case of v_o this should not happen. - if (!vim.visualBlock && !(motionResult instanceof Array)) { - curEnd.ch += offset; - } - if (vim.lastHPos != Infinity) { - vim.lastHPos = curEnd.ch; - } - selectionEnd = curEnd; - selectionStart = (motionResult instanceof Array) ? curStart : selectionStart; - if (vim.visualLine) { - if (cursorIsBefore(selectionStart, selectionEnd)) { - selectionStart.ch = 0; - - var lastLine = cm.lastLine(); - if (selectionEnd.line > lastLine) { - selectionEnd.line = lastLine; - } - selectionEnd.ch = lineLength(cm, selectionEnd.line); - } else { - selectionEnd.ch = 0; - selectionStart.ch = lineLength(cm, selectionStart.line); - } - } else if (vim.visualBlock) { - // Select a block and - // return the diagonally opposite end. - selectionStart = selectBlock(cm, selectionEnd); - } - if (!vim.visualBlock) { - cm.setSelection(selectionStart, selectionEnd); + newHead = clipCursorToContent(cm, newHead, vim.visualBlock); + if (newAnchor) { + newAnchor = clipCursorToContent(cm, newAnchor, true); } + newAnchor = newAnchor || oldAnchor; + sel.anchor = newAnchor; + sel.head = newHead; + updateCmSelection(cm); updateMark(cm, vim, '<', - cursorIsBefore(selectionStart, selectionEnd) ? selectionStart - : selectionEnd); + cursorIsBefore(newAnchor, newHead) ? newAnchor + : newHead); updateMark(cm, vim, '>', - cursorIsBefore(selectionStart, selectionEnd) ? selectionEnd - : selectionStart); + cursorIsBefore(newAnchor, newHead) ? newHead + : newAnchor); } else if (!operator) { - curEnd = clipCursorToContent(cm, curEnd); - cm.setCursor(curEnd.line, curEnd.ch); + newHead = clipCursorToContent(cm, newHead); + cm.setCursor(newHead.line, newHead.ch); } } - if (operator) { - var inverted = false; - vim.lastMotion = null; - var lastSelection = vim.lastSelection; - operatorArgs.repeat = repeat; // Indent in visual mode needs this. - if (vim.visualMode) { - curStart = selectionStart; - curEnd = selectionEnd; - motionArgs.inclusive = true; - operatorArgs.shouldMoveCursor = false; - } - // Swap start and end if motion was backward. - if (curEnd && cursorIsBefore(curEnd, curStart)) { - var tmp = curStart; - curStart = curEnd; - curEnd = tmp; - inverted = true; - } else if (!curEnd) { - curEnd = copyCursor(curStart); - } - if (motionArgs.inclusive && !vim.visualMode) { - // Move the selection end one to the right to include the last - // character. - curEnd.ch++; - } - if (operatorArgs.selOffset) { + if (operatorArgs.lastSel) { // Replaying a visual mode operation - curEnd.line = curStart.line + operatorArgs.selOffset.line; - if (operatorArgs.selOffset.line) {curEnd.ch = operatorArgs.selOffset.ch; } - else { curEnd.ch = curStart.ch + operatorArgs.selOffset.ch; } - // In case of blockwise visual - if (lastSelection && lastSelection.visualBlock) { - var block = lastSelection.visualBlock; - var width = block.width; - var height = block.height; - curEnd = Pos(curStart.line + height, curStart.ch + width); - // selectBlock creates a 'proper' rectangular block. - // We do not want that in all cases, so we manually set selections. - var selections = []; - for (var i = curStart.line; i < curEnd.line; i++) { - var anchor = Pos(i, curStart.ch); - var head = Pos(i, curEnd.ch); - var range = {anchor: anchor, head: head}; - selections.push(range); - } - cm.setSelections(selections); - var blockSelected = true; + newAnchor = oldAnchor; + var lastSel = operatorArgs.lastSel; + var lineOffset = Math.abs(lastSel.head.line - lastSel.anchor.line); + var chOffset = Math.abs(lastSel.head.ch - lastSel.anchor.ch); + if (lastSel.visualLine) { + // Linewise Visual mode: The same number of lines. + newHead = Pos(oldAnchor.line + lineOffset, oldAnchor.ch); + } else if (lastSel.visualBlock) { + // Blockwise Visual mode: The same number of lines and columns. + newHead = Pos(oldAnchor.line + lineOffset, oldAnchor.ch + chOffset); + } else if (lastSel.head.line == lastSel.anchor.line) { + // Normal Visual mode within one line: The same number of characters. + newHead = Pos(oldAnchor.line, oldAnchor.ch + chOffset); + } else { + // Normal Visual mode with several lines: The same number of lines, in the + // last line the same number of characters as in the last line the last time. + newHead = Pos(oldAnchor.line + lineOffset, oldAnchor.ch); } + vim.visualMode = true; + vim.visualLine = lastSel.visualLine; + vim.visualBlock = lastSel.visualBlock; + sel = vim.sel = { + anchor: newAnchor, + head: newHead + }; + updateCmSelection(cm); } else if (vim.visualMode) { - var selOffset = Pos(); - selOffset.line = curEnd.line - curStart.line; - if (selOffset.line) { selOffset.ch = curEnd.ch; } - else { selOffset.ch = curEnd.ch - curStart.ch; } - operatorArgs.selOffset = selOffset; + operatorArgs.lastSel = { + anchor: copyCursor(sel.anchor), + head: copyCursor(sel.head), + visualBlock: vim.visualBlock, + visualLine: vim.visualLine + }; } - var linewise = motionArgs.linewise || - (vim.visualMode && vim.visualLine) || - operatorArgs.linewise; - if (linewise) { - // Expand selection to entire line. - expandSelectionToLine(cm, curStart, curEnd); - } else if (motionArgs.forward) { - // Clip to trailing newlines only if the motion goes forward. - clipToLine(cm, curStart, curEnd); + var curStart, curEnd, linewise, mode; + var cmSel; + if (vim.visualMode) { + // Init visual op + curStart = cursorMin(sel.head, sel.anchor); + curEnd = cursorMax(sel.head, sel.anchor); + linewise = vim.visualLine || operatorArgs.linewise; + mode = vim.visualBlock ? 'block' : + linewise ? 'line' : + 'char'; + cmSel = makeCmSelection(cm, { + anchor: curStart, + head: curEnd + }, mode); + if (linewise) { + var ranges = cmSel.ranges; + if (mode == 'block') { + // Linewise operators in visual block mode extend to end of line + for (var i = 0; i < ranges.length; i++) { + ranges[i].head.ch = lineLength(cm, ranges[i].head.line); + } + } else if (mode == 'line') { + ranges[0].head = Pos(ranges[0].head.line + 1, 0); + } + } + } else { + // Init motion op + curStart = copyCursor(newAnchor || oldAnchor); + curEnd = copyCursor(newHead || oldHead); + if (cursorIsBefore(curEnd, curStart)) { + var tmp = curStart; + curStart = curEnd; + curEnd = tmp; + } + linewise = motionArgs.linewise || operatorArgs.linewise; + if (linewise) { + // Expand selection to entire line. + expandSelectionToLine(cm, curStart, curEnd); + } else if (motionArgs.forward) { + // Clip to trailing newlines only if the motion goes forward. + clipToLine(cm, curStart, curEnd); + } + mode = 'char'; + var exclusive = !motionArgs.inclusive || linewise; + cmSel = makeCmSelection(cm, { + anchor: curStart, + head: curEnd + }, mode, exclusive); } + cm.setSelections(cmSel.ranges, cmSel.primary); + vim.lastMotion = null; + operatorArgs.repeat = repeat; // For indent in visual mode. operatorArgs.registerName = registerName; // Keep track of linewise as it affects how paste and change behave. operatorArgs.linewise = linewise; - if (!vim.visualBlock && !blockSelected) { - cm.setSelection(curStart, curEnd); - } - operators[operator](cm, operatorArgs, vim, curStart, - curEnd, curOriginal); + var operatorMoveTo = operators[operator]( + cm, operatorArgs, cmSel.ranges, oldAnchor, newHead); if (vim.visualMode) { exitVisualMode(cm); } + if (operatorMoveTo) { + cm.setCursor(operatorMoveTo); + } } }, recordLastEdit: function(vim, inputState, actionCommand) { @@ -1510,7 +1443,7 @@ */ // All of the functions below return Cursor objects. var motions = { - moveToTopLine: function(cm, motionArgs) { + moveToTopLine: function(cm, _head, motionArgs) { var line = getUserVisibleLines(cm).top + motionArgs.repeat -1; return Pos(line, findFirstNonWhiteSpaceCharacter(cm.getLine(line))); }, @@ -1519,17 +1452,17 @@ var line = Math.floor((range.top + range.bottom) * 0.5); return Pos(line, findFirstNonWhiteSpaceCharacter(cm.getLine(line))); }, - moveToBottomLine: function(cm, motionArgs) { + moveToBottomLine: function(cm, _head, motionArgs) { var line = getUserVisibleLines(cm).bottom - motionArgs.repeat +1; return Pos(line, findFirstNonWhiteSpaceCharacter(cm.getLine(line))); }, - expandToLine: function(cm, motionArgs) { + expandToLine: function(_cm, head, motionArgs) { // Expands forward to end of line, and then to next line if repeat is // >1. Does not handle backward motion! - var cur = cm.getCursor(); + var cur = head; return Pos(cur.line + motionArgs.repeat - 1, Infinity); }, - findNext: function(cm, motionArgs) { + findNext: function(cm, _head, motionArgs) { var state = getSearchState(cm); var query = state.getQuery(); if (!query) { @@ -1541,7 +1474,7 @@ highlightSearchMatches(cm, query); return findNext(cm, prev/** prev */, query, motionArgs.repeat); }, - goToMark: function(cm, motionArgs, vim) { + goToMark: function(cm, _head, motionArgs, vim) { var mark = vim.marks[motionArgs.selectedCharacter]; if (mark) { var pos = mark.find(); @@ -1549,22 +1482,19 @@ } return null; }, - moveToOtherHighlightedEnd: function(cm, motionArgs, vim) { - var ranges = cm.listSelections(); - var curEnd = cm.getCursor('head'); - var curStart = ranges[0].anchor; - var curIndex = cursorEqual(ranges[0].head, curEnd) ? ranges.length-1 : 0; - if (motionArgs.sameLine && vim.visualBlock) { - curStart = Pos(curEnd.line, ranges[curIndex].anchor.ch); - curEnd = Pos(ranges[curIndex].head.line, curEnd.ch); + moveToOtherHighlightedEnd: function(cm, _head, motionArgs, vim) { + if (vim.visualBlock && motionArgs.sameLine) { + var sel = vim.sel; + return [ + clipCursorToContent(cm, Pos(sel.anchor.line, sel.head.ch)), + clipCursorToContent(cm, Pos(sel.head.line, sel.anchor.ch)) + ]; } else { - curStart = ranges[curIndex].anchor; + return ([vim.sel.head, vim.sel.anchor]); } - cm.setCursor(curEnd); - return ([curEnd, curStart]); }, - jumpToMark: function(cm, motionArgs, vim) { - var best = cm.getCursor(); + jumpToMark: function(cm, head, motionArgs, vim) { + var best = head; for (var i = 0; i < motionArgs.repeat; i++) { var cursor = best; for (var key in vim.marks) { @@ -1584,8 +1514,8 @@ var equal = cursorEqual(cursor, best); var between = (motionArgs.forward) ? - cusrorIsBetween(cursor, mark, best) : - cusrorIsBetween(best, mark, cursor); + cursorIsBetween(cursor, mark, best) : + cursorIsBetween(best, mark, cursor); if (equal || between) { best = mark; @@ -1601,14 +1531,14 @@ } return best; }, - moveByCharacters: function(cm, motionArgs) { - var cur = cm.getCursor(); + moveByCharacters: function(_cm, head, motionArgs) { + var cur = head; var repeat = motionArgs.repeat; var ch = motionArgs.forward ? cur.ch + repeat : cur.ch - repeat; return Pos(cur.line, ch); }, - moveByLines: function(cm, motionArgs, vim) { - var cur = cm.getCursor(); + moveByLines: function(cm, head, motionArgs, vim) { + var cur = head; var endCh = cur.ch; // Depending what our last motion was, we may want to do different // things. If our last motion was moving vertically, we want to @@ -1643,8 +1573,8 @@ vim.lastHSPos = cm.charCoords(Pos(line, endCh),'div').left; return Pos(line, endCh); }, - moveByDisplayLines: function(cm, motionArgs, vim) { - var cur = cm.getCursor(); + moveByDisplayLines: function(cm, head, motionArgs, vim) { + var cur = head; switch (vim.lastMotion) { case this.moveByDisplayLines: case this.moveByScroll: @@ -1671,16 +1601,16 @@ vim.lastHPos = res.ch; return res; }, - moveByPage: function(cm, motionArgs) { + moveByPage: function(cm, head, motionArgs) { // CodeMirror only exposes functions that move the cursor page down, so // doing this bad hack to move the cursor and move it back. evalInput // will move the cursor to where it should be in the end. - var curStart = cm.getCursor(); + var curStart = head; var repeat = motionArgs.repeat; return cm.findPosV(curStart, (motionArgs.forward ? repeat : -repeat), 'page'); }, - moveByParagraph: function(cm, motionArgs) { - var line = cm.getCursor().line; + moveByParagraph: function(cm, head, motionArgs) { + var line = head.line; var repeat = motionArgs.repeat; var inc = motionArgs.forward ? 1 : -1; for (var i = 0; i < repeat; i++) { @@ -1695,16 +1625,16 @@ } return Pos(line, 0); }, - moveByScroll: function(cm, motionArgs, vim) { + moveByScroll: function(cm, head, motionArgs, vim) { var scrollbox = cm.getScrollInfo(); var curEnd = null; var repeat = motionArgs.repeat; if (!repeat) { repeat = scrollbox.clientHeight / (2 * cm.defaultTextHeight()); } - var orig = cm.charCoords(cm.getCursor(), 'local'); + var orig = cm.charCoords(head, 'local'); motionArgs.repeat = repeat; - var curEnd = motions.moveByDisplayLines(cm, motionArgs, vim); + var curEnd = motions.moveByDisplayLines(cm, head, motionArgs, vim); if (!curEnd) { return null; } @@ -1712,11 +1642,11 @@ cm.scrollTo(null, scrollbox.top + dest.top - orig.top); return curEnd; }, - moveByWords: function(cm, motionArgs) { - return moveToWord(cm, motionArgs.repeat, !!motionArgs.forward, + moveByWords: function(cm, head, motionArgs) { + return moveToWord(cm, head, motionArgs.repeat, !!motionArgs.forward, !!motionArgs.wordEnd, !!motionArgs.bigWord); }, - moveTillCharacter: function(cm, motionArgs) { + moveTillCharacter: function(cm, _head, motionArgs) { var repeat = motionArgs.repeat; var curEnd = moveToCharacter(cm, repeat, motionArgs.forward, motionArgs.selectedCharacter); @@ -1726,26 +1656,26 @@ curEnd.ch += increment; return curEnd; }, - moveToCharacter: function(cm, motionArgs) { + moveToCharacter: function(cm, head, motionArgs) { var repeat = motionArgs.repeat; recordLastCharacterSearch(0, motionArgs); return moveToCharacter(cm, repeat, motionArgs.forward, - motionArgs.selectedCharacter) || cm.getCursor(); + motionArgs.selectedCharacter) || head; }, - moveToSymbol: function(cm, motionArgs) { + moveToSymbol: function(cm, head, motionArgs) { var repeat = motionArgs.repeat; return findSymbol(cm, repeat, motionArgs.forward, - motionArgs.selectedCharacter) || cm.getCursor(); + motionArgs.selectedCharacter) || head; }, - moveToColumn: function(cm, motionArgs, vim) { + moveToColumn: function(cm, head, motionArgs, vim) { var repeat = motionArgs.repeat; // repeat is equivalent to which column we want to move to! vim.lastHPos = repeat - 1; - vim.lastHSPos = cm.charCoords(cm.getCursor(),'div').left; + vim.lastHSPos = cm.charCoords(head,'div').left; return moveToColumn(cm, repeat); }, - moveToEol: function(cm, motionArgs, vim) { - var cur = cm.getCursor(); + moveToEol: function(cm, head, motionArgs, vim) { + var cur = head; vim.lastHPos = Infinity; var retval= Pos(cur.line + motionArgs.repeat - 1, Infinity); var end=cm.clipPos(retval); @@ -1753,15 +1683,15 @@ vim.lastHSPos = cm.charCoords(end,'div').left; return retval; }, - moveToFirstNonWhiteSpaceCharacter: function(cm) { + moveToFirstNonWhiteSpaceCharacter: function(cm, head) { // Go to the start of the line where the text begins, or the end for // whitespace-only lines - var cursor = cm.getCursor(); + var cursor = head; return Pos(cursor.line, findFirstNonWhiteSpaceCharacter(cm.getLine(cursor.line))); }, - moveToMatchedSymbol: function(cm) { - var cursor = cm.getCursor(); + moveToMatchedSymbol: function(cm, head) { + var cursor = head; var line = cursor.line; var ch = cursor.ch; var lineText = cm.getLine(line); @@ -1782,11 +1712,10 @@ return cursor; } }, - moveToStartOfLine: function(cm) { - var cursor = cm.getCursor(); - return Pos(cursor.line, 0); + moveToStartOfLine: function(_cm, head) { + return Pos(head.line, 0); }, - moveToLineOrEdgeOfDocument: function(cm, motionArgs) { + moveToLineOrEdgeOfDocument: function(cm, _head, motionArgs) { var lineNum = motionArgs.forward ? cm.lastLine() : cm.firstLine(); if (motionArgs.repeatIsExplicit) { lineNum = motionArgs.repeat - cm.getOption('firstLineNumber'); @@ -1794,7 +1723,7 @@ return Pos(lineNum, findFirstNonWhiteSpaceCharacter(cm.getLine(lineNum))); }, - textObjectManipulation: function(cm, motionArgs) { + textObjectManipulation: function(cm, head, motionArgs) { // TODO: lots of possible exceptions that can be thrown here. Try da( // outside of a () block. @@ -1823,9 +1752,9 @@ var tmp; if (mirroredPairs[character]) { - tmp = selectCompanionObject(cm, character, inclusive); + tmp = selectCompanionObject(cm, head, character, inclusive); } else if (selfPaired[character]) { - tmp = findBeginningAndEnd(cm, character, inclusive); + tmp = findBeginningAndEnd(cm, head, character, inclusive); } else if (character === 'W') { tmp = expandWordUnderCursor(cm, inclusive, true /** forward */, true /** bigWord */); @@ -1837,10 +1766,14 @@ return null; } - return [tmp.start, tmp.end]; + if (!cm.state.vim.visualMode) { + return [tmp.start, tmp.end]; + } else { + return expandSelection(cm, tmp.start, tmp.end); + } }, - repeatLastCharacterSearch: function(cm, motionArgs) { + repeatLastCharacterSearch: function(cm, head, motionArgs) { var lastSearch = vimGlobalState.lastChararacterSearch; var repeat = motionArgs.repeat; var forward = motionArgs.forward === lastSearch.forward; @@ -1850,133 +1783,107 @@ var curEnd = moveToCharacter(cm, repeat, forward, lastSearch.selectedCharacter); if (!curEnd) { cm.moveH(increment, 'char'); - return cm.getCursor(); + return head; } curEnd.ch += increment; return curEnd; } }; + function fillArray(val, times) { + var arr = []; + for (var i = 0; i < times; i++) { + arr.push(val); + } + return arr; + } + /** + * An operator acts on a text selection. It receives the list of selections + * as input. The corresponding CodeMirror selection is guaranteed to + * match the input selection. + */ var operators = { - change: function(cm, operatorArgs, vim) { - var selections = cm.listSelections(); - var start = selections[0], end = selections[selections.length-1]; - var curStart = cursorIsBefore(start.anchor, start.head) ? start.anchor : start.head; - var curEnd = cursorIsBefore(end.anchor, end.head) ? end.head : end.anchor; - var text = cm.getSelection(); - var visualBlock = vim.visualBlock; - if (vim.lastSelection && !vim.visualMode) { - visualBlock = vim.lastSelection.visualBlock ? true : visualBlock; - } - var lastInsertModeChanges = vimGlobalState.macroModeState.lastInsertModeChanges; - lastInsertModeChanges.inVisualBlock = visualBlock; - var replacement = new Array(selections.length).join('1').split('1'); - // save the selectionEnd mark - var selectionEnd = vim.marks['>'] ? vim.marks['>'].find() : cm.getCursor('head'); - vimGlobalState.registerController.pushText( - operatorArgs.registerName, 'change', text, - operatorArgs.linewise); - if (operatorArgs.linewise) { - // 'C' in visual block extends the block till eol for all lines - if (visualBlock){ - var startLine = curStart.line; - while (startLine <= curEnd.line) { - var endCh = lineLength(cm, startLine); - var head = Pos(startLine, endCh); - var anchor = Pos(startLine, curStart.ch); - startLine++; - cm.replaceRange('', anchor, head); - } - } else { - // Push the next line back down, if there is a next line. - replacement = '\n'; - if (curEnd.line == curStart.line && curEnd.line == cm.lastLine()) { - replacement = ''; - } - cm.replaceRange(replacement, curStart, curEnd); - cm.indentLine(curStart.line, 'smart'); - // null ch so setCursor moves to end of line. - curStart.ch = null; - cm.setCursor(curStart); - } - } else { - // Exclude trailing whitespace if the range is not all whitespace. - var text = cm.getRange(curStart, curEnd); + change: function(cm, args, ranges) { + var finalHead, text; + var vim = cm.state.vim; + vimGlobalState.macroModeState.lastInsertModeChanges.inVisualBlock = vim.visualBlock; + if (!vim.visualMode) { + var anchor = ranges[0].anchor, + head = ranges[0].head; + text = cm.getRange(anchor, head); if (!isWhiteSpaceString(text)) { + // Exclude trailing whitespace if the range is not all whitespace. var match = (/\s+$/).exec(text); if (match) { - curEnd = offsetCursor(curEnd, 0, - match[0].length); + head = offsetCursor(head, 0, - match[0].length); + text = text.slice(0, - match[0].length); } } - if (visualBlock) { - cm.replaceSelections(replacement); - } else { - cm.setCursor(curStart); - cm.replaceRange('', curStart, curEnd); + var wasLastLine = head.line - 1 == cm.lastLine(); + cm.replaceRange('', anchor, head); + if (args.linewise && !wasLastLine) { + // Push the next line back down, if there is a next line. + CodeMirror.commands.newlineAndIndent(cm); + // null ch so setCursor moves to end of line. + anchor.ch = null; } - } - vim.marks['>'] = cm.setBookmark(selectionEnd); - actions.enterInsertMode(cm, {}, cm.state.vim); - }, - // delete is a javascript keyword. - 'delete': function(cm, operatorArgs, vim) { - var selections = cm.listSelections(); - var start = selections[0], end = selections[selections.length-1]; - var curStart = cursorIsBefore(start.anchor, start.head) ? start.anchor : start.head; - var curEnd = cursorIsBefore(end.anchor, end.head) ? end.head : end.anchor; - // Save the '>' mark before cm.replaceRange clears it. - var selectionEnd, selectionStart; - var blockwise = vim.visualBlock; - if (vim.visualMode) { - selectionEnd = vim.marks['>'].find(); - selectionStart = vim.marks['<'].find(); - } else if (vim.lastSelection) { - selectionEnd = vim.lastSelection.curStartMark.find(); - selectionStart = vim.lastSelection.curEndMark.find(); - blockwise = vim.lastSelection.visualBlock; - } - var text = cm.getSelection(); - vimGlobalState.registerController.pushText( - operatorArgs.registerName, 'delete', text, - operatorArgs.linewise, blockwise); - var replacement = new Array(selections.length).join('1').split('1'); - // If the ending line is past the last line, inclusive, instead of - // including the trailing \n, include the \n before the starting line - if (operatorArgs.linewise && - curEnd.line == cm.lastLine() && curStart.line == curEnd.line) { - var tmp = copyCursor(curEnd); - curStart.line--; - curStart.ch = lineLength(cm, curStart.line); - curEnd = tmp; - cm.replaceRange('', curStart, curEnd); + finalHead = anchor; } else { + text = cm.getSelection(); + var replacement = fillArray('', ranges.length); cm.replaceSelections(replacement); + finalHead = cursorMin(ranges[0].head, ranges[0].anchor); } - // restore the saved bookmark - if (selectionEnd) { - var curStartMark = cm.setBookmark(selectionStart); - var curEndMark = cm.setBookmark(selectionEnd); - if (vim.visualMode) { - vim.marks['<'] = curStartMark; - vim.marks['>'] = curEndMark; - } else { - vim.lastSelection.curStartMark = curStartMark; - vim.lastSelection.curEndMark = curEndMark; + vimGlobalState.registerController.pushText( + args.registerName, 'change', text, + args.linewise, ranges.length > 1); + actions.enterInsertMode(cm, {head: finalHead}, cm.state.vim); + }, + // delete is a javascript keyword. + 'delete': function(cm, args, ranges) { + var finalHead, text; + var vim = cm.state.vim; + if (!vim.visualBlock) { + var anchor = ranges[0].anchor, + head = ranges[0].head; + if (args.linewise && + head.line != cm.firstLine() && + anchor.line == cm.lastLine() && + anchor.line == head.line - 1) { + // Special case for dd on last line (and first line). + if (anchor.line == cm.firstLine()) { + anchor.ch = 0; + } else { + anchor = Pos(anchor.line - 1, lineLength(cm, anchor.line - 1)); + } + } + text = cm.getRange(anchor, head); + cm.replaceRange('', anchor, head); + finalHead = anchor; + if (args.linewise) { + finalHead = motions.moveToFirstNonWhiteSpaceCharacter(cm, anchor); } - } - if (operatorArgs.linewise) { - cm.setCursor(motions.moveToFirstNonWhiteSpaceCharacter(cm)); } else { - cm.setCursor(curStart); + text = cm.getSelection(); + var replacement = fillArray('', ranges.length); + cm.replaceSelections(replacement); + finalHead = ranges[0].anchor; } + vimGlobalState.registerController.pushText( + args.registerName, 'delete', text, + args.linewise, vim.visualBlock); + return finalHead; }, - indent: function(cm, operatorArgs, vim, curStart, curEnd) { - var startLine = curStart.line; - var endLine = curEnd.line; + indent: function(cm, args, ranges) { + var vim = cm.state.vim; + var startLine = ranges[0].anchor.line; + var endLine = vim.visualBlock ? + ranges[ranges.length - 1].anchor.line : + ranges[0].head.line; // In visual mode, n> shifts the selection right n times, instead of // shifting n lines right once. - var repeat = (vim.visualMode) ? operatorArgs.repeat : 1; - if (operatorArgs.linewise) { + var repeat = (vim.visualMode) ? args.repeat : 1; + if (args.linewise) { // The only way to delete a newline is to delete until the start of // the next line, so in linewise mode evalInput will include the next // line. We don't want this in indent, so we go back a line. @@ -1984,39 +1891,52 @@ } for (var i = startLine; i <= endLine; i++) { for (var j = 0; j < repeat; j++) { - cm.indentLine(i, operatorArgs.indentRight); + cm.indentLine(i, args.indentRight); } } - cm.setCursor(curStart); - cm.setCursor(motions.moveToFirstNonWhiteSpaceCharacter(cm)); + return motions.moveToFirstNonWhiteSpaceCharacter(cm, ranges[0].anchor); }, - swapcase: function(cm, operatorArgs, _vim, _curStart, _curEnd, _curOriginal) { + changeCase: function(cm, args, ranges, oldAnchor, newHead) { var selections = cm.getSelections(); - var ranges = cm.listSelections(); var swapped = []; + var toLower = args.toLower; for (var j = 0; j < selections.length; j++) { var toSwap = selections[j]; var text = ''; - for (var i = 0; i < toSwap.length; i++) { - var character = toSwap.charAt(i); - text += isUpperCase(character) ? character.toLowerCase() : - character.toUpperCase(); + if (toLower === true) { + text = toSwap.toLowerCase(); + } else if (toLower === false) { + text = toSwap.toUpperCase(); + } else { + for (var i = 0; i < toSwap.length; i++) { + var character = toSwap.charAt(i); + text += isUpperCase(character) ? character.toLowerCase() : + character.toUpperCase(); + } } swapped.push(text); } cm.replaceSelections(swapped); - var curStart = ranges[0].anchor; - var curEnd = ranges[0].head; - if (!operatorArgs.shouldMoveCursor) { - cm.setCursor(cursorIsBefore(curStart, curEnd) ? curStart : curEnd); + if (args.shouldMoveCursor){ + return newHead; + } else if (!cm.state.vim.visualMode && args.linewise && ranges[0].anchor.line + 1 == ranges[0].head.line) { + return motions.moveToFirstNonWhiteSpaceCharacter(cm, oldAnchor); + } else if (args.linewise){ + return oldAnchor; + } else { + return cursorMin(ranges[0].anchor, ranges[0].head); } }, - yank: function(cm, operatorArgs, vim, _curStart, _curEnd, curOriginal) { + yank: function(cm, args, ranges, oldAnchor) { + var vim = cm.state.vim; var text = cm.getSelection(); + var endPos = vim.visualMode + ? cursorMin(vim.sel.anchor, vim.sel.head, ranges[0].head, ranges[0].anchor) + : oldAnchor; vimGlobalState.registerController.pushText( - operatorArgs.registerName, 'yank', - text, operatorArgs.linewise, vim.visualBlock); - cm.setCursor(curOriginal); + args.registerName, 'yank', + text, args.linewise, vim.visualBlock); + return endPos; } }; @@ -2108,41 +2028,40 @@ vim.insertMode = true; vim.insertModeRepeat = actionArgs && actionArgs.repeat || 1; var insertAt = (actionArgs) ? actionArgs.insertAt : null; - if (vim.visualMode) { - var selections = getSelectedAreaRange(cm, vim); - var selectionStart = selections[0]; - var selectionEnd = selections[1]; - } + var sel = vim.sel; + var head = actionArgs.head || cm.getCursor('head'); + var height = cm.listSelections().length; if (insertAt == 'eol') { - var cursor = cm.getCursor(); - cursor = Pos(cursor.line, lineLength(cm, cursor.line)); - cm.setCursor(cursor); + head = Pos(head.line, lineLength(cm, head.line)); } else if (insertAt == 'charAfter') { - cm.setCursor(offsetCursor(cm.getCursor(), 0, 1)); + head = offsetCursor(head, 0, 1); } else if (insertAt == 'firstNonBlank') { - if (vim.visualMode && !vim.visualBlock) { - if (selectionEnd.line < selectionStart.line) { - cm.setCursor(selectionEnd); + head = motions.moveToFirstNonWhiteSpaceCharacter(cm, head); + } else if (insertAt == 'startOfSelectedArea') { + if (!vim.visualBlock) { + if (sel.head.line < sel.anchor.line) { + head = sel.head; } else { - selectionStart = Pos(selectionStart.line, 0); - cm.setCursor(selectionStart); + head = Pos(sel.anchor.line, 0); } - cm.setCursor(motions.moveToFirstNonWhiteSpaceCharacter(cm)); - } else if (vim.visualBlock) { - selectionEnd = Pos(selectionEnd.line, selectionStart.ch); - cm.setCursor(selectionStart); - selectBlock(cm, selectionEnd); } else { - cm.setCursor(motions.moveToFirstNonWhiteSpaceCharacter(cm)); + head = Pos( + Math.min(sel.head.line, sel.anchor.line), + Math.min(sel.head.ch, sel.anchor.ch)); + height = Math.abs(sel.head.line - sel.anchor.line) + 1; } } else if (insertAt == 'endOfSelectedArea') { - if (vim.visualBlock) { - selectionStart = Pos(selectionStart.line, selectionEnd.ch); - cm.setCursor(selectionStart); - selectBlock(cm, selectionEnd); - } else if (selectionEnd.line < selectionStart.line) { - selectionEnd = Pos(selectionStart.line, 0); - cm.setCursor(selectionEnd); + if (!vim.visualBlock) { + if (sel.head.line >= sel.anchor.line) { + head = offsetCursor(sel.head, 0, 1); + } else { + head = Pos(sel.anchor.line, 0); + } + } else { + head = Pos( + Math.min(sel.head.line, sel.anchor.line), + Math.max(sel.head.ch + 1, sel.anchor.ch)); + height = Math.abs(sel.head.line - sel.anchor.line) + 1; } } else if (insertAt == 'inplace') { if (vim.visualMode){ @@ -2168,129 +2087,68 @@ if (vim.visualMode) { exitVisualMode(cm); } + selectForInsert(cm, head, height); }, toggleVisualMode: function(cm, actionArgs, vim) { var repeat = actionArgs.repeat; - var curStart = cm.getCursor(); - var curEnd; - var selections = cm.listSelections(); + var anchor = cm.getCursor(); + var head; // TODO: The repeat should actually select number of characters/lines // equal to the repeat times the size of the previous visual // operation. if (!vim.visualMode) { - cm.on('mousedown', exitVisualMode); + // Entering visual mode vim.visualMode = true; vim.visualLine = !!actionArgs.linewise; vim.visualBlock = !!actionArgs.blockwise; - if (vim.visualLine) { - curStart.ch = 0; - curEnd = clipCursorToContent( - cm, Pos(curStart.line + repeat - 1, lineLength(cm, curStart.line)), - true /** includeLineBreak */); - } else { - curEnd = clipCursorToContent( - cm, Pos(curStart.line, curStart.ch + repeat), + head = clipCursorToContent( + cm, Pos(anchor.line, anchor.ch + repeat - 1), true /** includeLineBreak */); - } - cm.setSelection(curStart, curEnd); - CodeMirror.signal(cm, "vim-mode-change", {mode: "visual", subMode: vim.visualLine ? "linewise" : ""}); + vim.sel = { + anchor: anchor, + head: head + }; + CodeMirror.signal(cm, "vim-mode-change", {mode: "visual", subMode: vim.visualLine ? "linewise" : vim.visualBlock ? "blockwise" : ""}); + updateCmSelection(cm); + updateMark(cm, vim, '<', cursorMin(anchor, head)); + updateMark(cm, vim, '>', cursorMax(anchor, head)); + } else if (vim.visualLine ^ actionArgs.linewise || + vim.visualBlock ^ actionArgs.blockwise) { + // Toggling between modes + vim.visualLine = !!actionArgs.linewise; + vim.visualBlock = !!actionArgs.blockwise; + CodeMirror.signal(cm, "vim-mode-change", {mode: "visual", subMode: vim.visualLine ? "linewise" : vim.visualBlock ? "blockwise" : ""}); + updateCmSelection(cm); } else { - curStart = cm.getCursor('anchor'); - curEnd = cm.getCursor('head'); - if (vim.visualLine) { - if (actionArgs.blockwise) { - // This means Ctrl-V pressed in linewise visual - vim.visualBlock = true; - selectBlock(cm, curEnd); - CodeMirror.signal(cm, 'vim-mode-change', {mode: 'visual', subMode: 'blockwise'}); - } else if (!actionArgs.linewise) { - // v pressed in linewise, switch to characterwise visual mode - CodeMirror.signal(cm, 'vim-mode-change', {mode: 'visual'}); - } else { - exitVisualMode(cm); - } - vim.visualLine = false; - } else if (vim.visualBlock) { - if (actionArgs.linewise) { - // Shift-V pressed in blockwise visual mode - vim.visualLine = true; - curStart = Pos(selections[0].anchor.line, 0); - curEnd = Pos(selections[selections.length-1].anchor.line, lineLength(cm, selections[selections.length-1].anchor.line)); - cm.setSelection(curStart, curEnd); - CodeMirror.signal(cm, 'vim-mode-change', {mode: 'visual', subMode: 'linewise'}); - } else if (!actionArgs.blockwise) { - // v pressed in blockwise mode, Switch to characterwise - if (curEnd != selections[0].head) { - curStart = selections[0].anchor; - } else { - curStart = selections[selections.length-1].anchor; - } - cm.setSelection(curStart, curEnd); - CodeMirror.signal(cm, 'vim-mode-change', {mode: 'visual'}); - } else { - exitVisualMode(cm); - } - vim.visualBlock = false; - } else if (actionArgs.linewise) { - // Shift-V pressed in characterwise visual mode. Switch to linewise - // visual mode instead of exiting visual mode. - vim.visualLine = true; - curStart.ch = cursorIsBefore(curStart, curEnd) ? 0 : - lineLength(cm, curStart.line); - curEnd.ch = cursorIsBefore(curStart, curEnd) ? - lineLength(cm, curEnd.line) : 0; - cm.setSelection(curStart, curEnd); - CodeMirror.signal(cm, "vim-mode-change", {mode: "visual", subMode: "linewise"}); - } else if (actionArgs.blockwise) { - vim.visualBlock = true; - selectBlock(cm, curEnd); - CodeMirror.signal(cm, 'vim-mode-change', {mode: 'visual', subMode: 'blockwise'}); - } else { - exitVisualMode(cm); - } + exitVisualMode(cm); } - updateMark(cm, vim, '<', cursorIsBefore(curStart, curEnd) ? curStart - : curEnd); - updateMark(cm, vim, '>', cursorIsBefore(curStart, curEnd) ? curEnd - : curStart); }, reselectLastSelection: function(cm, _actionArgs, vim) { - var curStart = vim.marks['<'].find(); - var curEnd = vim.marks['>'].find(); var lastSelection = vim.lastSelection; + if (vim.visualMode) { + updateLastSelection(cm, vim); + } if (lastSelection) { - // Set the selections as per last selection - var selectionStart = lastSelection.curStartMark.find(); - var selectionEnd = lastSelection.curEndMark.find(); - var blockwise = lastSelection.visualBlock; - // update last selection - updateLastSelection(cm, vim, curStart, curEnd); - if (blockwise) { - cm.setCursor(selectionStart); - selectionStart = selectBlock(cm, selectionEnd); - } else { - cm.setSelection(selectionStart, selectionEnd); - selectionStart = cm.getCursor('anchor'); - selectionEnd = cm.getCursor('head'); - } - if (vim.visualMode) { - updateMark(cm, vim, '<', cursorIsBefore(selectionStart, selectionEnd) ? selectionStart - : selectionEnd); - updateMark(cm, vim, '>', cursorIsBefore(selectionStart, selectionEnd) ? selectionEnd - : selectionStart); + var anchor = lastSelection.anchorMark.find(); + var head = lastSelection.headMark.find(); + if (!anchor || !head) { + // If the marks have been destroyed due to edits, do nothing. + return; } - // Last selection is updated now + vim.sel = { + anchor: anchor, + head: head + }; vim.visualMode = true; - if (lastSelection.visualLine) { - vim.visualLine = true; - vim.visualBlock = false; - } else if (lastSelection.visualBlock) { - vim.visualLine = false; - vim.visualBlock = true; - } else { - vim.visualBlock = vim.visualLine = false; - } - CodeMirror.signal(cm, "vim-mode-change", {mode: "visual", subMode: vim.visualLine ? "linewise" : ""}); + vim.visualLine = lastSelection.visualLine; + vim.visualBlock = lastSelection.visualBlock; + updateCmSelection(cm); + updateMark(cm, vim, '<', cursorMin(anchor, head)); + updateMark(cm, vim, '>', cursorMax(anchor, head)); + CodeMirror.signal(cm, 'vim-mode-change', { + mode: 'visual', + subMode: vim.visualLine ? 'linewise' : + vim.visualBlock ? 'blockwise' : ''}); } }, joinLines: function(cm, actionArgs, vim) { @@ -2307,18 +2165,19 @@ Infinity)); } var finalCh = 0; - cm.operation(function() { - for (var i = curStart.line; i < curEnd.line; i++) { - finalCh = lineLength(cm, curStart.line); - var tmp = Pos(curStart.line + 1, - lineLength(cm, curStart.line + 1)); - var text = cm.getRange(curStart, tmp); - text = text.replace(/\n\s*/g, ' '); - cm.replaceRange(text, curStart, tmp); - } - var curFinalPos = Pos(curStart.line, finalCh); - cm.setCursor(curFinalPos); - }); + for (var i = curStart.line; i < curEnd.line; i++) { + finalCh = lineLength(cm, curStart.line); + var tmp = Pos(curStart.line + 1, + lineLength(cm, curStart.line + 1)); + var text = cm.getRange(curStart, tmp); + text = text.replace(/\n\s*/g, ' '); + cm.replaceRange(text, curStart, tmp); + } + var curFinalPos = Pos(curStart.line, finalCh); + cm.setCursor(curFinalPos); + if (vim.visualMode) { + exitVisualMode(cm); + } }, newLineAndEnterInsertMode: function(cm, actionArgs, vim) { vim.insertMode = true; @@ -2347,11 +2206,12 @@ return; } if (actionArgs.matchIndent) { - // length that considers tabs and cm.options.tabSize + var tabSize = cm.getOption("tabSize"); + // length that considers tabs and tabSize var whitespaceLength = function(str) { var tabs = (str.split("\t").length - 1); var spaces = (str.split(" ").length - 1); - return tabs * cm.options.tabSize + spaces * 1; + return tabs * tabSize + spaces * 1; }; var currentLine = cm.getLine(cm.getCursor().line); var indent = whitespaceLength(currentLine.match(/^\s*/)[0]); @@ -2364,8 +2224,8 @@ if (newIndent < 0) { return ""; } - else if (cm.options.indentWithTabs) { - var quotient = Math.floor(newIndent / cm.options.tabSize); + else if (cm.getOption("indentWithTabs")) { + var quotient = Math.floor(newIndent / tabSize); return Array(quotient + 1).join('\t'); } else { @@ -2413,7 +2273,7 @@ var emptyStrings = new Array(selections.length).join('1').split('1'); // save the curEnd marker before it get cleared due to cm.replaceRange. if (vim.lastSelection) { - lastSelectionCurEnd = vim.lastSelection.curEndMark.find(); + lastSelectionCurEnd = vim.lastSelection.headMark.find(); } // push the previously selected text to unnamed register vimGlobalState.registerController.unnamedRegister.setText(selectedText); @@ -2437,7 +2297,7 @@ } // restore the the curEnd marker if(lastSelectionCurEnd) { - vim.lastSelection.curEndMark = cm.setBookmark(lastSelectionCurEnd); + vim.lastSelection.headMark = cm.setBookmark(lastSelectionCurEnd); } if (linewise) { curPosFinal.ch=0; @@ -2479,10 +2339,10 @@ } } } - cm.setCursor(curPosFinal); if (vim.visualMode) { exitVisualMode(cm); } + cm.setCursor(curPosFinal); }, undo: function(cm, actionArgs) { cm.operation(function() { @@ -2527,7 +2387,7 @@ replaceWithStr = replaceWithStr.replace(/[^\n]/g, replaceWith); if (vim.visualBlock) { // Tabs are split in visua block before replacing - var spaces = new Array(cm.options.tabSize+1).join(' '); + var spaces = new Array(cm.getOption("tabSize")+1).join(' '); replaceWithStr = cm.getSelection(); replaceWithStr = replaceWithStr.replace(/\t/g, spaces).replace(/[^\n]/g, replaceWith).split('\n'); cm.replaceSelections(replaceWithStr); @@ -2583,28 +2443,7 @@ } repeatLastEdit(cm, vim, repeat, false /** repeatForInsert */); }, - changeCase: function(cm, actionArgs, vim) { - var selectionStart = getSelectedAreaRange(cm, vim)[0]; - var text = cm.getSelection(); - var lastSelectionCurEnd; - var blockSelection; - if (vim.lastSelection) { - // save the curEnd marker to avoid its removal due to cm.replaceRange - lastSelectionCurEnd = vim.lastSelection.curEndMark.find(); - blockSelection = vim.lastSelection.visualBlock; - } - var toLower = actionArgs.toLower; - text = toLower ? text.toLowerCase() : text.toUpperCase(); - cm.replaceSelections(vim.visualBlock || blockSelection ? text.split('\n') : [text]); - // restore the last selection curEnd marker - if (lastSelectionCurEnd) { - vim.lastSelection.curEndMark = cm.setBookmark(lastSelectionCurEnd); - } - cm.setCursor(selectionStart); - if (vim.visualMode) { - exitVisualMode(cm); - } - } + exitInsertMode: exitInsertMode }; /* @@ -2632,16 +2471,66 @@ return ret; } function offsetCursor(cur, offsetLine, offsetCh) { + if (typeof offsetLine === 'object') { + offsetCh = offsetLine.ch; + offsetLine = offsetLine.line; + } return Pos(cur.line + offsetLine, cur.ch + offsetCh); } - function matchKeysPartial(pressed, mapped) { - for (var i = 0; i < pressed.length; i++) { - // 'character' means any character. For mark, register commads, etc. - if (pressed[i] != mapped[i] && mapped[i] != 'character') { - return false; + function getOffset(anchor, head) { + return { + line: head.line - anchor.line, + ch: head.line - anchor.line + }; + } + function commandMatches(keys, keyMap, context, inputState) { + // Partial matches are not applied. They inform the key handler + // that the current key sequence is a subsequence of a valid key + // sequence, so that the key buffer is not cleared. + var match, partial = [], full = []; + for (var i = 0; i < keyMap.length; i++) { + var command = keyMap[i]; + if (context == 'insert' && command.context != 'insert' || + command.context && command.context != context || + inputState.operator && command.type == 'action' || + !(match = commandMatch(keys, command.keys))) { continue; } + if (match == 'partial') { partial.push(command); } + if (match == 'full') { full.push(command); } + } + return { + partial: partial.length && partial, + full: full.length && full + }; + } + function commandMatch(pressed, mapped) { + if (mapped.slice(-11) == '') { + // Last character matches anything. + var prefixLen = mapped.length - 11; + var pressedPrefix = pressed.slice(0, prefixLen); + var mappedPrefix = mapped.slice(0, prefixLen); + return pressedPrefix == mappedPrefix && pressed.length > prefixLen ? 'full' : + mappedPrefix.indexOf(pressedPrefix) == 0 ? 'partial' : false; + } else { + return pressed == mapped ? 'full' : + mapped.indexOf(pressed) == 0 ? 'partial' : false; + } + } + function lastChar(keys) { + var match = /^.*(<[\w\-]+>)$/.exec(keys); + var selectedCharacter = match ? match[1] : keys.slice(-1); + if (selectedCharacter.length > 1){ + switch(selectedCharacter){ + case '': + selectedCharacter='\n'; + break; + case '': + selectedCharacter=' '; + break; + default: + break; } } - return true; + return selectedCharacter; } function repeatFn(cm, fn, repeat) { return function() { @@ -2665,7 +2554,19 @@ } return false; } - function cusrorIsBetween(cur1, cur2, cur3) { + function cursorMin(cur1, cur2) { + if (arguments.length > 2) { + cur2 = cursorMin.apply(undefined, Array.prototype.slice.call(arguments, 1)); + } + return cursorIsBefore(cur1, cur2) ? cur1 : cur2; + } + function cursorMax(cur1, cur2) { + if (arguments.length > 2) { + cur2 = cursorMax.apply(undefined, Array.prototype.slice.call(arguments, 1)); + } + return cursorIsBefore(cur1, cur2) ? cur2 : cur1; + } + function cursorIsBetween(cur1, cur2, cur3) { // returns true if cur2 is between cur1 and cur3. var cur1before2 = cursorIsBefore(cur1, cur2); var cur2before3 = cursorIsBefore(cur2, cur3); @@ -2700,121 +2601,59 @@ // Distance between selectionEnd.ch and any(first considered here) selection.ch function selectBlock(cm, selectionEnd) { var selections = [], ranges = cm.listSelections(); - var firstRange = ranges[0].anchor, lastRange = ranges[ranges.length-1].anchor; - var start, end, direction, selectionStart; - var curEnd = cm.getCursor('head'); - var originalSelectionEnd = copyCursor(selectionEnd); - start = firstRange.line; - end = lastRange.line; - if (selectionEnd.line < curEnd.line) { - direction = 'up'; - } else if (selectionEnd.line > curEnd.line) { - direction = 'down'; - } else { - if (selectionEnd.ch != curEnd.ch) { - direction = selectionEnd.ch > curEnd.ch ? 'right' : 'left'; - } - selectionStart = cm.getCursor('anchor'); - } - var primIndex = getIndex(ranges, curEnd); - // sets to true when selectionEnd already lies inside the existing selections - selectionEnd = cm.clipPos(selectionEnd); - var contains = getIndex(ranges, selectionEnd) < 0 ? false : true; - var isClipped = !cursorEqual(originalSelectionEnd, selectionEnd); - // This function helps to check selection crossing - // in case of short lines. - var processSelectionCrossing = function() { - if (isClipped) { - if (curEnd.ch >= selectionStart.ch) { - selectionStart.ch++; - } - } else if (curEnd.ch == lineLength(cm, curEnd.line)) { - if (cursorEqual(ranges[primIndex].anchor, ranges[primIndex].head) && ranges.length>1) { - if (direction == 'up') { - if (contains || primIndex>0) { - start = firstRange.line; - end = selectionEnd.line; - selectionStart = ranges[primIndex-1].anchor; - } - } else { - if (contains || primIndex == 0) { - end = lastRange.line; - start = selectionEnd.line; - selectionStart = ranges[primIndex+1].anchor; - } - } - if (selectionEnd.ch >= selectionStart.ch) { - selectionStart.ch--; - } - } - } - }; - switch(direction) { - case 'up': - start = contains ? firstRange.line : selectionEnd.line; - end = contains ? selectionEnd.line : lastRange.line; - selectionStart = lastRange; - processSelectionCrossing(); - break; - case 'down': - start = contains ? selectionEnd.line : firstRange.line; - end = contains ? lastRange.line : selectionEnd.line; - selectionStart = firstRange; - processSelectionCrossing(); - break; - case 'left': - if ((selectionEnd.ch <= selectionStart.ch) && (curEnd.ch > selectionStart.ch)) { - selectionStart.ch++; - selectionEnd.ch--; - } - break; - case 'right': - if ((selectionStart.ch <= selectionEnd.ch) && (curEnd.ch < selectionStart.ch)) { - selectionStart.ch--; - selectionEnd.ch++; - } - break; - default: - start = selectionStart.line; - end = selectionEnd.line; - } - while (start <= end) { - var anchor = {line: start, ch: selectionStart.ch}; - var head = {line: start, ch: selectionEnd.ch}; - var range = {anchor: anchor, head: head}; + var head = copyCursor(cm.clipPos(selectionEnd)); + var isClipped = !cursorEqual(selectionEnd, head); + var curHead = cm.getCursor('head'); + var primIndex = getIndex(ranges, curHead); + var wasClipped = cursorEqual(ranges[primIndex].head, ranges[primIndex].anchor); + var max = ranges.length - 1; + var index = max - primIndex > primIndex ? max : 0; + var base = ranges[index].anchor; + + var firstLine = Math.min(base.line, head.line); + var lastLine = Math.max(base.line, head.line); + var baseCh = base.ch, headCh = head.ch; + + var dir = ranges[index].head.ch - baseCh; + var newDir = headCh - baseCh; + if (dir > 0 && newDir <= 0) { + baseCh++; + if (!isClipped) { headCh--; } + } else if (dir < 0 && newDir >= 0) { + baseCh--; + if (!wasClipped) { headCh++; } + } else if (dir < 0 && newDir == -1) { + baseCh--; + headCh++; + } + for (var line = firstLine; line <= lastLine; line++) { + var range = {anchor: new Pos(line, baseCh), head: new Pos(line, headCh)}; selections.push(range); - if (cursorEqual(head, selectionEnd)) { - primIndex = selections.indexOf(range); - } - start++; } - // Update selectionEnd and selectionStart - // after selection crossing - selectionEnd.ch = selections[0].head.ch; - selectionStart.ch = selections[0].anchor.ch; - if (cursorEqual(selectionEnd, selections[0].head)) { - selectionStart.line = selections[selections.length-1].anchor.line; - } else { - selectionStart.line = selections[0].anchor.line; + primIndex = head.line == lastLine ? selections.length - 1 : 0; + cm.setSelections(selections); + selectionEnd.ch = headCh; + base.ch = baseCh; + return base; + } + function selectForInsert(cm, head, height) { + var sel = []; + for (var i = 0; i < height; i++) { + var lineHead = offsetCursor(head, i, 0); + sel.push({anchor: lineHead, head: lineHead}); } - cm.setSelections(selections, primIndex); - return selectionStart; + cm.setSelections(sel, 0); } // getIndex returns the index of the cursor in the selections. function getIndex(ranges, cursor, end) { - var pos = -1; for (var i = 0; i < ranges.length; i++) { - var atAnchor = cursorEqual(ranges[i].anchor, cursor); - var atHead = cursorEqual(ranges[i].head, cursor); - if (end == 'head') { - pos = atHead ? i : pos; - } else if (end == 'anchor') { - pos = atAnchor ? i : pos; - } else { - pos = (atAnchor || atHead) ? i : pos; + var atAnchor = end != 'head' && cursorEqual(ranges[i].anchor, cursor); + var atHead = end != 'anchor' && cursorEqual(ranges[i].head, cursor); + if (atAnchor || atHead) { + return i; } } - return pos; + return -1; } function getSelectedAreaRange(cm, vim) { var lastSelection = vim.lastSelection; @@ -2845,8 +2684,8 @@ } cm.setSelections(selections); } else { - var start = lastSelection.curStartMark.find(); - var end = lastSelection.curEndMark.find(); + var start = lastSelection.anchorMark.find(); + var end = lastSelection.headMark.find(); var line = end.line - start.line; var ch = end.ch - start.ch; selectionEnd = {line: selectionEnd.line + line, ch: line ? selectionEnd.ch : ch + selectionEnd.ch}; @@ -2865,51 +2704,133 @@ return getCurrentSelectedAreaRange(); } } - function updateLastSelection(cm, vim, selectionStart, selectionEnd) { - if (!selectionStart || !selectionEnd) { - selectionStart = vim.marks['<'].find() || cm.getCursor('anchor'); - selectionEnd = vim.marks['>'].find() || cm.getCursor('head'); - } + // Updates the previous selection with the current selection's values. This + // should only be called in visual mode. + function updateLastSelection(cm, vim) { + var anchor = vim.sel.anchor; + var head = vim.sel.head; // To accommodate the effect of lastPastedText in the last selection if (vim.lastPastedText) { - selectionEnd = cm.posFromIndex(cm.indexFromPos(selectionStart) + vim.lastPastedText.length); + head = cm.posFromIndex(cm.indexFromPos(anchor) + vim.lastPastedText.length); vim.lastPastedText = null; } - var ranges = cm.listSelections(); - // This check ensures to set the cursor - // position where we left off in previous selection - var swap = getIndex(ranges, selectionStart, 'head') > -1; - if (vim.visualBlock) { - var height = Math.abs(selectionStart.line - selectionEnd.line)+1; - var width = Math.abs(selectionStart.ch - selectionEnd.ch); - var block = {height: height, width: width}; - } - // can't use selection state here because yank has already reset its cursor - // Also, Bookmarks make the visual selections robust to edit operations - vim.lastSelection = {'curStartMark': cm.setBookmark(swap ? selectionEnd : selectionStart), - 'curEndMark': cm.setBookmark(swap ? selectionStart : selectionEnd), + vim.lastSelection = {'anchorMark': cm.setBookmark(anchor), + 'headMark': cm.setBookmark(head), + 'anchor': copyCursor(anchor), + 'head': copyCursor(head), 'visualMode': vim.visualMode, 'visualLine': vim.visualLine, - 'visualBlock': block}; + 'visualBlock': vim.visualBlock}; + } + function expandSelection(cm, start, end) { + var sel = cm.state.vim.sel; + var head = sel.head; + var anchor = sel.anchor; + var tmp; + if (cursorIsBefore(end, start)) { + tmp = end; + end = start; + start = tmp; + } + if (cursorIsBefore(head, anchor)) { + head = cursorMin(start, head); + anchor = cursorMax(anchor, end); + } else { + anchor = cursorMin(start, anchor); + head = cursorMax(head, end); + head = offsetCursor(head, 0, -1); + if (head.ch == -1 && head.line != cm.firstLine()) { + head = Pos(head.line - 1, lineLength(cm, head.line - 1)); + } + } + return [anchor, head]; + } + /** + * Updates the CodeMirror selection to match the provided vim selection. + * If no arguments are given, it uses the current vim selection state. + */ + function updateCmSelection(cm, sel, mode) { + var vim = cm.state.vim; + sel = sel || vim.sel; + var mode = mode || + vim.visualLine ? 'line' : vim.visualBlock ? 'block' : 'char'; + var cmSel = makeCmSelection(cm, sel, mode); + cm.setSelections(cmSel.ranges, cmSel.primary); + updateFakeCursor(cm); + } + function makeCmSelection(cm, sel, mode, exclusive) { + var head = copyCursor(sel.head); + var anchor = copyCursor(sel.anchor); + if (mode == 'char') { + var headOffset = !exclusive && !cursorIsBefore(sel.head, sel.anchor) ? 1 : 0; + var anchorOffset = cursorIsBefore(sel.head, sel.anchor) ? 1 : 0; + head = offsetCursor(sel.head, 0, headOffset); + anchor = offsetCursor(sel.anchor, 0, anchorOffset); + return { + ranges: [{anchor: anchor, head: head}], + primary: 0 + }; + } else if (mode == 'line') { + if (!cursorIsBefore(sel.head, sel.anchor)) { + anchor.ch = 0; + + var lastLine = cm.lastLine(); + if (head.line > lastLine) { + head.line = lastLine; + } + head.ch = lineLength(cm, head.line); + } else { + head.ch = 0; + anchor.ch = lineLength(cm, anchor.line); + } + return { + ranges: [{anchor: anchor, head: head}], + primary: 0 + }; + } else if (mode == 'block') { + var top = Math.min(anchor.line, head.line), + left = Math.min(anchor.ch, head.ch), + bottom = Math.max(anchor.line, head.line), + right = Math.max(anchor.ch, head.ch) + 1; + var height = bottom - top + 1; + var primary = head.line == top ? 0 : height - 1; + var ranges = []; + for (var i = 0; i < height; i++) { + ranges.push({ + anchor: Pos(top + i, left), + head: Pos(top + i, right) + }); + } + return { + ranges: ranges, + primary: primary + }; + } + } + function getHead(cm) { + var cur = cm.getCursor('head'); + if (cm.getSelection().length == 1) { + // Small corner case when only 1 character is selected. The "real" + // head is the left of head and anchor. + cur = cursorMin(cur, cm.getCursor('anchor')); + } + return cur; } - function exitVisualMode(cm) { - cm.off('mousedown', exitVisualMode); + /** + * If moveHead is set to false, the CodeMirror selection will not be + * touched. The caller assumes the responsibility of putting the cursor + * in the right place. + */ + function exitVisualMode(cm, moveHead) { var vim = cm.state.vim; - var selectionStart = cm.getCursor('anchor'); - var selectionEnd = cm.getCursor('head'); - // hack to place the cursor at the right place - // in case of visual block - if (vim.visualBlock && (cursorIsBefore(selectionStart, selectionEnd))) { - selectionEnd.ch--; + if (moveHead !== false) { + cm.setCursor(clipCursorToContent(cm, vim.sel.head)); } updateLastSelection(cm, vim); vim.visualMode = false; vim.visualLine = false; vim.visualBlock = false; - if (!cursorEqual(selectionStart, selectionEnd)) { - cm.setCursor(clipCursorToContent(cm, selectionEnd)); - } CodeMirror.signal(cm, "vim-mode-change", {mode: "normal"}); if (vim.fakeCursor) { vim.fakeCursor.clear(); @@ -2964,7 +2885,7 @@ } function expandWordUnderCursor(cm, inclusive, _forward, bigWord, noSymbol) { - var cur = cm.getCursor(); + var cur = getHead(cm); var line = cm.getLine(cur.line); var idx = cur.ch; @@ -3239,6 +3160,7 @@ /** * @param {CodeMirror} cm CodeMirror object. + * @param {Pos} cur The position to start from. * @param {int} repeat Number of words to move past. * @param {boolean} forward True to search forward. False to search * backward. @@ -3248,8 +3170,7 @@ * False if only alphabet characters count as part of the word. * @return {Cursor} The position the cursor should move to. */ - function moveToWord(cm, repeat, forward, wordEnd, bigWord) { - var cur = cm.getCursor(); + function moveToWord(cm, cur, repeat, forward, wordEnd, bigWord) { var curStart = copyCursor(cur); var words = []; if (forward && !wordEnd || !forward && wordEnd) { @@ -3349,8 +3270,8 @@ // TODO: perhaps this finagling of start and end positions belonds // in codmirror/replaceRange? - function selectCompanionObject(cm, symb, inclusive) { - var cur = cm.getCursor(), start, end; + function selectCompanionObject(cm, head, symb, inclusive) { + var cur = head, start, end; var bracketRegexp = ({ '(': /[()]/, ')': /[()]/, @@ -3394,8 +3315,8 @@ // Takes in a symbol and a cursor and tries to simulate text objects that // have identical opening and closing symbols // TODO support across multiple lines - function findBeginningAndEnd(cm, symb, inclusive) { - var cur = copyCursor(cm.getCursor()); + function findBeginningAndEnd(cm, head, symb, inclusive) { + var cur = copyCursor(head); var line = cm.getLine(cur.line); var chars = line.split(''); var start, end, i, len; @@ -3828,6 +3749,7 @@ // shortNames must not match the prefix of the other command. var defaultExCommandMap = [ { name: 'map' }, + { name: 'imap', shortName: 'im' }, { name: 'nmap', shortName: 'nm' }, { name: 'vmap', shortName: 'vm' }, { name: 'unmap' }, @@ -3842,10 +3764,10 @@ { name: 'registers', shortName: 'reg', excludeFromCommandHistory: true }, { name: 'global', shortName: 'g' } ]; - Vim.ExCommandDispatcher = function() { + var ExCommandDispatcher = function() { this.buildCommandMap_(); }; - Vim.ExCommandDispatcher.prototype = { + ExCommandDispatcher.prototype = { processCommand: function(cm, input, opt_params) { var vim = cm.state.vim; var commandHistoryRegister = vimGlobalState.registerController.getRegister(':'); @@ -3882,7 +3804,7 @@ if (command.type == 'exToKey') { // Handle Ex to Key mapping. for (var i = 0; i < command.toKeys.length; i++) { - CodeMirror.Vim.handleKey(cm, command.toKeys[i]); + CodeMirror.Vim.handleKey(cm, command.toKeys[i], 'mapping'); } return; } else if (command.type == 'exToEx') { @@ -4006,7 +3928,7 @@ this.commandMap_[commandName] = { name: commandName, type: 'exToKey', - toKeys: parseKeyString(rhs), + toKeys: rhs, user: true }; } @@ -4014,7 +3936,7 @@ if (rhs != ':' && rhs.charAt(0) == ':') { // Key to Ex mapping. var mapping = { - keys: parseKeyString(lhs), + keys: lhs, type: 'keyToEx', exArgs: { input: rhs.substring(1) }, user: true}; @@ -4023,9 +3945,9 @@ } else { // Key to key mapping var mapping = { - keys: parseKeyString(lhs), + keys: lhs, type: 'keyToKey', - toKeys: parseKeyString(rhs), + toKeys: rhs, user: true }; if (ctx) { mapping.context = ctx; } @@ -4034,15 +3956,6 @@ } }, unmap: function(lhs, ctx) { - var arrayEquals = function(a, b) { - if (a === b) return true; - if (a == null || b == null) return true; - if (a.length != b.length) return false; - for (var i = 0; i < a.length; i++) { - if (a[i] !== b[i]) return false; - } - return true; - }; if (lhs != ':' && lhs.charAt(0) == ':') { // Ex to Ex or Ex to key mapping if (ctx) { throw Error('Mode not supported for ex mappings'); } @@ -4053,9 +3966,9 @@ } } else { // Key to Ex or key to key mapping - var keys = parseKeyString(lhs); + var keys = lhs; for (var i = 0; i < defaultKeymap.length; i++) { - if (arrayEquals(keys, defaultKeymap[i].keys) + if (keys == defaultKeymap[i].keys && defaultKeymap[i].context === ctx && defaultKeymap[i].user) { defaultKeymap.splice(i, 1); @@ -4067,21 +3980,6 @@ } }; - // Converts a key string sequence of the form abd into Vim's - // keymap representation. - function parseKeyString(str) { - var key, match; - var keys = []; - while (str) { - match = (/<\w+-.+?>|<\w+>|./).exec(str); - if (match === null)break; - key = match[0]; - str = str.substring(match.index + key.length); - keys.push(key); - } - return keys; - } - var exCommands = { map: function(cm, params, ctx) { var mapArgs = params.args; @@ -4093,6 +3991,7 @@ } exCommandDispatcher.map(mapArgs[0], mapArgs[1], ctx); }, + imap: function(cm, params) { this.map(cm, params, 'insert'); }, nmap: function(cm, params) { this.map(cm, params, 'normal'); }, vmap: function(cm, params) { this.map(cm, params, 'visual'); }, unmap: function(cm, params, ctx) { @@ -4467,7 +4366,7 @@ } }; - var exCommandDispatcher = new Vim.ExCommandDispatcher(); + var exCommandDispatcher = new ExCommandDispatcher(); /** * @param {CodeMirror} cm CodeMirror instance we are in. @@ -4555,6 +4454,7 @@ break; } if (done) { stop(close); } + return true; } // Actually do replace. @@ -4574,65 +4474,10 @@ }); } - // Register Vim with CodeMirror - function buildVimKeyMap() { - /** - * Handle the raw key event from CodeMirror. Translate the - * Shift + key modifier to the resulting letter, while preserving other - * modifers. - */ - function cmKeyToVimKey(key, modifier) { - var vimKey = key; - if (isUpperCase(vimKey) && modifier == 'Ctrl') { - vimKey = vimKey.toLowerCase(); - } - if (modifier) { - // Vim will parse modifier+key combination as a single key. - vimKey = modifier.charAt(0) + '-' + vimKey; - } - var specialKey = ({Enter:'CR',Backspace:'BS',Delete:'Del'})[vimKey]; - vimKey = specialKey ? specialKey : vimKey; - vimKey = vimKey.length > 1 ? '<'+ vimKey + '>' : vimKey; - return vimKey; - } - - // Closure to bind CodeMirror, key, modifier. - function keyMapper(vimKey) { - return function(cm) { - CodeMirror.signal(cm, 'vim-keypress', vimKey); - CodeMirror.Vim.handleKey(cm, vimKey); - }; - } - - var cmToVimKeymap = { - 'nofallthrough': true, - 'style': 'fat-cursor' - }; - function bindKeys(keys, modifier) { - for (var i = 0; i < keys.length; i++) { - var key = keys[i]; - if (!modifier && key.length == 1) { - // Wrap all keys without modifiers with '' to identify them by their - // key characters instead of key identifiers. - key = "'" + key + "'"; - } - var vimKey = cmKeyToVimKey(keys[i], modifier); - var cmKey = modifier ? modifier + '-' + key : key; - cmToVimKeymap[cmKey] = keyMapper(vimKey); - } - } - bindKeys(upperCaseAlphabet); - bindKeys(lowerCaseAlphabet); - bindKeys(upperCaseAlphabet, 'Ctrl'); - bindKeys(specialSymbols); - bindKeys(specialSymbols, 'Ctrl'); - bindKeys(numbers); - bindKeys(numbers, 'Ctrl'); - bindKeys(specialKeys); - bindKeys(specialKeys, 'Ctrl'); - return cmToVimKeymap; - } - CodeMirror.keyMap.vim = buildVimKeyMap(); + CodeMirror.keyMap.vim = { + attach: attachVimMap, + detach: detachVimMap + }; function exitInsertMode(cm) { var vim = cm.state.vim; @@ -4688,63 +4533,13 @@ } } - defineOption('enableInsertModeEscKeys', false, 'boolean'); - // Use this option to customize the two-character ESC keymap. - // If you want to use characters other than i j or k you'll have to add - // lines to the vim-insert and await-second keymaps later in this file. - defineOption('insertModeEscKeys', 'kj', 'string'); // The timeout in milliseconds for the two-character ESC keymap should be // adjusted according to your typing speed to prevent false positives. defineOption('insertModeEscKeysTimeout', 200, 'number'); - function firstEscCharacterHandler(ch) { - return function(cm){ - var keys = getOption('insertModeEscKeys'); - var firstEscCharacter = keys && keys.length > 1 && keys.charAt(0); - if (!getOption('enableInsertModeEscKeys')|| firstEscCharacter !== ch) { - return CodeMirror.Pass; - } else { - cm.replaceRange(ch, cm.getCursor(), cm.getCursor(), "+input"); - cm.setOption('keyMap', 'await-second'); - cm.state.vim.awaitingEscapeSecondCharacter = true; - setTimeout( - function(){ - if(cm.state.vim.awaitingEscapeSecondCharacter) { - cm.state.vim.awaitingEscapeSecondCharacter = false; - cm.setOption('keyMap', 'vim-insert'); - } - }, - getOption('insertModeEscKeysTimeout')); - } - }; - } - function secondEscCharacterHandler(ch){ - return function(cm) { - var keys = getOption('insertModeEscKeys'); - var secondEscCharacter = keys && keys.length > 1 && keys.charAt(1); - if (!getOption('enableInsertModeEscKeys')|| secondEscCharacter !== ch) { - return CodeMirror.Pass; - // This is not the handler you're looking for. Just insert as usual. - } else { - if (cm.state.vim.insertMode) { - var lastChange = vimGlobalState.macroModeState.lastInsertModeChanges; - if (lastChange && lastChange.changes.length) { - lastChange.changes.pop(); - } - } - cm.state.vim.awaitingEscapeSecondCharacter = false; - cm.replaceRange('', {ch: cm.getCursor().ch - 1, line: cm.getCursor().line}, - cm.getCursor(), "+input"); - exitInsertMode(cm); - } - }; - } CodeMirror.keyMap['vim-insert'] = { // TODO: override navigation keys so that Esc will cancel automatic // indentation from o, O, i_ - 'Esc': exitInsertMode, - 'Ctrl-[': exitInsertMode, - 'Ctrl-C': exitInsertMode, 'Ctrl-N': 'autocomplete', 'Ctrl-P': 'autocomplete', 'Enter': function(cm) { @@ -4752,26 +4547,22 @@ CodeMirror.commands.newlineAndIndent; fn(cm); }, - // The next few lines are where you'd add additional handlers if - // you wanted to use keys other than i j and k for two-character - // escape sequences. Don't forget to add them in the await-second - // section as well. - "'i'": firstEscCharacterHandler('i'), - "'j'": firstEscCharacterHandler('j'), - "'k'": firstEscCharacterHandler('k'), - fallthrough: ['default'] + fallthrough: ['default'], + attach: attachVimMap, + detach: detachVimMap }; CodeMirror.keyMap['await-second'] = { - "'i'": secondEscCharacterHandler('i'), - "'j'": secondEscCharacterHandler('j'), - "'k'": secondEscCharacterHandler('k'), - fallthrough: ['vim-insert'] + fallthrough: ['vim-insert'], + attach: attachVimMap, + detach: detachVimMap }; CodeMirror.keyMap['vim-replace'] = { 'Backspace': 'goCharLeft', - fallthrough: ['vim-insert'] + fallthrough: ['vim-insert'], + attach: attachVimMap, + detach: detachVimMap }; function executeMacroRegister(cm, vim, macroModeState, registerName) { @@ -4789,7 +4580,7 @@ match = (/<\w+-.+?>|<\w+>|./).exec(text); key = match[0]; text = text.substring(match.index + key.length); - CodeMirror.Vim.handleKey(cm, key); + CodeMirror.Vim.handleKey(cm, key, 'macro'); if (vim.insertMode) { var changes = register.insertModeChanges[imc++].changes; vimGlobalState.macroModeState.lastInsertModeChanges.changes = @@ -4866,28 +4657,49 @@ // Cursor moved outside the context of an edit. Reset the change. lastChange.changes = []; } - } else if (cm.doc.history.lastSelOrigin == '*mouse') { - // Reset lastHPos if mouse click was done in normal mode. - vim.lastHPos = cm.doc.getCursor().ch; - if (cm.somethingSelected()) { - // If something is still selected, enter visual mode. - vim.visualMode = true; - } + } else if (!cm.curOp.isVimOp) { + handleExternalSelection(cm, vim); } if (vim.visualMode) { - var from, head; - from = head = cm.getCursor('head'); - var anchor = cm.getCursor('anchor'); - var to = Pos(head.line, from.ch + (cursorIsBefore(anchor, head) ? -1 : 1)); - if (cursorIsBefore(to, from)) { - var temp = from; - from = to; - to = temp; - } - if (vim.fakeCursor) { - vim.fakeCursor.clear(); - } - vim.fakeCursor = cm.markText(from, to, {className: 'cm-animate-fat-cursor'}); + updateFakeCursor(cm); + } + } + function updateFakeCursor(cm) { + var vim = cm.state.vim; + var from = copyCursor(vim.sel.head); + var to = offsetCursor(from, 0, 1); + if (vim.fakeCursor) { + vim.fakeCursor.clear(); + } + vim.fakeCursor = cm.markText(from, to, {className: 'cm-animate-fat-cursor'}); + } + function handleExternalSelection(cm, vim) { + var anchor = cm.getCursor('anchor'); + var head = cm.getCursor('head'); + // Enter or exit visual mode to match mouse selection. + if (vim.visualMode && cursorEqual(head, anchor) && lineLength(cm, head.line) > head.ch) { + exitVisualMode(cm, false); + } else if (!vim.visualMode && !vim.insertMode && cm.somethingSelected()) { + vim.visualMode = true; + vim.visualLine = false; + CodeMirror.signal(cm, "vim-mode-change", {mode: "visual"}); + } + if (vim.visualMode) { + // Bind CodeMirror selection model to vim selection model. + // Mouse selections are considered visual characterwise. + var headOffset = !cursorIsBefore(head, anchor) ? -1 : 0; + var anchorOffset = cursorIsBefore(head, anchor) ? -1 : 0; + head = offsetCursor(head, 0, headOffset); + anchor = offsetCursor(anchor, 0, anchorOffset); + vim.sel = { + anchor: anchor, + head: head + }; + updateMark(cm, vim, '<', cursorMin(head, anchor)); + updateMark(cm, vim, '>', cursorMax(head, anchor)); + } else if (!vim.insertMode) { + // Reset lastHPos if selection was modified by something outside of vim mode e.g. by mouse. + vim.lastHPos = cm.getCursor().ch; } } @@ -4910,7 +4722,7 @@ return true; } if (keyName.indexOf('Delete') != -1 || keyName.indexOf('Backspace') != -1) { - CodeMirror.lookupKey(keyName, ['vim-insert'], onKeyFound); + CodeMirror.lookupKey(keyName, 'vim-insert', onKeyFound); } } @@ -4979,32 +4791,33 @@ } return true; } - var curStart = cm.getCursor(); + var head = cm.getCursor('head'); var inVisualBlock = vimGlobalState.macroModeState.lastInsertModeChanges.inVisualBlock; if (inVisualBlock) { // Set up block selection again for repeating the changes. var vim = cm.state.vim; - var block = vim.lastSelection.visualBlock; - var curEnd = Pos(curStart.line + block.height-1, curStart.ch); - cm.setCursor(curStart); - selectBlock(cm, curEnd); + var lastSel = vim.lastSelection; + var offset = getOffset(lastSel.anchor, lastSel.head); + selectForInsert(cm, head, offset.line + 1); repeat = cm.listSelections().length; - cm.setCursor(curStart); + cm.setCursor(head); } for (var i = 0; i < repeat; i++) { + if (inVisualBlock) { + cm.setCursor(offsetCursor(head, i, 0)); + } for (var j = 0; j < changes.length; j++) { var change = changes[j]; if (change instanceof InsertModeKey) { - CodeMirror.lookupKey(change.keyName, ['vim-insert'], keyHandler); + CodeMirror.lookupKey(change.keyName, 'vim-insert', keyHandler); } else { var cur = cm.getCursor(); cm.replaceRange(change, cur, cur); } } - if (inVisualBlock) { - curStart.line++; - cm.setCursor(curStart); - } + } + if (inVisualBlock) { + cm.setCursor(offsetCursor(head, 0, 1)); } } diff --git a/media/editors/codemirror/lib/addons-uncompressed.js b/media/editors/codemirror/lib/addons-uncompressed.js index a35cf1e9b8723..433020a6af715 100644 --- a/media/editors/codemirror/lib/addons-uncompressed.js +++ b/media/editors/codemirror/lib/addons-uncompressed.js @@ -127,31 +127,32 @@ }; var closingBrackets = ""; for (var i = 0; i < pairs.length; i += 2) (function(left, right) { - if (left != right) closingBrackets += right; + closingBrackets += right; map["'" + left + "'"] = function(cm) { if (cm.getOption("disableInput")) return CodeMirror.Pass; var ranges = cm.listSelections(), type, next; for (var i = 0; i < ranges.length; i++) { var range = ranges[i], cur = range.head, curType; var next = cm.getRange(cur, Pos(cur.line, cur.ch + 1)); - if (!range.empty()) + if (!range.empty()) { curType = "surround"; - else if (left == right && next == right) { + } else if (left == right && next == right) { if (cm.getRange(cur, Pos(cur.line, cur.ch + 3)) == left + left + left) curType = "skipThree"; else curType = "skip"; } else if (left == right && cur.ch > 1 && cm.getRange(Pos(cur.line, cur.ch - 2), cur) == left + left && - (cur.ch <= 2 || cm.getRange(Pos(cur.line, cur.ch - 3), Pos(cur.line, cur.ch - 2)) != left)) + (cur.ch <= 2 || cm.getRange(Pos(cur.line, cur.ch - 3), Pos(cur.line, cur.ch - 2)) != left)) { curType = "addFour"; - else if (left == '"' || left == "'") { + } else if (left == '"' || left == "'") { if (!CodeMirror.isWordChar(next) && enteringString(cm, cur, left)) curType = "both"; else return CodeMirror.Pass; - } else if (cm.getLine(cur.line).length == cur.ch || closingBrackets.indexOf(next) >= 0 || SPACE_CHAR_REGEX.test(next)) + } else if (cm.getLine(cur.line).length == cur.ch || closingBrackets.indexOf(next) >= 0 || SPACE_CHAR_REGEX.test(next)) { curType = "both"; - else + } else { return CodeMirror.Pass; + } if (!type) type = curType; else if (type != curType) return CodeMirror.Pass; } @@ -1128,12 +1129,12 @@ CodeMirror.registerHelper("fold", "include", function(cm, start) { (function(mod) { if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); + mod(require("../../lib/codemirror"), "cjs"); else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); + define(["../../lib/codemirror"], function(CM) { mod(CM, "amd"); }); else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { + mod(CodeMirror, "plain"); +})(function(CodeMirror, env) { if (!CodeMirror.modeURL) CodeMirror.modeURL = "../mode/%N/%N.js"; var loading = {}; @@ -1160,21 +1161,24 @@ CodeMirror.registerHelper("fold", "include", function(cm, start) { if (CodeMirror.modes.hasOwnProperty(mode)) return ensureDeps(mode, cont); if (loading.hasOwnProperty(mode)) return loading[mode].push(cont); - var script = document.createElement("script"); - script.src = CodeMirror.modeURL.replace(/%N/g, mode); - var others = document.getElementsByTagName("script")[0]; - others.parentNode.insertBefore(script, others); - var list = loading[mode] = [cont]; - var count = 0, poll = setInterval(function() { - if (++count > 100) return clearInterval(poll); - if (CodeMirror.modes.hasOwnProperty(mode)) { - clearInterval(poll); - loading[mode] = null; + var file = CodeMirror.modeURL.replace(/%N/g, mode); + if (env == "plain") { + var script = document.createElement("script"); + script.src = file; + var others = document.getElementsByTagName("script")[0]; + var list = loading[mode] = [cont]; + CodeMirror.on(script, "load", function() { ensureDeps(mode, function() { for (var i = 0; i < list.length; ++i) list[i](); }); - } - }, 200); + }); + others.parentNode.insertBefore(script, others); + } else if (env == "cjs") { + require(file); + cont(); + } else if (env == "amd") { + requirejs([file], cont); + } }; CodeMirror.autoLoadMode = function(instance, mode) { @@ -1447,305 +1451,253 @@ CodeMirror.multiplexingMode = function(outer /*, others */) { var defaultKeymap = [ // Key to key mapping. This goes first to make it possible to override // existing mappings. - { keys: [''], type: 'keyToKey', toKeys: ['h'] }, - { keys: [''], type: 'keyToKey', toKeys: ['l'] }, - { keys: [''], type: 'keyToKey', toKeys: ['k'] }, - { keys: [''], type: 'keyToKey', toKeys: ['j'] }, - { keys: [''], type: 'keyToKey', toKeys: ['l'] }, - { keys: [''], type: 'keyToKey', toKeys: ['h'] }, - { keys: [''], type: 'keyToKey', toKeys: ['W'] }, - { keys: [''], type: 'keyToKey', toKeys: ['B'] }, - { keys: [''], type: 'keyToKey', toKeys: ['w'] }, - { keys: [''], type: 'keyToKey', toKeys: ['b'] }, - { keys: [''], type: 'keyToKey', toKeys: ['j'] }, - { keys: [''], type: 'keyToKey', toKeys: ['k'] }, - { keys: [''], type: 'keyToKey', toKeys: [''] }, - { keys: [''], type: 'keyToKey', toKeys: [''] }, - { keys: ['s'], type: 'keyToKey', toKeys: ['c', 'l'], context: 'normal' }, - { keys: ['s'], type: 'keyToKey', toKeys: ['x', 'i'], context: 'visual'}, - { keys: ['S'], type: 'keyToKey', toKeys: ['c', 'c'], context: 'normal' }, - { keys: ['S'], type: 'keyToKey', toKeys: ['d', 'c', 'c'], context: 'visual' }, - { keys: [''], type: 'keyToKey', toKeys: ['0'] }, - { keys: [''], type: 'keyToKey', toKeys: ['$'] }, - { keys: [''], type: 'keyToKey', toKeys: [''] }, - { keys: [''], type: 'keyToKey', toKeys: [''] }, - { keys: [''], type: 'keyToKey', toKeys: ['j', '^'], context: 'normal' }, + { keys: '', type: 'keyToKey', toKeys: 'h' }, + { keys: '', type: 'keyToKey', toKeys: 'l' }, + { keys: '', type: 'keyToKey', toKeys: 'k' }, + { keys: '', type: 'keyToKey', toKeys: 'j' }, + { keys: '', type: 'keyToKey', toKeys: 'l' }, + { keys: '', type: 'keyToKey', toKeys: 'h' }, + { keys: '', type: 'keyToKey', toKeys: 'W' }, + { keys: '', type: 'keyToKey', toKeys: 'B' }, + { keys: '', type: 'keyToKey', toKeys: 'w' }, + { keys: '', type: 'keyToKey', toKeys: 'b' }, + { keys: '', type: 'keyToKey', toKeys: 'j' }, + { keys: '', type: 'keyToKey', toKeys: 'k' }, + { keys: '', type: 'keyToKey', toKeys: '' }, + { keys: '', type: 'keyToKey', toKeys: '' }, + { keys: '', type: 'keyToKey', toKeys: '', context: 'insert' }, + { keys: '', type: 'keyToKey', toKeys: '', context: 'insert' }, + { keys: 's', type: 'keyToKey', toKeys: 'cl', context: 'normal' }, + { keys: 's', type: 'keyToKey', toKeys: 'xi', context: 'visual'}, + { keys: 'S', type: 'keyToKey', toKeys: 'cc', context: 'normal' }, + { keys: 'S', type: 'keyToKey', toKeys: 'dcc', context: 'visual' }, + { keys: '', type: 'keyToKey', toKeys: '0' }, + { keys: '', type: 'keyToKey', toKeys: '$' }, + { keys: '', type: 'keyToKey', toKeys: '' }, + { keys: '', type: 'keyToKey', toKeys: '' }, + { keys: '', type: 'keyToKey', toKeys: 'j^', context: 'normal' }, // Motions - { keys: ['H'], type: 'motion', - motion: 'moveToTopLine', - motionArgs: { linewise: true, toJumplist: true }}, - { keys: ['M'], type: 'motion', - motion: 'moveToMiddleLine', - motionArgs: { linewise: true, toJumplist: true }}, - { keys: ['L'], type: 'motion', - motion: 'moveToBottomLine', - motionArgs: { linewise: true, toJumplist: true }}, - { keys: ['h'], type: 'motion', - motion: 'moveByCharacters', - motionArgs: { forward: false }}, - { keys: ['l'], type: 'motion', - motion: 'moveByCharacters', - motionArgs: { forward: true }}, - { keys: ['j'], type: 'motion', - motion: 'moveByLines', - motionArgs: { forward: true, linewise: true }}, - { keys: ['k'], type: 'motion', - motion: 'moveByLines', - motionArgs: { forward: false, linewise: true }}, - { keys: ['g','j'], type: 'motion', - motion: 'moveByDisplayLines', - motionArgs: { forward: true }}, - { keys: ['g','k'], type: 'motion', - motion: 'moveByDisplayLines', - motionArgs: { forward: false }}, - { keys: ['w'], type: 'motion', - motion: 'moveByWords', - motionArgs: { forward: true, wordEnd: false }}, - { keys: ['W'], type: 'motion', - motion: 'moveByWords', - motionArgs: { forward: true, wordEnd: false, bigWord: true }}, - { keys: ['e'], type: 'motion', - motion: 'moveByWords', - motionArgs: { forward: true, wordEnd: true, inclusive: true }}, - { keys: ['E'], type: 'motion', - motion: 'moveByWords', - motionArgs: { forward: true, wordEnd: true, bigWord: true, - inclusive: true }}, - { keys: ['b'], type: 'motion', - motion: 'moveByWords', - motionArgs: { forward: false, wordEnd: false }}, - { keys: ['B'], type: 'motion', - motion: 'moveByWords', - motionArgs: { forward: false, wordEnd: false, bigWord: true }}, - { keys: ['g', 'e'], type: 'motion', - motion: 'moveByWords', - motionArgs: { forward: false, wordEnd: true, inclusive: true }}, - { keys: ['g', 'E'], type: 'motion', - motion: 'moveByWords', - motionArgs: { forward: false, wordEnd: true, bigWord: true, - inclusive: true }}, - { keys: ['{'], type: 'motion', motion: 'moveByParagraph', - motionArgs: { forward: false, toJumplist: true }}, - { keys: ['}'], type: 'motion', motion: 'moveByParagraph', - motionArgs: { forward: true, toJumplist: true }}, - { keys: [''], type: 'motion', - motion: 'moveByPage', motionArgs: { forward: true }}, - { keys: [''], type: 'motion', - motion: 'moveByPage', motionArgs: { forward: false }}, - { keys: [''], type: 'motion', - motion: 'moveByScroll', - motionArgs: { forward: true, explicitRepeat: true }}, - { keys: [''], type: 'motion', - motion: 'moveByScroll', - motionArgs: { forward: false, explicitRepeat: true }}, - { keys: ['g', 'g'], type: 'motion', - motion: 'moveToLineOrEdgeOfDocument', - motionArgs: { forward: false, explicitRepeat: true, linewise: true, toJumplist: true }}, - { keys: ['G'], type: 'motion', - motion: 'moveToLineOrEdgeOfDocument', - motionArgs: { forward: true, explicitRepeat: true, linewise: true, toJumplist: true }}, - { keys: ['0'], type: 'motion', motion: 'moveToStartOfLine' }, - { keys: ['^'], type: 'motion', - motion: 'moveToFirstNonWhiteSpaceCharacter' }, - { keys: ['+'], type: 'motion', - motion: 'moveByLines', - motionArgs: { forward: true, toFirstChar:true }}, - { keys: ['-'], type: 'motion', - motion: 'moveByLines', - motionArgs: { forward: false, toFirstChar:true }}, - { keys: ['_'], type: 'motion', - motion: 'moveByLines', - motionArgs: { forward: true, toFirstChar:true, repeatOffset:-1 }}, - { keys: ['$'], type: 'motion', - motion: 'moveToEol', - motionArgs: { inclusive: true }}, - { keys: ['%'], type: 'motion', - motion: 'moveToMatchedSymbol', - motionArgs: { inclusive: true, toJumplist: true }}, - { keys: ['f', 'character'], type: 'motion', - motion: 'moveToCharacter', - motionArgs: { forward: true , inclusive: true }}, - { keys: ['F', 'character'], type: 'motion', - motion: 'moveToCharacter', - motionArgs: { forward: false }}, - { keys: ['t', 'character'], type: 'motion', - motion: 'moveTillCharacter', - motionArgs: { forward: true, inclusive: true }}, - { keys: ['T', 'character'], type: 'motion', - motion: 'moveTillCharacter', - motionArgs: { forward: false }}, - { keys: [';'], type: 'motion', motion: 'repeatLastCharacterSearch', - motionArgs: { forward: true }}, - { keys: [','], type: 'motion', motion: 'repeatLastCharacterSearch', - motionArgs: { forward: false }}, - { keys: ['\'', 'character'], type: 'motion', motion: 'goToMark', - motionArgs: {toJumplist: true, linewise: true}}, - { keys: ['`', 'character'], type: 'motion', motion: 'goToMark', - motionArgs: {toJumplist: true}}, - { keys: [']', '`'], type: 'motion', motion: 'jumpToMark', motionArgs: { forward: true } }, - { keys: ['[', '`'], type: 'motion', motion: 'jumpToMark', motionArgs: { forward: false } }, - { keys: [']', '\''], type: 'motion', motion: 'jumpToMark', motionArgs: { forward: true, linewise: true } }, - { keys: ['[', '\''], type: 'motion', motion: 'jumpToMark', motionArgs: { forward: false, linewise: true } }, + { keys: 'H', type: 'motion', motion: 'moveToTopLine', motionArgs: { linewise: true, toJumplist: true }}, + { keys: 'M', type: 'motion', motion: 'moveToMiddleLine', motionArgs: { linewise: true, toJumplist: true }}, + { keys: 'L', type: 'motion', motion: 'moveToBottomLine', motionArgs: { linewise: true, toJumplist: true }}, + { keys: 'h', type: 'motion', motion: 'moveByCharacters', motionArgs: { forward: false }}, + { keys: 'l', type: 'motion', motion: 'moveByCharacters', motionArgs: { forward: true }}, + { keys: 'j', type: 'motion', motion: 'moveByLines', motionArgs: { forward: true, linewise: true }}, + { keys: 'k', type: 'motion', motion: 'moveByLines', motionArgs: { forward: false, linewise: true }}, + { keys: 'gj', type: 'motion', motion: 'moveByDisplayLines', motionArgs: { forward: true }}, + { keys: 'gk', type: 'motion', motion: 'moveByDisplayLines', motionArgs: { forward: false }}, + { keys: 'w', type: 'motion', motion: 'moveByWords', motionArgs: { forward: true, wordEnd: false }}, + { keys: 'W', type: 'motion', motion: 'moveByWords', motionArgs: { forward: true, wordEnd: false, bigWord: true }}, + { keys: 'e', type: 'motion', motion: 'moveByWords', motionArgs: { forward: true, wordEnd: true, inclusive: true }}, + { keys: 'E', type: 'motion', motion: 'moveByWords', motionArgs: { forward: true, wordEnd: true, bigWord: true, inclusive: true }}, + { keys: 'b', type: 'motion', motion: 'moveByWords', motionArgs: { forward: false, wordEnd: false }}, + { keys: 'B', type: 'motion', motion: 'moveByWords', motionArgs: { forward: false, wordEnd: false, bigWord: true }}, + { keys: 'ge', type: 'motion', motion: 'moveByWords', motionArgs: { forward: false, wordEnd: true, inclusive: true }}, + { keys: 'gE', type: 'motion', motion: 'moveByWords', motionArgs: { forward: false, wordEnd: true, bigWord: true, inclusive: true }}, + { keys: '{', type: 'motion', motion: 'moveByParagraph', motionArgs: { forward: false, toJumplist: true }}, + { keys: '}', type: 'motion', motion: 'moveByParagraph', motionArgs: { forward: true, toJumplist: true }}, + { keys: '', type: 'motion', motion: 'moveByPage', motionArgs: { forward: true }}, + { keys: '', type: 'motion', motion: 'moveByPage', motionArgs: { forward: false }}, + { keys: '', type: 'motion', motion: 'moveByScroll', motionArgs: { forward: true, explicitRepeat: true }}, + { keys: '', type: 'motion', motion: 'moveByScroll', motionArgs: { forward: false, explicitRepeat: true }}, + { keys: 'gg', type: 'motion', motion: 'moveToLineOrEdgeOfDocument', motionArgs: { forward: false, explicitRepeat: true, linewise: true, toJumplist: true }}, + { keys: 'G', type: 'motion', motion: 'moveToLineOrEdgeOfDocument', motionArgs: { forward: true, explicitRepeat: true, linewise: true, toJumplist: true }}, + { keys: '0', type: 'motion', motion: 'moveToStartOfLine' }, + { keys: '^', type: 'motion', motion: 'moveToFirstNonWhiteSpaceCharacter' }, + { keys: '+', type: 'motion', motion: 'moveByLines', motionArgs: { forward: true, toFirstChar:true }}, + { keys: '-', type: 'motion', motion: 'moveByLines', motionArgs: { forward: false, toFirstChar:true }}, + { keys: '_', type: 'motion', motion: 'moveByLines', motionArgs: { forward: true, toFirstChar:true, repeatOffset:-1 }}, + { keys: '$', type: 'motion', motion: 'moveToEol', motionArgs: { inclusive: true }}, + { keys: '%', type: 'motion', motion: 'moveToMatchedSymbol', motionArgs: { inclusive: true, toJumplist: true }}, + { keys: 'f', type: 'motion', motion: 'moveToCharacter', motionArgs: { forward: true , inclusive: true }}, + { keys: 'F', type: 'motion', motion: 'moveToCharacter', motionArgs: { forward: false }}, + { keys: 't', type: 'motion', motion: 'moveTillCharacter', motionArgs: { forward: true, inclusive: true }}, + { keys: 'T', type: 'motion', motion: 'moveTillCharacter', motionArgs: { forward: false }}, + { keys: ';', type: 'motion', motion: 'repeatLastCharacterSearch', motionArgs: { forward: true }}, + { keys: ',', type: 'motion', motion: 'repeatLastCharacterSearch', motionArgs: { forward: false }}, + { keys: '\'', type: 'motion', motion: 'goToMark', motionArgs: {toJumplist: true, linewise: true}}, + { keys: '`', type: 'motion', motion: 'goToMark', motionArgs: {toJumplist: true}}, + { keys: ']`', type: 'motion', motion: 'jumpToMark', motionArgs: { forward: true } }, + { keys: '[`', type: 'motion', motion: 'jumpToMark', motionArgs: { forward: false } }, + { keys: ']\'', type: 'motion', motion: 'jumpToMark', motionArgs: { forward: true, linewise: true } }, + { keys: '[\'', type: 'motion', motion: 'jumpToMark', motionArgs: { forward: false, linewise: true } }, // the next two aren't motions but must come before more general motion declarations - { keys: [']', 'p'], type: 'action', action: 'paste', isEdit: true, - actionArgs: { after: true, isEdit: true, matchIndent: true}}, - { keys: ['[', 'p'], type: 'action', action: 'paste', isEdit: true, - actionArgs: { after: false, isEdit: true, matchIndent: true}}, - { keys: [']', 'character'], type: 'motion', - motion: 'moveToSymbol', - motionArgs: { forward: true, toJumplist: true}}, - { keys: ['[', 'character'], type: 'motion', - motion: 'moveToSymbol', - motionArgs: { forward: false, toJumplist: true}}, - { keys: ['|'], type: 'motion', - motion: 'moveToColumn', - motionArgs: { }}, - { keys: ['o'], type: 'motion', motion: 'moveToOtherHighlightedEnd', motionArgs: { }, context:'visual'}, - { keys: ['O'], type: 'motion', motion: 'moveToOtherHighlightedEnd', motionArgs: {sameLine: true}, context:'visual'}, + { keys: ']p', type: 'action', action: 'paste', isEdit: true, actionArgs: { after: true, isEdit: true, matchIndent: true}}, + { keys: '[p', type: 'action', action: 'paste', isEdit: true, actionArgs: { after: false, isEdit: true, matchIndent: true}}, + { keys: ']', type: 'motion', motion: 'moveToSymbol', motionArgs: { forward: true, toJumplist: true}}, + { keys: '[', type: 'motion', motion: 'moveToSymbol', motionArgs: { forward: false, toJumplist: true}}, + { keys: '|', type: 'motion', motion: 'moveToColumn'}, + { keys: 'o', type: 'motion', motion: 'moveToOtherHighlightedEnd', context:'visual'}, + { keys: 'O', type: 'motion', motion: 'moveToOtherHighlightedEnd', motionArgs: {sameLine: true}, context:'visual'}, // Operators - { keys: ['d'], type: 'operator', operator: 'delete' }, - { keys: ['y'], type: 'operator', operator: 'yank' }, - { keys: ['c'], type: 'operator', operator: 'change' }, - { keys: ['>'], type: 'operator', operator: 'indent', - operatorArgs: { indentRight: true }}, - { keys: ['<'], type: 'operator', operator: 'indent', - operatorArgs: { indentRight: false }}, - { keys: ['g', '~'], type: 'operator', operator: 'swapcase' }, - { keys: ['n'], type: 'motion', motion: 'findNext', - motionArgs: { forward: true, toJumplist: true }}, - { keys: ['N'], type: 'motion', motion: 'findNext', - motionArgs: { forward: false, toJumplist: true }}, + { keys: 'd', type: 'operator', operator: 'delete' }, + { keys: 'y', type: 'operator', operator: 'yank' }, + { keys: 'c', type: 'operator', operator: 'change' }, + { keys: '>', type: 'operator', operator: 'indent', operatorArgs: { indentRight: true }}, + { keys: '<', type: 'operator', operator: 'indent', operatorArgs: { indentRight: false }}, + { keys: 'g~', type: 'operator', operator: 'changeCase' }, + { keys: 'gu', type: 'operator', operator: 'changeCase', operatorArgs: {toLower: true}, isEdit: true }, + { keys: 'gU', type: 'operator', operator: 'changeCase', operatorArgs: {toLower: false}, isEdit: true }, + { keys: 'n', type: 'motion', motion: 'findNext', motionArgs: { forward: true, toJumplist: true }}, + { keys: 'N', type: 'motion', motion: 'findNext', motionArgs: { forward: false, toJumplist: true }}, // Operator-Motion dual commands - { keys: ['x'], type: 'operatorMotion', operator: 'delete', - motion: 'moveByCharacters', motionArgs: { forward: true }, - operatorMotionArgs: { visualLine: false }}, - { keys: ['X'], type: 'operatorMotion', operator: 'delete', - motion: 'moveByCharacters', motionArgs: { forward: false }, - operatorMotionArgs: { visualLine: true }}, - { keys: ['D'], type: 'operatorMotion', operator: 'delete', - motion: 'moveToEol', motionArgs: { inclusive: true }, - operatorMotionArgs: { visualLine: true }}, - { keys: ['Y'], type: 'operatorMotion', operator: 'yank', - motion: 'moveToEol', motionArgs: { inclusive: true }, - operatorMotionArgs: { visualLine: true }}, - { keys: ['C'], type: 'operatorMotion', - operator: 'change', - motion: 'moveToEol', motionArgs: { inclusive: true }, - operatorMotionArgs: { visualLine: true }}, - { keys: ['~'], type: 'operatorMotion', - operator: 'swapcase', operatorArgs: { shouldMoveCursor: true }, - motion: 'moveByCharacters', motionArgs: { forward: true }}, + { keys: 'x', type: 'operatorMotion', operator: 'delete', motion: 'moveByCharacters', motionArgs: { forward: true }, operatorMotionArgs: { visualLine: false }}, + { keys: 'X', type: 'operatorMotion', operator: 'delete', motion: 'moveByCharacters', motionArgs: { forward: false }, operatorMotionArgs: { visualLine: true }}, + { keys: 'D', type: 'operatorMotion', operator: 'delete', motion: 'moveToEol', motionArgs: { inclusive: true }, context: 'normal'}, + { keys: 'D', type: 'operator', operator: 'delete', operatorArgs: { linewise: true }, context: 'visual'}, + { keys: 'Y', type: 'operatorMotion', operator: 'yank', motion: 'moveToEol', motionArgs: { inclusive: true }, context: 'normal'}, + { keys: 'Y', type: 'operator', operator: 'yank', operatorArgs: { linewise: true }, context: 'visual'}, + { keys: 'C', type: 'operatorMotion', operator: 'change', motion: 'moveToEol', motionArgs: { inclusive: true }, context: 'normal'}, + { keys: 'C', type: 'operator', operator: 'change', operatorArgs: { linewise: true }, context: 'visual'}, + { keys: '~', type: 'operatorMotion', operator: 'changeCase', motion: 'moveByCharacters', motionArgs: { forward: true }, operatorArgs: { shouldMoveCursor: true }, context: 'normal'}, + { keys: '~', type: 'operator', operator: 'changeCase', context: 'visual'}, + { keys: '', type: 'operatorMotion', operator: 'delete', motion: 'moveByWords', motionArgs: { forward: false, wordEnd: false }, context: 'insert' }, // Actions - { keys: [''], type: 'action', action: 'jumpListWalk', - actionArgs: { forward: true }}, - { keys: [''], type: 'action', action: 'jumpListWalk', - actionArgs: { forward: false }}, - { keys: [''], type: 'action', - action: 'scroll', - actionArgs: { forward: true, linewise: true }}, - { keys: [''], type: 'action', - action: 'scroll', - actionArgs: { forward: false, linewise: true }}, - { keys: ['a'], type: 'action', action: 'enterInsertMode', isEdit: true, - actionArgs: { insertAt: 'charAfter' }}, - { keys: ['A'], type: 'action', action: 'enterInsertMode', isEdit: true, - actionArgs: { insertAt: 'eol' }}, - { keys: ['A'], type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'endOfSelectedArea' }, context: 'visual' }, - { keys: ['i'], type: 'action', action: 'enterInsertMode', isEdit: true, - actionArgs: { insertAt: 'inplace' }}, - { keys: ['I'], type: 'action', action: 'enterInsertMode', isEdit: true, - actionArgs: { insertAt: 'firstNonBlank' }}, - { keys: ['o'], type: 'action', action: 'newLineAndEnterInsertMode', - isEdit: true, interlaceInsertRepeat: true, - actionArgs: { after: true }}, - { keys: ['O'], type: 'action', action: 'newLineAndEnterInsertMode', - isEdit: true, interlaceInsertRepeat: true, - actionArgs: { after: false }}, - { keys: ['v'], type: 'action', action: 'toggleVisualMode' }, - { keys: ['V'], type: 'action', action: 'toggleVisualMode', - actionArgs: { linewise: true }}, - { keys: [''], type: 'action', action: 'toggleVisualMode', - actionArgs: { blockwise: true }}, - { keys: ['g', 'v'], type: 'action', action: 'reselectLastSelection' }, - { keys: ['J'], type: 'action', action: 'joinLines', isEdit: true }, - { keys: ['p'], type: 'action', action: 'paste', isEdit: true, - actionArgs: { after: true, isEdit: true }}, - { keys: ['P'], type: 'action', action: 'paste', isEdit: true, - actionArgs: { after: false, isEdit: true }}, - { keys: ['r', 'character'], type: 'action', action: 'replace', isEdit: true }, - { keys: ['@', 'character'], type: 'action', action: 'replayMacro' }, - { keys: ['q', 'character'], type: 'action', action: 'enterMacroRecordMode' }, + { keys: '', type: 'action', action: 'jumpListWalk', actionArgs: { forward: true }}, + { keys: '', type: 'action', action: 'jumpListWalk', actionArgs: { forward: false }}, + { keys: '', type: 'action', action: 'scroll', actionArgs: { forward: true, linewise: true }}, + { keys: '', type: 'action', action: 'scroll', actionArgs: { forward: false, linewise: true }}, + { keys: 'a', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'charAfter' }, context: 'normal' }, + { keys: 'A', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'eol' }, context: 'normal' }, + { keys: 'A', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'endOfSelectedArea' }, context: 'visual' }, + { keys: 'i', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'inplace' }, context: 'normal' }, + { keys: 'I', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'firstNonBlank'}, context: 'normal' }, + { keys: 'I', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'startOfSelectedArea' }, context: 'visual' }, + { keys: 'o', type: 'action', action: 'newLineAndEnterInsertMode', isEdit: true, interlaceInsertRepeat: true, actionArgs: { after: true }, context: 'normal' }, + { keys: 'O', type: 'action', action: 'newLineAndEnterInsertMode', isEdit: true, interlaceInsertRepeat: true, actionArgs: { after: false }, context: 'normal' }, + { keys: 'v', type: 'action', action: 'toggleVisualMode' }, + { keys: 'V', type: 'action', action: 'toggleVisualMode', actionArgs: { linewise: true }}, + { keys: '', type: 'action', action: 'toggleVisualMode', actionArgs: { blockwise: true }}, + { keys: 'gv', type: 'action', action: 'reselectLastSelection' }, + { keys: 'J', type: 'action', action: 'joinLines', isEdit: true }, + { keys: 'p', type: 'action', action: 'paste', isEdit: true, actionArgs: { after: true, isEdit: true }}, + { keys: 'P', type: 'action', action: 'paste', isEdit: true, actionArgs: { after: false, isEdit: true }}, + { keys: 'r', type: 'action', action: 'replace', isEdit: true }, + { keys: '@', type: 'action', action: 'replayMacro' }, + { keys: 'q', type: 'action', action: 'enterMacroRecordMode' }, // Handle Replace-mode as a special case of insert mode. - { keys: ['R'], type: 'action', action: 'enterInsertMode', isEdit: true, - actionArgs: { replace: true }}, - { keys: ['u'], type: 'action', action: 'undo' }, - { keys: ['u'], type: 'action', action: 'changeCase', actionArgs: {toLower: true}, context: 'visual', isEdit: true }, - { keys: ['U'],type: 'action', action: 'changeCase', actionArgs: {toLower: false}, context: 'visual', isEdit: true }, - { keys: [''], type: 'action', action: 'redo' }, - { keys: ['m', 'character'], type: 'action', action: 'setMark' }, - { keys: ['"', 'character'], type: 'action', action: 'setRegister' }, - { keys: ['z', 'z'], type: 'action', action: 'scrollToCursor', - actionArgs: { position: 'center' }}, - { keys: ['z', '.'], type: 'action', action: 'scrollToCursor', - actionArgs: { position: 'center' }, - motion: 'moveToFirstNonWhiteSpaceCharacter' }, - { keys: ['z', 't'], type: 'action', action: 'scrollToCursor', - actionArgs: { position: 'top' }}, - { keys: ['z', ''], type: 'action', action: 'scrollToCursor', - actionArgs: { position: 'top' }, - motion: 'moveToFirstNonWhiteSpaceCharacter' }, - { keys: ['z', '-'], type: 'action', action: 'scrollToCursor', - actionArgs: { position: 'bottom' }}, - { keys: ['z', 'b'], type: 'action', action: 'scrollToCursor', - actionArgs: { position: 'bottom' }, - motion: 'moveToFirstNonWhiteSpaceCharacter' }, - { keys: ['.'], type: 'action', action: 'repeatLastEdit' }, - { keys: [''], type: 'action', action: 'incrementNumberToken', - isEdit: true, - actionArgs: {increase: true, backtrack: false}}, - { keys: [''], type: 'action', action: 'incrementNumberToken', - isEdit: true, - actionArgs: {increase: false, backtrack: false}}, + { keys: 'R', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { replace: true }}, + { keys: 'u', type: 'action', action: 'undo', context: 'normal' }, + { keys: 'u', type: 'operator', operator: 'changeCase', operatorArgs: {toLower: true}, context: 'visual', isEdit: true }, + { keys: 'U', type: 'operator', operator: 'changeCase', operatorArgs: {toLower: false}, context: 'visual', isEdit: true }, + { keys: '', type: 'action', action: 'redo' }, + { keys: 'm', type: 'action', action: 'setMark' }, + { keys: '"', type: 'action', action: 'setRegister' }, + { keys: 'zz', type: 'action', action: 'scrollToCursor', actionArgs: { position: 'center' }}, + { keys: 'z.', type: 'action', action: 'scrollToCursor', actionArgs: { position: 'center' }, motion: 'moveToFirstNonWhiteSpaceCharacter' }, + { keys: 'zt', type: 'action', action: 'scrollToCursor', actionArgs: { position: 'top' }}, + { keys: 'z', type: 'action', action: 'scrollToCursor', actionArgs: { position: 'top' }, motion: 'moveToFirstNonWhiteSpaceCharacter' }, + { keys: 'z-', type: 'action', action: 'scrollToCursor', actionArgs: { position: 'bottom' }}, + { keys: 'zb', type: 'action', action: 'scrollToCursor', actionArgs: { position: 'bottom' }, motion: 'moveToFirstNonWhiteSpaceCharacter' }, + { keys: '.', type: 'action', action: 'repeatLastEdit' }, + { keys: '', type: 'action', action: 'incrementNumberToken', isEdit: true, actionArgs: {increase: true, backtrack: false}}, + { keys: '', type: 'action', action: 'incrementNumberToken', isEdit: true, actionArgs: {increase: false, backtrack: false}}, // Text object motions - { keys: ['a', 'character'], type: 'motion', - motion: 'textObjectManipulation' }, - { keys: ['i', 'character'], type: 'motion', - motion: 'textObjectManipulation', - motionArgs: { textObjectInner: true }}, + { keys: 'a', type: 'motion', motion: 'textObjectManipulation' }, + { keys: 'i', type: 'motion', motion: 'textObjectManipulation', motionArgs: { textObjectInner: true }}, // Search - { keys: ['/'], type: 'search', - searchArgs: { forward: true, querySrc: 'prompt', toJumplist: true }}, - { keys: ['?'], type: 'search', - searchArgs: { forward: false, querySrc: 'prompt', toJumplist: true }}, - { keys: ['*'], type: 'search', - searchArgs: { forward: true, querySrc: 'wordUnderCursor', wholeWordOnly: true, toJumplist: true }}, - { keys: ['#'], type: 'search', - searchArgs: { forward: false, querySrc: 'wordUnderCursor', wholeWordOnly: true, toJumplist: true }}, - { keys: ['g', '*'], type: 'search', searchArgs: { forward: true, querySrc: 'wordUnderCursor', toJumplist: true }}, - { keys: ['g', '#'], type: 'search', searchArgs: { forward: false, querySrc: 'wordUnderCursor', toJumplist: true }}, + { keys: '/', type: 'search', searchArgs: { forward: true, querySrc: 'prompt', toJumplist: true }}, + { keys: '?', type: 'search', searchArgs: { forward: false, querySrc: 'prompt', toJumplist: true }}, + { keys: '*', type: 'search', searchArgs: { forward: true, querySrc: 'wordUnderCursor', wholeWordOnly: true, toJumplist: true }}, + { keys: '#', type: 'search', searchArgs: { forward: false, querySrc: 'wordUnderCursor', wholeWordOnly: true, toJumplist: true }}, + { keys: 'g*', type: 'search', searchArgs: { forward: true, querySrc: 'wordUnderCursor', toJumplist: true }}, + { keys: 'g#', type: 'search', searchArgs: { forward: false, querySrc: 'wordUnderCursor', toJumplist: true }}, // Ex command - { keys: [':'], type: 'ex' } + { keys: ':', type: 'ex' } ]; var Pos = CodeMirror.Pos; + var modifierCodes = [16, 17, 18, 91]; + var specialKey = {Enter:'CR',Backspace:'BS',Delete:'Del'}; + var mac = /Mac/.test(navigator.platform); var Vim = function() { - CodeMirror.defineOption('vimMode', false, function(cm, val) { - if (val) { - cm.setOption('keyMap', 'vim'); - cm.setOption('disableInput', true); - cm.setOption('showCursorWhenSelecting', false); - CodeMirror.signal(cm, "vim-mode-change", {mode: "normal"}); - cm.on('cursorActivity', onCursorActivity); - maybeInitVimState(cm); - CodeMirror.on(cm.getInputField(), 'paste', getOnPasteFn(cm)); - } else if (cm.state.vim) { - cm.setOption('keyMap', 'default'); - cm.setOption('disableInput', false); - cm.off('cursorActivity', onCursorActivity); - CodeMirror.off(cm.getInputField(), 'paste', getOnPasteFn(cm)); - cm.state.vim = null; + function lookupKey(e) { + var keyCode = e.keyCode; + if (modifierCodes.indexOf(keyCode) != -1) { return; } + var hasModifier = e.ctrlKey || e.metaKey; + var key = CodeMirror.keyNames[keyCode]; + key = specialKey[key] || key; + var name = ''; + if (e.ctrlKey) { name += 'C-'; } + if (e.altKey) { name += 'A-'; } + if (mac && e.metaKey || (!hasModifier && e.shiftKey) && key.length < 2) { + // Shift key bindings can only specified for special characters. + return; + } else if (e.shiftKey && !/^[A-Za-z]$/.test(key)) { + name += 'S-'; } + if (key.length == 1) { key = key.toLowerCase(); } + name += key; + if (name.length > 1) { name = '<' + name + '>'; } + return name; + } + // Keys with modifiers are handled using keydown due to limitations of + // keypress event. + function handleKeyDown(cm, e) { + var name = lookupKey(e); + if (!name) { return; } + + CodeMirror.signal(cm, 'vim-keypress', name); + if (CodeMirror.Vim.handleKey(cm, name, 'user')) { + CodeMirror.e_stop(e); + } + } + // Keys without modifiers are handled using keypress to work best with + // non-standard keyboard layouts. + function handleKeyPress(cm, e) { + var code = e.charCode || e.keyCode; + if (e.ctrlKey || e.metaKey || e.altKey || + e.shiftKey && code < 32) { return; } + var name = String.fromCharCode(code); + + CodeMirror.signal(cm, 'vim-keypress', name); + if (CodeMirror.Vim.handleKey(cm, name, 'user')) { + CodeMirror.e_stop(e); + } + } + + function enterVimMode(cm) { + cm.setOption('disableInput', true); + cm.setOption('showCursorWhenSelecting', false); + CodeMirror.signal(cm, "vim-mode-change", {mode: "normal"}); + cm.on('cursorActivity', onCursorActivity); + maybeInitVimState(cm); + CodeMirror.on(cm.getInputField(), 'paste', getOnPasteFn(cm)); + cm.on('keypress', handleKeyPress); + cm.on('keydown', handleKeyDown); + } + + function leaveVimMode(cm) { + cm.setOption('disableInput', false); + cm.off('cursorActivity', onCursorActivity); + CodeMirror.off(cm.getInputField(), 'paste', getOnPasteFn(cm)); + cm.state.vim = null; + cm.off('keypress', handleKeyPress); + cm.off('keydown', handleKeyDown); + } + + function detachVimMap(cm, next) { + if (this == CodeMirror.keyMap.vim) + CodeMirror.rmClass(cm.getWrapperElement(), "cm-fat-cursor"); + + if (!next || next.attach != attachVimMap) + leaveVimMode(cm, false); + } + function attachVimMap(cm, prev) { + if (this == CodeMirror.keyMap.vim) + CodeMirror.addClass(cm.getWrapperElement(), "cm-fat-cursor"); + + if (!prev || prev.attach != attachVimMap) + enterVimMode(cm); + } + + // Deprecated, simply setting the keymap works again. + CodeMirror.defineOption('vimMode', false, function(cm, val, prev) { + if (val && cm.getOption("keyMap") != "vim") + cm.setOption("keyMap", "vim"); + else if (!val && prev != CodeMirror.Init && /^vim/.test(cm.getOption("keyMap"))) + cm.setOption("keyMap", "default"); }); function getOnPasteFn(cm) { var vim = cm.state.vim; @@ -1772,9 +1724,6 @@ CodeMirror.multiplexingMode = function(outer /*, others */) { var upperCaseAlphabet = makeKeyRange(65, 26); var lowerCaseAlphabet = makeKeyRange(97, 26); var numbers = makeKeyRange(48, 10); - var specialSymbols = '~`!@#$%^&*()_-+=[{}]\\|/?.,<>:;"\''.split(''); - var specialKeys = ['Left', 'Right', 'Up', 'Down', 'Space', 'Backspace', - 'Esc', 'Home', 'End', 'PageUp', 'PageDown', 'Enter']; var validMarks = [].concat(upperCaseAlphabet, lowerCaseAlphabet, numbers, ['<', '>']); var validRegisters = [].concat(upperCaseAlphabet, lowerCaseAlphabet, numbers, ['-', '"', '.', ':', '/']); @@ -1992,8 +1941,8 @@ CodeMirror.multiplexingMode = function(outer /*, others */) { visualBlock: false, lastSelection: null, lastPastedText: null, - // Used by two-character ESC keymap routines. Should not be changed from false here. - awaitingEscapeSecondCharacter: false + sel: { + } }; } return cm.state.vim; @@ -2023,6 +1972,7 @@ CodeMirror.multiplexingMode = function(outer /*, others */) { } } + var lastInsertModeKeyTimer; var vimApi= { buildKeyMap: function() { // TODO: Convert keymap into dictionary format for fast lookup. @@ -2060,58 +2010,121 @@ CodeMirror.multiplexingMode = function(outer /*, others */) { }, // This is the outermost function called by CodeMirror, after keys have // been mapped to their Vim equivalents. - handleKey: function(cm, key) { - var command; + handleKey: function(cm, key, origin) { var vim = maybeInitVimState(cm); - var macroModeState = vimGlobalState.macroModeState; - if (macroModeState.isRecording) { - if (key == 'q') { - macroModeState.exitMacroRecordMode(); - clearInputState(cm); - return; + function handleMacroRecording() { + var macroModeState = vimGlobalState.macroModeState; + if (macroModeState.isRecording) { + if (key == 'q') { + macroModeState.exitMacroRecordMode(); + clearInputState(cm); + return true; + } + if (origin != 'mapping') { + logKey(macroModeState, key); + } } } - if (key == '') { - // Clear input state and get back to normal mode. - clearInputState(cm); - if (vim.visualMode) { - exitVisualMode(cm); + function handleEsc() { + if (key == '') { + // Clear input state and get back to normal mode. + clearInputState(cm); + if (vim.visualMode) { + exitVisualMode(cm); + } else if (vim.insertMode) { + exitInsertMode(cm); + } + return true; } - return; } - // Enter visual mode when the mouse selects text. - if (!vim.visualMode && - !cursorEqual(cm.getCursor('head'), cm.getCursor('anchor'))) { - vim.visualMode = true; - vim.visualLine = false; - CodeMirror.signal(cm, "vim-mode-change", {mode: "visual"}); - cm.on('mousedown', exitVisualMode); - } - if (key != '0' || (key == '0' && vim.inputState.getRepeat() === 0)) { - // Have to special case 0 since it's both a motion and a number. - command = commandDispatcher.matchCommand(key, defaultKeymap, vim); - } - if (!command) { - if (isNumber(key)) { - // Increment count unless count is 0 and key is 0. - vim.inputState.pushRepeatDigit(key); + function doKeyToKey(keys) { + // TODO: prevent infinite recursion. + var match; + while (keys) { + // Pull off one command key, which is either a single character + // or a special sequence wrapped in '<' and '>', e.g. ''. + match = (/<\w+-.+?>|<\w+>|./).exec(keys); + key = match[0]; + keys = keys.substring(match.index + key.length); + CodeMirror.Vim.handleKey(cm, key, 'mapping'); + } + } + + function handleKeyInsertMode() { + if (handleEsc()) { return true; } + var keys = vim.inputState.keyBuffer = vim.inputState.keyBuffer + key; + var keysAreChars = key.length == 1; + var match = commandDispatcher.matchCommand(keys, defaultKeymap, vim.inputState, 'insert'); + // Need to check all key substrings in insert mode. + while (keys.length > 1 && match.type != 'full') { + var keys = vim.inputState.keyBuffer = keys.slice(1); + var thisMatch = commandDispatcher.matchCommand(keys, defaultKeymap, vim.inputState, 'insert'); + if (thisMatch.type != 'none') { match = thisMatch; } + } + if (match.type == 'none') { clearInputState(cm); return false; } + else if (match.type == 'partial') { + if (lastInsertModeKeyTimer) { window.clearTimeout(lastInsertModeKeyTimer); } + lastInsertModeKeyTimer = window.setTimeout( + function() { if (vim.insertMode && vim.inputState.keyBuffer) { clearInputState(cm); } }, + getOption('insertModeEscKeysTimeout')); + return !keysAreChars; } - if (macroModeState.isRecording) { - logKey(macroModeState, key); + + if (lastInsertModeKeyTimer) { window.clearTimeout(lastInsertModeKeyTimer); } + if (keysAreChars) { + var here = cm.getCursor(); + cm.replaceRange('', offsetCursor(here, 0, -(keys.length - 1)), here, '+input'); } - return; + clearInputState(cm); + var command = match.command; + if (command.type == 'keyToKey') { + doKeyToKey(command.toKeys); + } else { + commandDispatcher.processCommand(cm, vim, command); + } + return true; } - if (command.type == 'keyToKey') { - // TODO: prevent infinite recursion. - for (var i = 0; i < command.toKeys.length; i++) { - this.handleKey(cm, command.toKeys[i]); + + function handleKeyNonInsertMode() { + if (handleMacroRecording() || handleEsc()) { return true; }; + + var keys = vim.inputState.keyBuffer = vim.inputState.keyBuffer + key; + if (/^[1-9]\d*$/.test(keys)) { return true; } + + var keysMatcher = /^(\d*)(.*)$/.exec(keys); + if (!keysMatcher) { clearInputState(cm); return false; } + var context = vim.visualMode ? 'visual' : + 'normal'; + var match = commandDispatcher.matchCommand(keysMatcher[2] || keysMatcher[1], defaultKeymap, vim.inputState, context); + if (match.type == 'none') { clearInputState(cm); return false; } + else if (match.type == 'partial') { return true; } + + vim.inputState.keyBuffer = ''; + var command = match.command; + var keysMatcher = /^(\d*)(.*)$/.exec(keys); + if (keysMatcher[1] && keysMatcher[1] != '0') { + vim.inputState.pushRepeatDigit(keysMatcher[1]); } - } else { - if (macroModeState.isRecording) { - logKey(macroModeState, key); + if (command.type == 'keyToKey') { + doKeyToKey(command.toKeys); + } else { + commandDispatcher.processCommand(cm, vim, command); } - commandDispatcher.processCommand(cm, vim, command); + return true; } + + return cm.operation(function() { + cm.curOp.isVimOp = true; + try { + if (vim.insertMode) { return handleKeyInsertMode(); } + else { return handleKeyNonInsertMode(); } + } catch (e) { + // clear VIM state in case it's in a bad state. + cm.state.vim = undefined; + maybeInitVimState(cm); + throw e; + } + }); }, handleEx: function(cm, input) { exCommandDispatcher.processCommand(cm, input); @@ -2328,83 +2341,25 @@ CodeMirror.multiplexingMode = function(outer /*, others */) { } }; var commandDispatcher = { - matchCommand: function(key, keyMap, vim) { - var inputState = vim.inputState; - var keys = inputState.keyBuffer.concat(key); - var matchedCommands = []; - var selectedCharacter; - for (var i = 0; i < keyMap.length; i++) { - var command = keyMap[i]; - if (matchKeysPartial(keys, command.keys)) { - if (inputState.operator && command.type == 'action') { - // Ignore matched action commands after an operator. Operators - // only operate on motions. This check is really for text - // objects since aW, a[ etcs conflicts with a. - continue; - } - // Match commands that take as an argument. - if (command.keys[keys.length - 1] == 'character') { - selectedCharacter = keys[keys.length - 1]; - if (selectedCharacter.length>1){ - switch(selectedCharacter){ - case '': - selectedCharacter='\n'; - break; - case '': - selectedCharacter=' '; - break; - default: - continue; - } - } - } - // Add the command to the list of matched commands. Choose the best - // command later. - matchedCommands.push(command); - } + matchCommand: function(keys, keyMap, inputState, context) { + var matches = commandMatches(keys, keyMap, context, inputState); + if (!matches.full && !matches.partial) { + return {type: 'none'}; + } else if (!matches.full && matches.partial) { + return {type: 'partial'}; } - // Returns the command if it is a full match, or null if not. - function getFullyMatchedCommandOrNull(command) { - if (keys.length < command.keys.length) { - // Matches part of a multi-key command. Buffer and wait for next - // stroke. - inputState.keyBuffer.push(key); - return null; - } else { - if (command.keys[keys.length - 1] == 'character') { - inputState.selectedCharacter = selectedCharacter; - } - // Clear the buffer since a full match was found. - inputState.keyBuffer = []; - return command; + var bestMatch; + for (var i = 0; i < matches.full.length; i++) { + var match = matches.full[i]; + if (!bestMatch) { + bestMatch = match; } } - - if (!matchedCommands.length) { - // Clear the buffer since there were no matches. - inputState.keyBuffer = []; - return null; - } else if (matchedCommands.length == 1) { - return getFullyMatchedCommandOrNull(matchedCommands[0]); - } else { - // Find the best match in the list of matchedCommands. - var context = vim.visualMode ? 'visual' : 'normal'; - var bestMatch; // Default to first in the list. - for (var i = 0; i < matchedCommands.length; i++) { - var current = matchedCommands[i]; - if (current.context == context) { - bestMatch = current; - break; - } else if (!bestMatch && !current.context) { - // Only set an imperfect match to best match if no best match is - // set and the imperfect match is not restricted to another - // context. - bestMatch = current; - } - } - return getFullyMatchedCommandOrNull(bestMatch); + if (bestMatch.keys.slice(-11) == '') { + inputState.selectedCharacter = lastChar(keys); } + return {type: 'full', command: bestMatch}; }, processCommand: function(cm, vim, command) { vim.inputState.repeatOverride = command.repeatOverride; @@ -2423,10 +2378,12 @@ CodeMirror.multiplexingMode = function(outer /*, others */) { break; case 'search': this.processSearch(cm, vim, command); + clearInputState(cm); break; case 'ex': case 'keyToEx': this.processEx(cm, vim, command); + clearInputState(cm); break; default: break; @@ -2668,13 +2625,13 @@ CodeMirror.multiplexingMode = function(outer /*, others */) { var operator = inputState.operator; var operatorArgs = inputState.operatorArgs || {}; var registerName = inputState.registerName; - var selectionEnd = copyCursor(cm.getCursor('head')); - var selectionStart = copyCursor(cm.getCursor('anchor')); - // The difference between cur and selection cursors are that cur is - // being operated on and ignores that there is a selection. - var curStart = copyCursor(selectionEnd); - var curOriginal = copyCursor(curStart); - var curEnd; + var sel = vim.sel; + // TODO: Make sure cm and vim selections are identical outside visual mode. + var origHead = copyCursor(vim.visualMode ? sel.head: cm.getCursor('head')); + var origAnchor = copyCursor(vim.visualMode ? sel.anchor : cm.getCursor('anchor')); + var oldHead = copyCursor(origHead); + var oldAnchor = copyCursor(origAnchor); + var newHead, newAnchor; var repeat; if (operator) { this.recordLastEdit(vim, inputState); @@ -2701,7 +2658,7 @@ CodeMirror.multiplexingMode = function(outer /*, others */) { motionArgs.repeat = repeat; clearInputState(cm); if (motion) { - var motionResult = motions[motion](cm, motionArgs, vim); + var motionResult = motions[motion](cm, origHead, motionArgs, vim); vim.lastMotion = motions[motion]; if (!motionResult) { return; @@ -2714,159 +2671,139 @@ CodeMirror.multiplexingMode = function(outer /*, others */) { recordJumpPosition(cm, cachedCursor, motionResult); delete jumpList.cachedCursor; } else { - recordJumpPosition(cm, curOriginal, motionResult); + recordJumpPosition(cm, origHead, motionResult); } } if (motionResult instanceof Array) { - curStart = motionResult[0]; - curEnd = motionResult[1]; + newAnchor = motionResult[0]; + newHead = motionResult[1]; } else { - curEnd = motionResult; + newHead = motionResult; } // TODO: Handle null returns from motion commands better. - if (!curEnd) { - curEnd = Pos(curStart.line, curStart.ch); + if (!newHead) { + newHead = copyCursor(origHead); } if (vim.visualMode) { - // Check if the selection crossed over itself. Will need to shift - // the start point if that happened. - // offset is set to -1 or 1 to shift the curEnd - // left or right - var offset = 0; - if (cursorIsBefore(selectionStart, selectionEnd) && - (cursorEqual(selectionStart, curEnd) || - cursorIsBefore(curEnd, selectionStart))) { - // The end of the selection has moved from after the start to - // before the start. We will shift the start right by 1. - selectionStart.ch += 1; - offset = -1; - } else if (cursorIsBefore(selectionEnd, selectionStart) && - (cursorEqual(selectionStart, curEnd) || - cursorIsBefore(selectionStart, curEnd))) { - // The opposite happened. We will shift the start left by 1. - selectionStart.ch -= 1; - offset = 1; - } - // in case of visual Block selectionStart and curEnd - // may not be on the same line, - // Also, In case of v_o this should not happen. - if (!vim.visualBlock && !(motionResult instanceof Array)) { - curEnd.ch += offset; - } - if (vim.lastHPos != Infinity) { - vim.lastHPos = curEnd.ch; - } - selectionEnd = curEnd; - selectionStart = (motionResult instanceof Array) ? curStart : selectionStart; - if (vim.visualLine) { - if (cursorIsBefore(selectionStart, selectionEnd)) { - selectionStart.ch = 0; - - var lastLine = cm.lastLine(); - if (selectionEnd.line > lastLine) { - selectionEnd.line = lastLine; - } - selectionEnd.ch = lineLength(cm, selectionEnd.line); - } else { - selectionEnd.ch = 0; - selectionStart.ch = lineLength(cm, selectionStart.line); - } - } else if (vim.visualBlock) { - // Select a block and - // return the diagonally opposite end. - selectionStart = selectBlock(cm, selectionEnd); - } - if (!vim.visualBlock) { - cm.setSelection(selectionStart, selectionEnd); + newHead = clipCursorToContent(cm, newHead, vim.visualBlock); + if (newAnchor) { + newAnchor = clipCursorToContent(cm, newAnchor, true); } + newAnchor = newAnchor || oldAnchor; + sel.anchor = newAnchor; + sel.head = newHead; + updateCmSelection(cm); updateMark(cm, vim, '<', - cursorIsBefore(selectionStart, selectionEnd) ? selectionStart - : selectionEnd); + cursorIsBefore(newAnchor, newHead) ? newAnchor + : newHead); updateMark(cm, vim, '>', - cursorIsBefore(selectionStart, selectionEnd) ? selectionEnd - : selectionStart); + cursorIsBefore(newAnchor, newHead) ? newHead + : newAnchor); } else if (!operator) { - curEnd = clipCursorToContent(cm, curEnd); - cm.setCursor(curEnd.line, curEnd.ch); + newHead = clipCursorToContent(cm, newHead); + cm.setCursor(newHead.line, newHead.ch); } } - if (operator) { - var inverted = false; - vim.lastMotion = null; - var lastSelection = vim.lastSelection; - operatorArgs.repeat = repeat; // Indent in visual mode needs this. - if (vim.visualMode) { - curStart = selectionStart; - curEnd = selectionEnd; - motionArgs.inclusive = true; - operatorArgs.shouldMoveCursor = false; - } - // Swap start and end if motion was backward. - if (curEnd && cursorIsBefore(curEnd, curStart)) { - var tmp = curStart; - curStart = curEnd; - curEnd = tmp; - inverted = true; - } else if (!curEnd) { - curEnd = copyCursor(curStart); - } - if (motionArgs.inclusive && !vim.visualMode) { - // Move the selection end one to the right to include the last - // character. - curEnd.ch++; - } - if (operatorArgs.selOffset) { + if (operatorArgs.lastSel) { // Replaying a visual mode operation - curEnd.line = curStart.line + operatorArgs.selOffset.line; - if (operatorArgs.selOffset.line) {curEnd.ch = operatorArgs.selOffset.ch; } - else { curEnd.ch = curStart.ch + operatorArgs.selOffset.ch; } - // In case of blockwise visual - if (lastSelection && lastSelection.visualBlock) { - var block = lastSelection.visualBlock; - var width = block.width; - var height = block.height; - curEnd = Pos(curStart.line + height, curStart.ch + width); - // selectBlock creates a 'proper' rectangular block. - // We do not want that in all cases, so we manually set selections. - var selections = []; - for (var i = curStart.line; i < curEnd.line; i++) { - var anchor = Pos(i, curStart.ch); - var head = Pos(i, curEnd.ch); - var range = {anchor: anchor, head: head}; - selections.push(range); - } - cm.setSelections(selections); - var blockSelected = true; + newAnchor = oldAnchor; + var lastSel = operatorArgs.lastSel; + var lineOffset = Math.abs(lastSel.head.line - lastSel.anchor.line); + var chOffset = Math.abs(lastSel.head.ch - lastSel.anchor.ch); + if (lastSel.visualLine) { + // Linewise Visual mode: The same number of lines. + newHead = Pos(oldAnchor.line + lineOffset, oldAnchor.ch); + } else if (lastSel.visualBlock) { + // Blockwise Visual mode: The same number of lines and columns. + newHead = Pos(oldAnchor.line + lineOffset, oldAnchor.ch + chOffset); + } else if (lastSel.head.line == lastSel.anchor.line) { + // Normal Visual mode within one line: The same number of characters. + newHead = Pos(oldAnchor.line, oldAnchor.ch + chOffset); + } else { + // Normal Visual mode with several lines: The same number of lines, in the + // last line the same number of characters as in the last line the last time. + newHead = Pos(oldAnchor.line + lineOffset, oldAnchor.ch); } + vim.visualMode = true; + vim.visualLine = lastSel.visualLine; + vim.visualBlock = lastSel.visualBlock; + sel = vim.sel = { + anchor: newAnchor, + head: newHead + }; + updateCmSelection(cm); } else if (vim.visualMode) { - var selOffset = Pos(); - selOffset.line = curEnd.line - curStart.line; - if (selOffset.line) { selOffset.ch = curEnd.ch; } - else { selOffset.ch = curEnd.ch - curStart.ch; } - operatorArgs.selOffset = selOffset; - } - var linewise = motionArgs.linewise || - (vim.visualMode && vim.visualLine) || - operatorArgs.linewise; - if (linewise) { - // Expand selection to entire line. - expandSelectionToLine(cm, curStart, curEnd); - } else if (motionArgs.forward) { - // Clip to trailing newlines only if the motion goes forward. - clipToLine(cm, curStart, curEnd); + operatorArgs.lastSel = { + anchor: copyCursor(sel.anchor), + head: copyCursor(sel.head), + visualBlock: vim.visualBlock, + visualLine: vim.visualLine + }; } + var curStart, curEnd, linewise, mode; + var cmSel; + if (vim.visualMode) { + // Init visual op + curStart = cursorMin(sel.head, sel.anchor); + curEnd = cursorMax(sel.head, sel.anchor); + linewise = vim.visualLine || operatorArgs.linewise; + mode = vim.visualBlock ? 'block' : + linewise ? 'line' : + 'char'; + cmSel = makeCmSelection(cm, { + anchor: curStart, + head: curEnd + }, mode); + if (linewise) { + var ranges = cmSel.ranges; + if (mode == 'block') { + // Linewise operators in visual block mode extend to end of line + for (var i = 0; i < ranges.length; i++) { + ranges[i].head.ch = lineLength(cm, ranges[i].head.line); + } + } else if (mode == 'line') { + ranges[0].head = Pos(ranges[0].head.line + 1, 0); + } + } + } else { + // Init motion op + curStart = copyCursor(newAnchor || oldAnchor); + curEnd = copyCursor(newHead || oldHead); + if (cursorIsBefore(curEnd, curStart)) { + var tmp = curStart; + curStart = curEnd; + curEnd = tmp; + } + linewise = motionArgs.linewise || operatorArgs.linewise; + if (linewise) { + // Expand selection to entire line. + expandSelectionToLine(cm, curStart, curEnd); + } else if (motionArgs.forward) { + // Clip to trailing newlines only if the motion goes forward. + clipToLine(cm, curStart, curEnd); + } + mode = 'char'; + var exclusive = !motionArgs.inclusive || linewise; + cmSel = makeCmSelection(cm, { + anchor: curStart, + head: curEnd + }, mode, exclusive); + } + cm.setSelections(cmSel.ranges, cmSel.primary); + vim.lastMotion = null; + operatorArgs.repeat = repeat; // For indent in visual mode. operatorArgs.registerName = registerName; // Keep track of linewise as it affects how paste and change behave. operatorArgs.linewise = linewise; - if (!vim.visualBlock && !blockSelected) { - cm.setSelection(curStart, curEnd); - } - operators[operator](cm, operatorArgs, vim, curStart, - curEnd, curOriginal); + var operatorMoveTo = operators[operator]( + cm, operatorArgs, cmSel.ranges, oldAnchor, newHead); if (vim.visualMode) { exitVisualMode(cm); } + if (operatorMoveTo) { + cm.setCursor(operatorMoveTo); + } } }, recordLastEdit: function(vim, inputState, actionCommand) { @@ -2885,7 +2822,7 @@ CodeMirror.multiplexingMode = function(outer /*, others */) { */ // All of the functions below return Cursor objects. var motions = { - moveToTopLine: function(cm, motionArgs) { + moveToTopLine: function(cm, _head, motionArgs) { var line = getUserVisibleLines(cm).top + motionArgs.repeat -1; return Pos(line, findFirstNonWhiteSpaceCharacter(cm.getLine(line))); }, @@ -2894,17 +2831,17 @@ CodeMirror.multiplexingMode = function(outer /*, others */) { var line = Math.floor((range.top + range.bottom) * 0.5); return Pos(line, findFirstNonWhiteSpaceCharacter(cm.getLine(line))); }, - moveToBottomLine: function(cm, motionArgs) { + moveToBottomLine: function(cm, _head, motionArgs) { var line = getUserVisibleLines(cm).bottom - motionArgs.repeat +1; return Pos(line, findFirstNonWhiteSpaceCharacter(cm.getLine(line))); }, - expandToLine: function(cm, motionArgs) { + expandToLine: function(_cm, head, motionArgs) { // Expands forward to end of line, and then to next line if repeat is // >1. Does not handle backward motion! - var cur = cm.getCursor(); + var cur = head; return Pos(cur.line + motionArgs.repeat - 1, Infinity); }, - findNext: function(cm, motionArgs) { + findNext: function(cm, _head, motionArgs) { var state = getSearchState(cm); var query = state.getQuery(); if (!query) { @@ -2916,7 +2853,7 @@ CodeMirror.multiplexingMode = function(outer /*, others */) { highlightSearchMatches(cm, query); return findNext(cm, prev/** prev */, query, motionArgs.repeat); }, - goToMark: function(cm, motionArgs, vim) { + goToMark: function(cm, _head, motionArgs, vim) { var mark = vim.marks[motionArgs.selectedCharacter]; if (mark) { var pos = mark.find(); @@ -2924,22 +2861,19 @@ CodeMirror.multiplexingMode = function(outer /*, others */) { } return null; }, - moveToOtherHighlightedEnd: function(cm, motionArgs, vim) { - var ranges = cm.listSelections(); - var curEnd = cm.getCursor('head'); - var curStart = ranges[0].anchor; - var curIndex = cursorEqual(ranges[0].head, curEnd) ? ranges.length-1 : 0; - if (motionArgs.sameLine && vim.visualBlock) { - curStart = Pos(curEnd.line, ranges[curIndex].anchor.ch); - curEnd = Pos(ranges[curIndex].head.line, curEnd.ch); + moveToOtherHighlightedEnd: function(cm, _head, motionArgs, vim) { + if (vim.visualBlock && motionArgs.sameLine) { + var sel = vim.sel; + return [ + clipCursorToContent(cm, Pos(sel.anchor.line, sel.head.ch)), + clipCursorToContent(cm, Pos(sel.head.line, sel.anchor.ch)) + ]; } else { - curStart = ranges[curIndex].anchor; + return ([vim.sel.head, vim.sel.anchor]); } - cm.setCursor(curEnd); - return ([curEnd, curStart]); }, - jumpToMark: function(cm, motionArgs, vim) { - var best = cm.getCursor(); + jumpToMark: function(cm, head, motionArgs, vim) { + var best = head; for (var i = 0; i < motionArgs.repeat; i++) { var cursor = best; for (var key in vim.marks) { @@ -2959,8 +2893,8 @@ CodeMirror.multiplexingMode = function(outer /*, others */) { var equal = cursorEqual(cursor, best); var between = (motionArgs.forward) ? - cusrorIsBetween(cursor, mark, best) : - cusrorIsBetween(best, mark, cursor); + cursorIsBetween(cursor, mark, best) : + cursorIsBetween(best, mark, cursor); if (equal || between) { best = mark; @@ -2976,14 +2910,14 @@ CodeMirror.multiplexingMode = function(outer /*, others */) { } return best; }, - moveByCharacters: function(cm, motionArgs) { - var cur = cm.getCursor(); + moveByCharacters: function(_cm, head, motionArgs) { + var cur = head; var repeat = motionArgs.repeat; var ch = motionArgs.forward ? cur.ch + repeat : cur.ch - repeat; return Pos(cur.line, ch); }, - moveByLines: function(cm, motionArgs, vim) { - var cur = cm.getCursor(); + moveByLines: function(cm, head, motionArgs, vim) { + var cur = head; var endCh = cur.ch; // Depending what our last motion was, we may want to do different // things. If our last motion was moving vertically, we want to @@ -3018,8 +2952,8 @@ CodeMirror.multiplexingMode = function(outer /*, others */) { vim.lastHSPos = cm.charCoords(Pos(line, endCh),'div').left; return Pos(line, endCh); }, - moveByDisplayLines: function(cm, motionArgs, vim) { - var cur = cm.getCursor(); + moveByDisplayLines: function(cm, head, motionArgs, vim) { + var cur = head; switch (vim.lastMotion) { case this.moveByDisplayLines: case this.moveByScroll: @@ -3046,16 +2980,16 @@ CodeMirror.multiplexingMode = function(outer /*, others */) { vim.lastHPos = res.ch; return res; }, - moveByPage: function(cm, motionArgs) { + moveByPage: function(cm, head, motionArgs) { // CodeMirror only exposes functions that move the cursor page down, so // doing this bad hack to move the cursor and move it back. evalInput // will move the cursor to where it should be in the end. - var curStart = cm.getCursor(); + var curStart = head; var repeat = motionArgs.repeat; return cm.findPosV(curStart, (motionArgs.forward ? repeat : -repeat), 'page'); }, - moveByParagraph: function(cm, motionArgs) { - var line = cm.getCursor().line; + moveByParagraph: function(cm, head, motionArgs) { + var line = head.line; var repeat = motionArgs.repeat; var inc = motionArgs.forward ? 1 : -1; for (var i = 0; i < repeat; i++) { @@ -3070,16 +3004,16 @@ CodeMirror.multiplexingMode = function(outer /*, others */) { } return Pos(line, 0); }, - moveByScroll: function(cm, motionArgs, vim) { + moveByScroll: function(cm, head, motionArgs, vim) { var scrollbox = cm.getScrollInfo(); var curEnd = null; var repeat = motionArgs.repeat; if (!repeat) { repeat = scrollbox.clientHeight / (2 * cm.defaultTextHeight()); } - var orig = cm.charCoords(cm.getCursor(), 'local'); + var orig = cm.charCoords(head, 'local'); motionArgs.repeat = repeat; - var curEnd = motions.moveByDisplayLines(cm, motionArgs, vim); + var curEnd = motions.moveByDisplayLines(cm, head, motionArgs, vim); if (!curEnd) { return null; } @@ -3087,11 +3021,11 @@ CodeMirror.multiplexingMode = function(outer /*, others */) { cm.scrollTo(null, scrollbox.top + dest.top - orig.top); return curEnd; }, - moveByWords: function(cm, motionArgs) { - return moveToWord(cm, motionArgs.repeat, !!motionArgs.forward, + moveByWords: function(cm, head, motionArgs) { + return moveToWord(cm, head, motionArgs.repeat, !!motionArgs.forward, !!motionArgs.wordEnd, !!motionArgs.bigWord); }, - moveTillCharacter: function(cm, motionArgs) { + moveTillCharacter: function(cm, _head, motionArgs) { var repeat = motionArgs.repeat; var curEnd = moveToCharacter(cm, repeat, motionArgs.forward, motionArgs.selectedCharacter); @@ -3101,26 +3035,26 @@ CodeMirror.multiplexingMode = function(outer /*, others */) { curEnd.ch += increment; return curEnd; }, - moveToCharacter: function(cm, motionArgs) { + moveToCharacter: function(cm, head, motionArgs) { var repeat = motionArgs.repeat; recordLastCharacterSearch(0, motionArgs); return moveToCharacter(cm, repeat, motionArgs.forward, - motionArgs.selectedCharacter) || cm.getCursor(); + motionArgs.selectedCharacter) || head; }, - moveToSymbol: function(cm, motionArgs) { + moveToSymbol: function(cm, head, motionArgs) { var repeat = motionArgs.repeat; return findSymbol(cm, repeat, motionArgs.forward, - motionArgs.selectedCharacter) || cm.getCursor(); + motionArgs.selectedCharacter) || head; }, - moveToColumn: function(cm, motionArgs, vim) { + moveToColumn: function(cm, head, motionArgs, vim) { var repeat = motionArgs.repeat; // repeat is equivalent to which column we want to move to! vim.lastHPos = repeat - 1; - vim.lastHSPos = cm.charCoords(cm.getCursor(),'div').left; + vim.lastHSPos = cm.charCoords(head,'div').left; return moveToColumn(cm, repeat); }, - moveToEol: function(cm, motionArgs, vim) { - var cur = cm.getCursor(); + moveToEol: function(cm, head, motionArgs, vim) { + var cur = head; vim.lastHPos = Infinity; var retval= Pos(cur.line + motionArgs.repeat - 1, Infinity); var end=cm.clipPos(retval); @@ -3128,15 +3062,15 @@ CodeMirror.multiplexingMode = function(outer /*, others */) { vim.lastHSPos = cm.charCoords(end,'div').left; return retval; }, - moveToFirstNonWhiteSpaceCharacter: function(cm) { + moveToFirstNonWhiteSpaceCharacter: function(cm, head) { // Go to the start of the line where the text begins, or the end for // whitespace-only lines - var cursor = cm.getCursor(); + var cursor = head; return Pos(cursor.line, findFirstNonWhiteSpaceCharacter(cm.getLine(cursor.line))); }, - moveToMatchedSymbol: function(cm) { - var cursor = cm.getCursor(); + moveToMatchedSymbol: function(cm, head) { + var cursor = head; var line = cursor.line; var ch = cursor.ch; var lineText = cm.getLine(line); @@ -3157,11 +3091,10 @@ CodeMirror.multiplexingMode = function(outer /*, others */) { return cursor; } }, - moveToStartOfLine: function(cm) { - var cursor = cm.getCursor(); - return Pos(cursor.line, 0); + moveToStartOfLine: function(_cm, head) { + return Pos(head.line, 0); }, - moveToLineOrEdgeOfDocument: function(cm, motionArgs) { + moveToLineOrEdgeOfDocument: function(cm, _head, motionArgs) { var lineNum = motionArgs.forward ? cm.lastLine() : cm.firstLine(); if (motionArgs.repeatIsExplicit) { lineNum = motionArgs.repeat - cm.getOption('firstLineNumber'); @@ -3169,7 +3102,7 @@ CodeMirror.multiplexingMode = function(outer /*, others */) { return Pos(lineNum, findFirstNonWhiteSpaceCharacter(cm.getLine(lineNum))); }, - textObjectManipulation: function(cm, motionArgs) { + textObjectManipulation: function(cm, head, motionArgs) { // TODO: lots of possible exceptions that can be thrown here. Try da( // outside of a () block. @@ -3198,9 +3131,9 @@ CodeMirror.multiplexingMode = function(outer /*, others */) { var tmp; if (mirroredPairs[character]) { - tmp = selectCompanionObject(cm, character, inclusive); + tmp = selectCompanionObject(cm, head, character, inclusive); } else if (selfPaired[character]) { - tmp = findBeginningAndEnd(cm, character, inclusive); + tmp = findBeginningAndEnd(cm, head, character, inclusive); } else if (character === 'W') { tmp = expandWordUnderCursor(cm, inclusive, true /** forward */, true /** bigWord */); @@ -3212,10 +3145,14 @@ CodeMirror.multiplexingMode = function(outer /*, others */) { return null; } - return [tmp.start, tmp.end]; + if (!cm.state.vim.visualMode) { + return [tmp.start, tmp.end]; + } else { + return expandSelection(cm, tmp.start, tmp.end); + } }, - repeatLastCharacterSearch: function(cm, motionArgs) { + repeatLastCharacterSearch: function(cm, head, motionArgs) { var lastSearch = vimGlobalState.lastChararacterSearch; var repeat = motionArgs.repeat; var forward = motionArgs.forward === lastSearch.forward; @@ -3225,133 +3162,107 @@ CodeMirror.multiplexingMode = function(outer /*, others */) { var curEnd = moveToCharacter(cm, repeat, forward, lastSearch.selectedCharacter); if (!curEnd) { cm.moveH(increment, 'char'); - return cm.getCursor(); + return head; } curEnd.ch += increment; return curEnd; } }; + function fillArray(val, times) { + var arr = []; + for (var i = 0; i < times; i++) { + arr.push(val); + } + return arr; + } + /** + * An operator acts on a text selection. It receives the list of selections + * as input. The corresponding CodeMirror selection is guaranteed to + * match the input selection. + */ var operators = { - change: function(cm, operatorArgs, vim) { - var selections = cm.listSelections(); - var start = selections[0], end = selections[selections.length-1]; - var curStart = cursorIsBefore(start.anchor, start.head) ? start.anchor : start.head; - var curEnd = cursorIsBefore(end.anchor, end.head) ? end.head : end.anchor; - var text = cm.getSelection(); - var visualBlock = vim.visualBlock; - if (vim.lastSelection && !vim.visualMode) { - visualBlock = vim.lastSelection.visualBlock ? true : visualBlock; - } - var lastInsertModeChanges = vimGlobalState.macroModeState.lastInsertModeChanges; - lastInsertModeChanges.inVisualBlock = visualBlock; - var replacement = new Array(selections.length).join('1').split('1'); - // save the selectionEnd mark - var selectionEnd = vim.marks['>'] ? vim.marks['>'].find() : cm.getCursor('head'); - vimGlobalState.registerController.pushText( - operatorArgs.registerName, 'change', text, - operatorArgs.linewise); - if (operatorArgs.linewise) { - // 'C' in visual block extends the block till eol for all lines - if (visualBlock){ - var startLine = curStart.line; - while (startLine <= curEnd.line) { - var endCh = lineLength(cm, startLine); - var head = Pos(startLine, endCh); - var anchor = Pos(startLine, curStart.ch); - startLine++; - cm.replaceRange('', anchor, head); - } - } else { - // Push the next line back down, if there is a next line. - replacement = '\n'; - if (curEnd.line == curStart.line && curEnd.line == cm.lastLine()) { - replacement = ''; - } - cm.replaceRange(replacement, curStart, curEnd); - cm.indentLine(curStart.line, 'smart'); - // null ch so setCursor moves to end of line. - curStart.ch = null; - cm.setCursor(curStart); - } - } else { - // Exclude trailing whitespace if the range is not all whitespace. - var text = cm.getRange(curStart, curEnd); + change: function(cm, args, ranges) { + var finalHead, text; + var vim = cm.state.vim; + vimGlobalState.macroModeState.lastInsertModeChanges.inVisualBlock = vim.visualBlock; + if (!vim.visualMode) { + var anchor = ranges[0].anchor, + head = ranges[0].head; + text = cm.getRange(anchor, head); if (!isWhiteSpaceString(text)) { + // Exclude trailing whitespace if the range is not all whitespace. var match = (/\s+$/).exec(text); if (match) { - curEnd = offsetCursor(curEnd, 0, - match[0].length); + head = offsetCursor(head, 0, - match[0].length); + text = text.slice(0, - match[0].length); } } - if (visualBlock) { - cm.replaceSelections(replacement); - } else { - cm.setCursor(curStart); - cm.replaceRange('', curStart, curEnd); + var wasLastLine = head.line - 1 == cm.lastLine(); + cm.replaceRange('', anchor, head); + if (args.linewise && !wasLastLine) { + // Push the next line back down, if there is a next line. + CodeMirror.commands.newlineAndIndent(cm); + // null ch so setCursor moves to end of line. + anchor.ch = null; } - } - vim.marks['>'] = cm.setBookmark(selectionEnd); - actions.enterInsertMode(cm, {}, cm.state.vim); - }, - // delete is a javascript keyword. - 'delete': function(cm, operatorArgs, vim) { - var selections = cm.listSelections(); - var start = selections[0], end = selections[selections.length-1]; - var curStart = cursorIsBefore(start.anchor, start.head) ? start.anchor : start.head; - var curEnd = cursorIsBefore(end.anchor, end.head) ? end.head : end.anchor; - // Save the '>' mark before cm.replaceRange clears it. - var selectionEnd, selectionStart; - var blockwise = vim.visualBlock; - if (vim.visualMode) { - selectionEnd = vim.marks['>'].find(); - selectionStart = vim.marks['<'].find(); - } else if (vim.lastSelection) { - selectionEnd = vim.lastSelection.curStartMark.find(); - selectionStart = vim.lastSelection.curEndMark.find(); - blockwise = vim.lastSelection.visualBlock; - } - var text = cm.getSelection(); - vimGlobalState.registerController.pushText( - operatorArgs.registerName, 'delete', text, - operatorArgs.linewise, blockwise); - var replacement = new Array(selections.length).join('1').split('1'); - // If the ending line is past the last line, inclusive, instead of - // including the trailing \n, include the \n before the starting line - if (operatorArgs.linewise && - curEnd.line == cm.lastLine() && curStart.line == curEnd.line) { - var tmp = copyCursor(curEnd); - curStart.line--; - curStart.ch = lineLength(cm, curStart.line); - curEnd = tmp; - cm.replaceRange('', curStart, curEnd); + finalHead = anchor; } else { + text = cm.getSelection(); + var replacement = fillArray('', ranges.length); cm.replaceSelections(replacement); + finalHead = cursorMin(ranges[0].head, ranges[0].anchor); } - // restore the saved bookmark - if (selectionEnd) { - var curStartMark = cm.setBookmark(selectionStart); - var curEndMark = cm.setBookmark(selectionEnd); - if (vim.visualMode) { - vim.marks['<'] = curStartMark; - vim.marks['>'] = curEndMark; - } else { - vim.lastSelection.curStartMark = curStartMark; - vim.lastSelection.curEndMark = curEndMark; + vimGlobalState.registerController.pushText( + args.registerName, 'change', text, + args.linewise, ranges.length > 1); + actions.enterInsertMode(cm, {head: finalHead}, cm.state.vim); + }, + // delete is a javascript keyword. + 'delete': function(cm, args, ranges) { + var finalHead, text; + var vim = cm.state.vim; + if (!vim.visualBlock) { + var anchor = ranges[0].anchor, + head = ranges[0].head; + if (args.linewise && + head.line != cm.firstLine() && + anchor.line == cm.lastLine() && + anchor.line == head.line - 1) { + // Special case for dd on last line (and first line). + if (anchor.line == cm.firstLine()) { + anchor.ch = 0; + } else { + anchor = Pos(anchor.line - 1, lineLength(cm, anchor.line - 1)); + } + } + text = cm.getRange(anchor, head); + cm.replaceRange('', anchor, head); + finalHead = anchor; + if (args.linewise) { + finalHead = motions.moveToFirstNonWhiteSpaceCharacter(cm, anchor); } - } - if (operatorArgs.linewise) { - cm.setCursor(motions.moveToFirstNonWhiteSpaceCharacter(cm)); } else { - cm.setCursor(curStart); + text = cm.getSelection(); + var replacement = fillArray('', ranges.length); + cm.replaceSelections(replacement); + finalHead = ranges[0].anchor; } + vimGlobalState.registerController.pushText( + args.registerName, 'delete', text, + args.linewise, vim.visualBlock); + return finalHead; }, - indent: function(cm, operatorArgs, vim, curStart, curEnd) { - var startLine = curStart.line; - var endLine = curEnd.line; + indent: function(cm, args, ranges) { + var vim = cm.state.vim; + var startLine = ranges[0].anchor.line; + var endLine = vim.visualBlock ? + ranges[ranges.length - 1].anchor.line : + ranges[0].head.line; // In visual mode, n> shifts the selection right n times, instead of // shifting n lines right once. - var repeat = (vim.visualMode) ? operatorArgs.repeat : 1; - if (operatorArgs.linewise) { + var repeat = (vim.visualMode) ? args.repeat : 1; + if (args.linewise) { // The only way to delete a newline is to delete until the start of // the next line, so in linewise mode evalInput will include the next // line. We don't want this in indent, so we go back a line. @@ -3359,39 +3270,52 @@ CodeMirror.multiplexingMode = function(outer /*, others */) { } for (var i = startLine; i <= endLine; i++) { for (var j = 0; j < repeat; j++) { - cm.indentLine(i, operatorArgs.indentRight); + cm.indentLine(i, args.indentRight); } } - cm.setCursor(curStart); - cm.setCursor(motions.moveToFirstNonWhiteSpaceCharacter(cm)); + return motions.moveToFirstNonWhiteSpaceCharacter(cm, ranges[0].anchor); }, - swapcase: function(cm, operatorArgs, _vim, _curStart, _curEnd, _curOriginal) { + changeCase: function(cm, args, ranges, oldAnchor, newHead) { var selections = cm.getSelections(); - var ranges = cm.listSelections(); var swapped = []; + var toLower = args.toLower; for (var j = 0; j < selections.length; j++) { var toSwap = selections[j]; var text = ''; - for (var i = 0; i < toSwap.length; i++) { - var character = toSwap.charAt(i); - text += isUpperCase(character) ? character.toLowerCase() : - character.toUpperCase(); + if (toLower === true) { + text = toSwap.toLowerCase(); + } else if (toLower === false) { + text = toSwap.toUpperCase(); + } else { + for (var i = 0; i < toSwap.length; i++) { + var character = toSwap.charAt(i); + text += isUpperCase(character) ? character.toLowerCase() : + character.toUpperCase(); + } } swapped.push(text); } cm.replaceSelections(swapped); - var curStart = ranges[0].anchor; - var curEnd = ranges[0].head; - if (!operatorArgs.shouldMoveCursor) { - cm.setCursor(cursorIsBefore(curStart, curEnd) ? curStart : curEnd); + if (args.shouldMoveCursor){ + return newHead; + } else if (!cm.state.vim.visualMode && args.linewise && ranges[0].anchor.line + 1 == ranges[0].head.line) { + return motions.moveToFirstNonWhiteSpaceCharacter(cm, oldAnchor); + } else if (args.linewise){ + return oldAnchor; + } else { + return cursorMin(ranges[0].anchor, ranges[0].head); } }, - yank: function(cm, operatorArgs, vim, _curStart, _curEnd, curOriginal) { + yank: function(cm, args, ranges, oldAnchor) { + var vim = cm.state.vim; var text = cm.getSelection(); + var endPos = vim.visualMode + ? cursorMin(vim.sel.anchor, vim.sel.head, ranges[0].head, ranges[0].anchor) + : oldAnchor; vimGlobalState.registerController.pushText( - operatorArgs.registerName, 'yank', - text, operatorArgs.linewise, vim.visualBlock); - cm.setCursor(curOriginal); + args.registerName, 'yank', + text, args.linewise, vim.visualBlock); + return endPos; } }; @@ -3483,41 +3407,40 @@ CodeMirror.multiplexingMode = function(outer /*, others */) { vim.insertMode = true; vim.insertModeRepeat = actionArgs && actionArgs.repeat || 1; var insertAt = (actionArgs) ? actionArgs.insertAt : null; - if (vim.visualMode) { - var selections = getSelectedAreaRange(cm, vim); - var selectionStart = selections[0]; - var selectionEnd = selections[1]; - } + var sel = vim.sel; + var head = actionArgs.head || cm.getCursor('head'); + var height = cm.listSelections().length; if (insertAt == 'eol') { - var cursor = cm.getCursor(); - cursor = Pos(cursor.line, lineLength(cm, cursor.line)); - cm.setCursor(cursor); + head = Pos(head.line, lineLength(cm, head.line)); } else if (insertAt == 'charAfter') { - cm.setCursor(offsetCursor(cm.getCursor(), 0, 1)); + head = offsetCursor(head, 0, 1); } else if (insertAt == 'firstNonBlank') { - if (vim.visualMode && !vim.visualBlock) { - if (selectionEnd.line < selectionStart.line) { - cm.setCursor(selectionEnd); + head = motions.moveToFirstNonWhiteSpaceCharacter(cm, head); + } else if (insertAt == 'startOfSelectedArea') { + if (!vim.visualBlock) { + if (sel.head.line < sel.anchor.line) { + head = sel.head; } else { - selectionStart = Pos(selectionStart.line, 0); - cm.setCursor(selectionStart); + head = Pos(sel.anchor.line, 0); } - cm.setCursor(motions.moveToFirstNonWhiteSpaceCharacter(cm)); - } else if (vim.visualBlock) { - selectionEnd = Pos(selectionEnd.line, selectionStart.ch); - cm.setCursor(selectionStart); - selectBlock(cm, selectionEnd); } else { - cm.setCursor(motions.moveToFirstNonWhiteSpaceCharacter(cm)); + head = Pos( + Math.min(sel.head.line, sel.anchor.line), + Math.min(sel.head.ch, sel.anchor.ch)); + height = Math.abs(sel.head.line - sel.anchor.line) + 1; } } else if (insertAt == 'endOfSelectedArea') { - if (vim.visualBlock) { - selectionStart = Pos(selectionStart.line, selectionEnd.ch); - cm.setCursor(selectionStart); - selectBlock(cm, selectionEnd); - } else if (selectionEnd.line < selectionStart.line) { - selectionEnd = Pos(selectionStart.line, 0); - cm.setCursor(selectionEnd); + if (!vim.visualBlock) { + if (sel.head.line >= sel.anchor.line) { + head = offsetCursor(sel.head, 0, 1); + } else { + head = Pos(sel.anchor.line, 0); + } + } else { + head = Pos( + Math.min(sel.head.line, sel.anchor.line), + Math.max(sel.head.ch + 1, sel.anchor.ch)); + height = Math.abs(sel.head.line - sel.anchor.line) + 1; } } else if (insertAt == 'inplace') { if (vim.visualMode){ @@ -3543,129 +3466,68 @@ CodeMirror.multiplexingMode = function(outer /*, others */) { if (vim.visualMode) { exitVisualMode(cm); } + selectForInsert(cm, head, height); }, toggleVisualMode: function(cm, actionArgs, vim) { var repeat = actionArgs.repeat; - var curStart = cm.getCursor(); - var curEnd; - var selections = cm.listSelections(); + var anchor = cm.getCursor(); + var head; // TODO: The repeat should actually select number of characters/lines // equal to the repeat times the size of the previous visual // operation. if (!vim.visualMode) { - cm.on('mousedown', exitVisualMode); + // Entering visual mode vim.visualMode = true; vim.visualLine = !!actionArgs.linewise; vim.visualBlock = !!actionArgs.blockwise; - if (vim.visualLine) { - curStart.ch = 0; - curEnd = clipCursorToContent( - cm, Pos(curStart.line + repeat - 1, lineLength(cm, curStart.line)), - true /** includeLineBreak */); - } else { - curEnd = clipCursorToContent( - cm, Pos(curStart.line, curStart.ch + repeat), + head = clipCursorToContent( + cm, Pos(anchor.line, anchor.ch + repeat - 1), true /** includeLineBreak */); - } - cm.setSelection(curStart, curEnd); - CodeMirror.signal(cm, "vim-mode-change", {mode: "visual", subMode: vim.visualLine ? "linewise" : ""}); + vim.sel = { + anchor: anchor, + head: head + }; + CodeMirror.signal(cm, "vim-mode-change", {mode: "visual", subMode: vim.visualLine ? "linewise" : vim.visualBlock ? "blockwise" : ""}); + updateCmSelection(cm); + updateMark(cm, vim, '<', cursorMin(anchor, head)); + updateMark(cm, vim, '>', cursorMax(anchor, head)); + } else if (vim.visualLine ^ actionArgs.linewise || + vim.visualBlock ^ actionArgs.blockwise) { + // Toggling between modes + vim.visualLine = !!actionArgs.linewise; + vim.visualBlock = !!actionArgs.blockwise; + CodeMirror.signal(cm, "vim-mode-change", {mode: "visual", subMode: vim.visualLine ? "linewise" : vim.visualBlock ? "blockwise" : ""}); + updateCmSelection(cm); } else { - curStart = cm.getCursor('anchor'); - curEnd = cm.getCursor('head'); - if (vim.visualLine) { - if (actionArgs.blockwise) { - // This means Ctrl-V pressed in linewise visual - vim.visualBlock = true; - selectBlock(cm, curEnd); - CodeMirror.signal(cm, 'vim-mode-change', {mode: 'visual', subMode: 'blockwise'}); - } else if (!actionArgs.linewise) { - // v pressed in linewise, switch to characterwise visual mode - CodeMirror.signal(cm, 'vim-mode-change', {mode: 'visual'}); - } else { - exitVisualMode(cm); - } - vim.visualLine = false; - } else if (vim.visualBlock) { - if (actionArgs.linewise) { - // Shift-V pressed in blockwise visual mode - vim.visualLine = true; - curStart = Pos(selections[0].anchor.line, 0); - curEnd = Pos(selections[selections.length-1].anchor.line, lineLength(cm, selections[selections.length-1].anchor.line)); - cm.setSelection(curStart, curEnd); - CodeMirror.signal(cm, 'vim-mode-change', {mode: 'visual', subMode: 'linewise'}); - } else if (!actionArgs.blockwise) { - // v pressed in blockwise mode, Switch to characterwise - if (curEnd != selections[0].head) { - curStart = selections[0].anchor; - } else { - curStart = selections[selections.length-1].anchor; - } - cm.setSelection(curStart, curEnd); - CodeMirror.signal(cm, 'vim-mode-change', {mode: 'visual'}); - } else { - exitVisualMode(cm); - } - vim.visualBlock = false; - } else if (actionArgs.linewise) { - // Shift-V pressed in characterwise visual mode. Switch to linewise - // visual mode instead of exiting visual mode. - vim.visualLine = true; - curStart.ch = cursorIsBefore(curStart, curEnd) ? 0 : - lineLength(cm, curStart.line); - curEnd.ch = cursorIsBefore(curStart, curEnd) ? - lineLength(cm, curEnd.line) : 0; - cm.setSelection(curStart, curEnd); - CodeMirror.signal(cm, "vim-mode-change", {mode: "visual", subMode: "linewise"}); - } else if (actionArgs.blockwise) { - vim.visualBlock = true; - selectBlock(cm, curEnd); - CodeMirror.signal(cm, 'vim-mode-change', {mode: 'visual', subMode: 'blockwise'}); - } else { - exitVisualMode(cm); - } + exitVisualMode(cm); } - updateMark(cm, vim, '<', cursorIsBefore(curStart, curEnd) ? curStart - : curEnd); - updateMark(cm, vim, '>', cursorIsBefore(curStart, curEnd) ? curEnd - : curStart); }, reselectLastSelection: function(cm, _actionArgs, vim) { - var curStart = vim.marks['<'].find(); - var curEnd = vim.marks['>'].find(); var lastSelection = vim.lastSelection; + if (vim.visualMode) { + updateLastSelection(cm, vim); + } if (lastSelection) { - // Set the selections as per last selection - var selectionStart = lastSelection.curStartMark.find(); - var selectionEnd = lastSelection.curEndMark.find(); - var blockwise = lastSelection.visualBlock; - // update last selection - updateLastSelection(cm, vim, curStart, curEnd); - if (blockwise) { - cm.setCursor(selectionStart); - selectionStart = selectBlock(cm, selectionEnd); - } else { - cm.setSelection(selectionStart, selectionEnd); - selectionStart = cm.getCursor('anchor'); - selectionEnd = cm.getCursor('head'); - } - if (vim.visualMode) { - updateMark(cm, vim, '<', cursorIsBefore(selectionStart, selectionEnd) ? selectionStart - : selectionEnd); - updateMark(cm, vim, '>', cursorIsBefore(selectionStart, selectionEnd) ? selectionEnd - : selectionStart); + var anchor = lastSelection.anchorMark.find(); + var head = lastSelection.headMark.find(); + if (!anchor || !head) { + // If the marks have been destroyed due to edits, do nothing. + return; } - // Last selection is updated now + vim.sel = { + anchor: anchor, + head: head + }; vim.visualMode = true; - if (lastSelection.visualLine) { - vim.visualLine = true; - vim.visualBlock = false; - } else if (lastSelection.visualBlock) { - vim.visualLine = false; - vim.visualBlock = true; - } else { - vim.visualBlock = vim.visualLine = false; - } - CodeMirror.signal(cm, "vim-mode-change", {mode: "visual", subMode: vim.visualLine ? "linewise" : ""}); + vim.visualLine = lastSelection.visualLine; + vim.visualBlock = lastSelection.visualBlock; + updateCmSelection(cm); + updateMark(cm, vim, '<', cursorMin(anchor, head)); + updateMark(cm, vim, '>', cursorMax(anchor, head)); + CodeMirror.signal(cm, 'vim-mode-change', { + mode: 'visual', + subMode: vim.visualLine ? 'linewise' : + vim.visualBlock ? 'blockwise' : ''}); } }, joinLines: function(cm, actionArgs, vim) { @@ -3682,18 +3544,19 @@ CodeMirror.multiplexingMode = function(outer /*, others */) { Infinity)); } var finalCh = 0; - cm.operation(function() { - for (var i = curStart.line; i < curEnd.line; i++) { - finalCh = lineLength(cm, curStart.line); - var tmp = Pos(curStart.line + 1, - lineLength(cm, curStart.line + 1)); - var text = cm.getRange(curStart, tmp); - text = text.replace(/\n\s*/g, ' '); - cm.replaceRange(text, curStart, tmp); - } - var curFinalPos = Pos(curStart.line, finalCh); - cm.setCursor(curFinalPos); - }); + for (var i = curStart.line; i < curEnd.line; i++) { + finalCh = lineLength(cm, curStart.line); + var tmp = Pos(curStart.line + 1, + lineLength(cm, curStart.line + 1)); + var text = cm.getRange(curStart, tmp); + text = text.replace(/\n\s*/g, ' '); + cm.replaceRange(text, curStart, tmp); + } + var curFinalPos = Pos(curStart.line, finalCh); + cm.setCursor(curFinalPos); + if (vim.visualMode) { + exitVisualMode(cm); + } }, newLineAndEnterInsertMode: function(cm, actionArgs, vim) { vim.insertMode = true; @@ -3722,11 +3585,12 @@ CodeMirror.multiplexingMode = function(outer /*, others */) { return; } if (actionArgs.matchIndent) { - // length that considers tabs and cm.options.tabSize + var tabSize = cm.getOption("tabSize"); + // length that considers tabs and tabSize var whitespaceLength = function(str) { var tabs = (str.split("\t").length - 1); var spaces = (str.split(" ").length - 1); - return tabs * cm.options.tabSize + spaces * 1; + return tabs * tabSize + spaces * 1; }; var currentLine = cm.getLine(cm.getCursor().line); var indent = whitespaceLength(currentLine.match(/^\s*/)[0]); @@ -3739,8 +3603,8 @@ CodeMirror.multiplexingMode = function(outer /*, others */) { if (newIndent < 0) { return ""; } - else if (cm.options.indentWithTabs) { - var quotient = Math.floor(newIndent / cm.options.tabSize); + else if (cm.getOption("indentWithTabs")) { + var quotient = Math.floor(newIndent / tabSize); return Array(quotient + 1).join('\t'); } else { @@ -3788,7 +3652,7 @@ CodeMirror.multiplexingMode = function(outer /*, others */) { var emptyStrings = new Array(selections.length).join('1').split('1'); // save the curEnd marker before it get cleared due to cm.replaceRange. if (vim.lastSelection) { - lastSelectionCurEnd = vim.lastSelection.curEndMark.find(); + lastSelectionCurEnd = vim.lastSelection.headMark.find(); } // push the previously selected text to unnamed register vimGlobalState.registerController.unnamedRegister.setText(selectedText); @@ -3812,7 +3676,7 @@ CodeMirror.multiplexingMode = function(outer /*, others */) { } // restore the the curEnd marker if(lastSelectionCurEnd) { - vim.lastSelection.curEndMark = cm.setBookmark(lastSelectionCurEnd); + vim.lastSelection.headMark = cm.setBookmark(lastSelectionCurEnd); } if (linewise) { curPosFinal.ch=0; @@ -3854,10 +3718,10 @@ CodeMirror.multiplexingMode = function(outer /*, others */) { } } } - cm.setCursor(curPosFinal); if (vim.visualMode) { exitVisualMode(cm); } + cm.setCursor(curPosFinal); }, undo: function(cm, actionArgs) { cm.operation(function() { @@ -3902,7 +3766,7 @@ CodeMirror.multiplexingMode = function(outer /*, others */) { replaceWithStr = replaceWithStr.replace(/[^\n]/g, replaceWith); if (vim.visualBlock) { // Tabs are split in visua block before replacing - var spaces = new Array(cm.options.tabSize+1).join(' '); + var spaces = new Array(cm.getOption("tabSize")+1).join(' '); replaceWithStr = cm.getSelection(); replaceWithStr = replaceWithStr.replace(/\t/g, spaces).replace(/[^\n]/g, replaceWith).split('\n'); cm.replaceSelections(replaceWithStr); @@ -3958,28 +3822,7 @@ CodeMirror.multiplexingMode = function(outer /*, others */) { } repeatLastEdit(cm, vim, repeat, false /** repeatForInsert */); }, - changeCase: function(cm, actionArgs, vim) { - var selectionStart = getSelectedAreaRange(cm, vim)[0]; - var text = cm.getSelection(); - var lastSelectionCurEnd; - var blockSelection; - if (vim.lastSelection) { - // save the curEnd marker to avoid its removal due to cm.replaceRange - lastSelectionCurEnd = vim.lastSelection.curEndMark.find(); - blockSelection = vim.lastSelection.visualBlock; - } - var toLower = actionArgs.toLower; - text = toLower ? text.toLowerCase() : text.toUpperCase(); - cm.replaceSelections(vim.visualBlock || blockSelection ? text.split('\n') : [text]); - // restore the last selection curEnd marker - if (lastSelectionCurEnd) { - vim.lastSelection.curEndMark = cm.setBookmark(lastSelectionCurEnd); - } - cm.setCursor(selectionStart); - if (vim.visualMode) { - exitVisualMode(cm); - } - } + exitInsertMode: exitInsertMode }; /* @@ -4007,16 +3850,66 @@ CodeMirror.multiplexingMode = function(outer /*, others */) { return ret; } function offsetCursor(cur, offsetLine, offsetCh) { + if (typeof offsetLine === 'object') { + offsetCh = offsetLine.ch; + offsetLine = offsetLine.line; + } return Pos(cur.line + offsetLine, cur.ch + offsetCh); } - function matchKeysPartial(pressed, mapped) { - for (var i = 0; i < pressed.length; i++) { - // 'character' means any character. For mark, register commads, etc. - if (pressed[i] != mapped[i] && mapped[i] != 'character') { - return false; + function getOffset(anchor, head) { + return { + line: head.line - anchor.line, + ch: head.line - anchor.line + }; + } + function commandMatches(keys, keyMap, context, inputState) { + // Partial matches are not applied. They inform the key handler + // that the current key sequence is a subsequence of a valid key + // sequence, so that the key buffer is not cleared. + var match, partial = [], full = []; + for (var i = 0; i < keyMap.length; i++) { + var command = keyMap[i]; + if (context == 'insert' && command.context != 'insert' || + command.context && command.context != context || + inputState.operator && command.type == 'action' || + !(match = commandMatch(keys, command.keys))) { continue; } + if (match == 'partial') { partial.push(command); } + if (match == 'full') { full.push(command); } + } + return { + partial: partial.length && partial, + full: full.length && full + }; + } + function commandMatch(pressed, mapped) { + if (mapped.slice(-11) == '') { + // Last character matches anything. + var prefixLen = mapped.length - 11; + var pressedPrefix = pressed.slice(0, prefixLen); + var mappedPrefix = mapped.slice(0, prefixLen); + return pressedPrefix == mappedPrefix && pressed.length > prefixLen ? 'full' : + mappedPrefix.indexOf(pressedPrefix) == 0 ? 'partial' : false; + } else { + return pressed == mapped ? 'full' : + mapped.indexOf(pressed) == 0 ? 'partial' : false; + } + } + function lastChar(keys) { + var match = /^.*(<[\w\-]+>)$/.exec(keys); + var selectedCharacter = match ? match[1] : keys.slice(-1); + if (selectedCharacter.length > 1){ + switch(selectedCharacter){ + case '': + selectedCharacter='\n'; + break; + case '': + selectedCharacter=' '; + break; + default: + break; } } - return true; + return selectedCharacter; } function repeatFn(cm, fn, repeat) { return function() { @@ -4040,7 +3933,19 @@ CodeMirror.multiplexingMode = function(outer /*, others */) { } return false; } - function cusrorIsBetween(cur1, cur2, cur3) { + function cursorMin(cur1, cur2) { + if (arguments.length > 2) { + cur2 = cursorMin.apply(undefined, Array.prototype.slice.call(arguments, 1)); + } + return cursorIsBefore(cur1, cur2) ? cur1 : cur2; + } + function cursorMax(cur1, cur2) { + if (arguments.length > 2) { + cur2 = cursorMax.apply(undefined, Array.prototype.slice.call(arguments, 1)); + } + return cursorIsBefore(cur1, cur2) ? cur2 : cur1; + } + function cursorIsBetween(cur1, cur2, cur3) { // returns true if cur2 is between cur1 and cur3. var cur1before2 = cursorIsBefore(cur1, cur2); var cur2before3 = cursorIsBefore(cur2, cur3); @@ -4075,121 +3980,59 @@ CodeMirror.multiplexingMode = function(outer /*, others */) { // Distance between selectionEnd.ch and any(first considered here) selection.ch function selectBlock(cm, selectionEnd) { var selections = [], ranges = cm.listSelections(); - var firstRange = ranges[0].anchor, lastRange = ranges[ranges.length-1].anchor; - var start, end, direction, selectionStart; - var curEnd = cm.getCursor('head'); - var originalSelectionEnd = copyCursor(selectionEnd); - start = firstRange.line; - end = lastRange.line; - if (selectionEnd.line < curEnd.line) { - direction = 'up'; - } else if (selectionEnd.line > curEnd.line) { - direction = 'down'; - } else { - if (selectionEnd.ch != curEnd.ch) { - direction = selectionEnd.ch > curEnd.ch ? 'right' : 'left'; - } - selectionStart = cm.getCursor('anchor'); - } - var primIndex = getIndex(ranges, curEnd); - // sets to true when selectionEnd already lies inside the existing selections - selectionEnd = cm.clipPos(selectionEnd); - var contains = getIndex(ranges, selectionEnd) < 0 ? false : true; - var isClipped = !cursorEqual(originalSelectionEnd, selectionEnd); - // This function helps to check selection crossing - // in case of short lines. - var processSelectionCrossing = function() { - if (isClipped) { - if (curEnd.ch >= selectionStart.ch) { - selectionStart.ch++; - } - } else if (curEnd.ch == lineLength(cm, curEnd.line)) { - if (cursorEqual(ranges[primIndex].anchor, ranges[primIndex].head) && ranges.length>1) { - if (direction == 'up') { - if (contains || primIndex>0) { - start = firstRange.line; - end = selectionEnd.line; - selectionStart = ranges[primIndex-1].anchor; - } - } else { - if (contains || primIndex == 0) { - end = lastRange.line; - start = selectionEnd.line; - selectionStart = ranges[primIndex+1].anchor; - } - } - if (selectionEnd.ch >= selectionStart.ch) { - selectionStart.ch--; - } - } - } - }; - switch(direction) { - case 'up': - start = contains ? firstRange.line : selectionEnd.line; - end = contains ? selectionEnd.line : lastRange.line; - selectionStart = lastRange; - processSelectionCrossing(); - break; - case 'down': - start = contains ? selectionEnd.line : firstRange.line; - end = contains ? lastRange.line : selectionEnd.line; - selectionStart = firstRange; - processSelectionCrossing(); - break; - case 'left': - if ((selectionEnd.ch <= selectionStart.ch) && (curEnd.ch > selectionStart.ch)) { - selectionStart.ch++; - selectionEnd.ch--; - } - break; - case 'right': - if ((selectionStart.ch <= selectionEnd.ch) && (curEnd.ch < selectionStart.ch)) { - selectionStart.ch--; - selectionEnd.ch++; - } - break; - default: - start = selectionStart.line; - end = selectionEnd.line; - } - while (start <= end) { - var anchor = {line: start, ch: selectionStart.ch}; - var head = {line: start, ch: selectionEnd.ch}; - var range = {anchor: anchor, head: head}; + var head = copyCursor(cm.clipPos(selectionEnd)); + var isClipped = !cursorEqual(selectionEnd, head); + var curHead = cm.getCursor('head'); + var primIndex = getIndex(ranges, curHead); + var wasClipped = cursorEqual(ranges[primIndex].head, ranges[primIndex].anchor); + var max = ranges.length - 1; + var index = max - primIndex > primIndex ? max : 0; + var base = ranges[index].anchor; + + var firstLine = Math.min(base.line, head.line); + var lastLine = Math.max(base.line, head.line); + var baseCh = base.ch, headCh = head.ch; + + var dir = ranges[index].head.ch - baseCh; + var newDir = headCh - baseCh; + if (dir > 0 && newDir <= 0) { + baseCh++; + if (!isClipped) { headCh--; } + } else if (dir < 0 && newDir >= 0) { + baseCh--; + if (!wasClipped) { headCh++; } + } else if (dir < 0 && newDir == -1) { + baseCh--; + headCh++; + } + for (var line = firstLine; line <= lastLine; line++) { + var range = {anchor: new Pos(line, baseCh), head: new Pos(line, headCh)}; selections.push(range); - if (cursorEqual(head, selectionEnd)) { - primIndex = selections.indexOf(range); - } - start++; } - // Update selectionEnd and selectionStart - // after selection crossing - selectionEnd.ch = selections[0].head.ch; - selectionStart.ch = selections[0].anchor.ch; - if (cursorEqual(selectionEnd, selections[0].head)) { - selectionStart.line = selections[selections.length-1].anchor.line; - } else { - selectionStart.line = selections[0].anchor.line; + primIndex = head.line == lastLine ? selections.length - 1 : 0; + cm.setSelections(selections); + selectionEnd.ch = headCh; + base.ch = baseCh; + return base; + } + function selectForInsert(cm, head, height) { + var sel = []; + for (var i = 0; i < height; i++) { + var lineHead = offsetCursor(head, i, 0); + sel.push({anchor: lineHead, head: lineHead}); } - cm.setSelections(selections, primIndex); - return selectionStart; + cm.setSelections(sel, 0); } // getIndex returns the index of the cursor in the selections. function getIndex(ranges, cursor, end) { - var pos = -1; for (var i = 0; i < ranges.length; i++) { - var atAnchor = cursorEqual(ranges[i].anchor, cursor); - var atHead = cursorEqual(ranges[i].head, cursor); - if (end == 'head') { - pos = atHead ? i : pos; - } else if (end == 'anchor') { - pos = atAnchor ? i : pos; - } else { - pos = (atAnchor || atHead) ? i : pos; + var atAnchor = end != 'head' && cursorEqual(ranges[i].anchor, cursor); + var atHead = end != 'anchor' && cursorEqual(ranges[i].head, cursor); + if (atAnchor || atHead) { + return i; } } - return pos; + return -1; } function getSelectedAreaRange(cm, vim) { var lastSelection = vim.lastSelection; @@ -4220,8 +4063,8 @@ CodeMirror.multiplexingMode = function(outer /*, others */) { } cm.setSelections(selections); } else { - var start = lastSelection.curStartMark.find(); - var end = lastSelection.curEndMark.find(); + var start = lastSelection.anchorMark.find(); + var end = lastSelection.headMark.find(); var line = end.line - start.line; var ch = end.ch - start.ch; selectionEnd = {line: selectionEnd.line + line, ch: line ? selectionEnd.ch : ch + selectionEnd.ch}; @@ -4240,51 +4083,133 @@ CodeMirror.multiplexingMode = function(outer /*, others */) { return getCurrentSelectedAreaRange(); } } - function updateLastSelection(cm, vim, selectionStart, selectionEnd) { - if (!selectionStart || !selectionEnd) { - selectionStart = vim.marks['<'].find() || cm.getCursor('anchor'); - selectionEnd = vim.marks['>'].find() || cm.getCursor('head'); - } + // Updates the previous selection with the current selection's values. This + // should only be called in visual mode. + function updateLastSelection(cm, vim) { + var anchor = vim.sel.anchor; + var head = vim.sel.head; // To accommodate the effect of lastPastedText in the last selection if (vim.lastPastedText) { - selectionEnd = cm.posFromIndex(cm.indexFromPos(selectionStart) + vim.lastPastedText.length); + head = cm.posFromIndex(cm.indexFromPos(anchor) + vim.lastPastedText.length); vim.lastPastedText = null; } - var ranges = cm.listSelections(); - // This check ensures to set the cursor - // position where we left off in previous selection - var swap = getIndex(ranges, selectionStart, 'head') > -1; - if (vim.visualBlock) { - var height = Math.abs(selectionStart.line - selectionEnd.line)+1; - var width = Math.abs(selectionStart.ch - selectionEnd.ch); - var block = {height: height, width: width}; - } - // can't use selection state here because yank has already reset its cursor - // Also, Bookmarks make the visual selections robust to edit operations - vim.lastSelection = {'curStartMark': cm.setBookmark(swap ? selectionEnd : selectionStart), - 'curEndMark': cm.setBookmark(swap ? selectionStart : selectionEnd), + vim.lastSelection = {'anchorMark': cm.setBookmark(anchor), + 'headMark': cm.setBookmark(head), + 'anchor': copyCursor(anchor), + 'head': copyCursor(head), 'visualMode': vim.visualMode, 'visualLine': vim.visualLine, - 'visualBlock': block}; + 'visualBlock': vim.visualBlock}; } + function expandSelection(cm, start, end) { + var sel = cm.state.vim.sel; + var head = sel.head; + var anchor = sel.anchor; + var tmp; + if (cursorIsBefore(end, start)) { + tmp = end; + end = start; + start = tmp; + } + if (cursorIsBefore(head, anchor)) { + head = cursorMin(start, head); + anchor = cursorMax(anchor, end); + } else { + anchor = cursorMin(start, anchor); + head = cursorMax(head, end); + head = offsetCursor(head, 0, -1); + if (head.ch == -1 && head.line != cm.firstLine()) { + head = Pos(head.line - 1, lineLength(cm, head.line - 1)); + } + } + return [anchor, head]; + } + /** + * Updates the CodeMirror selection to match the provided vim selection. + * If no arguments are given, it uses the current vim selection state. + */ + function updateCmSelection(cm, sel, mode) { + var vim = cm.state.vim; + sel = sel || vim.sel; + var mode = mode || + vim.visualLine ? 'line' : vim.visualBlock ? 'block' : 'char'; + var cmSel = makeCmSelection(cm, sel, mode); + cm.setSelections(cmSel.ranges, cmSel.primary); + updateFakeCursor(cm); + } + function makeCmSelection(cm, sel, mode, exclusive) { + var head = copyCursor(sel.head); + var anchor = copyCursor(sel.anchor); + if (mode == 'char') { + var headOffset = !exclusive && !cursorIsBefore(sel.head, sel.anchor) ? 1 : 0; + var anchorOffset = cursorIsBefore(sel.head, sel.anchor) ? 1 : 0; + head = offsetCursor(sel.head, 0, headOffset); + anchor = offsetCursor(sel.anchor, 0, anchorOffset); + return { + ranges: [{anchor: anchor, head: head}], + primary: 0 + }; + } else if (mode == 'line') { + if (!cursorIsBefore(sel.head, sel.anchor)) { + anchor.ch = 0; - function exitVisualMode(cm) { - cm.off('mousedown', exitVisualMode); + var lastLine = cm.lastLine(); + if (head.line > lastLine) { + head.line = lastLine; + } + head.ch = lineLength(cm, head.line); + } else { + head.ch = 0; + anchor.ch = lineLength(cm, anchor.line); + } + return { + ranges: [{anchor: anchor, head: head}], + primary: 0 + }; + } else if (mode == 'block') { + var top = Math.min(anchor.line, head.line), + left = Math.min(anchor.ch, head.ch), + bottom = Math.max(anchor.line, head.line), + right = Math.max(anchor.ch, head.ch) + 1; + var height = bottom - top + 1; + var primary = head.line == top ? 0 : height - 1; + var ranges = []; + for (var i = 0; i < height; i++) { + ranges.push({ + anchor: Pos(top + i, left), + head: Pos(top + i, right) + }); + } + return { + ranges: ranges, + primary: primary + }; + } + } + function getHead(cm) { + var cur = cm.getCursor('head'); + if (cm.getSelection().length == 1) { + // Small corner case when only 1 character is selected. The "real" + // head is the left of head and anchor. + cur = cursorMin(cur, cm.getCursor('anchor')); + } + return cur; + } + + /** + * If moveHead is set to false, the CodeMirror selection will not be + * touched. The caller assumes the responsibility of putting the cursor + * in the right place. + */ + function exitVisualMode(cm, moveHead) { var vim = cm.state.vim; - var selectionStart = cm.getCursor('anchor'); - var selectionEnd = cm.getCursor('head'); - // hack to place the cursor at the right place - // in case of visual block - if (vim.visualBlock && (cursorIsBefore(selectionStart, selectionEnd))) { - selectionEnd.ch--; + if (moveHead !== false) { + cm.setCursor(clipCursorToContent(cm, vim.sel.head)); } updateLastSelection(cm, vim); vim.visualMode = false; vim.visualLine = false; vim.visualBlock = false; - if (!cursorEqual(selectionStart, selectionEnd)) { - cm.setCursor(clipCursorToContent(cm, selectionEnd)); - } CodeMirror.signal(cm, "vim-mode-change", {mode: "normal"}); if (vim.fakeCursor) { vim.fakeCursor.clear(); @@ -4339,7 +4264,7 @@ CodeMirror.multiplexingMode = function(outer /*, others */) { } function expandWordUnderCursor(cm, inclusive, _forward, bigWord, noSymbol) { - var cur = cm.getCursor(); + var cur = getHead(cm); var line = cm.getLine(cur.line); var idx = cur.ch; @@ -4614,6 +4539,7 @@ CodeMirror.multiplexingMode = function(outer /*, others */) { /** * @param {CodeMirror} cm CodeMirror object. + * @param {Pos} cur The position to start from. * @param {int} repeat Number of words to move past. * @param {boolean} forward True to search forward. False to search * backward. @@ -4623,8 +4549,7 @@ CodeMirror.multiplexingMode = function(outer /*, others */) { * False if only alphabet characters count as part of the word. * @return {Cursor} The position the cursor should move to. */ - function moveToWord(cm, repeat, forward, wordEnd, bigWord) { - var cur = cm.getCursor(); + function moveToWord(cm, cur, repeat, forward, wordEnd, bigWord) { var curStart = copyCursor(cur); var words = []; if (forward && !wordEnd || !forward && wordEnd) { @@ -4724,8 +4649,8 @@ CodeMirror.multiplexingMode = function(outer /*, others */) { // TODO: perhaps this finagling of start and end positions belonds // in codmirror/replaceRange? - function selectCompanionObject(cm, symb, inclusive) { - var cur = cm.getCursor(), start, end; + function selectCompanionObject(cm, head, symb, inclusive) { + var cur = head, start, end; var bracketRegexp = ({ '(': /[()]/, ')': /[()]/, @@ -4769,8 +4694,8 @@ CodeMirror.multiplexingMode = function(outer /*, others */) { // Takes in a symbol and a cursor and tries to simulate text objects that // have identical opening and closing symbols // TODO support across multiple lines - function findBeginningAndEnd(cm, symb, inclusive) { - var cur = copyCursor(cm.getCursor()); + function findBeginningAndEnd(cm, head, symb, inclusive) { + var cur = copyCursor(head); var line = cm.getLine(cur.line); var chars = line.split(''); var start, end, i, len; @@ -5203,6 +5128,7 @@ CodeMirror.multiplexingMode = function(outer /*, others */) { // shortNames must not match the prefix of the other command. var defaultExCommandMap = [ { name: 'map' }, + { name: 'imap', shortName: 'im' }, { name: 'nmap', shortName: 'nm' }, { name: 'vmap', shortName: 'vm' }, { name: 'unmap' }, @@ -5217,10 +5143,10 @@ CodeMirror.multiplexingMode = function(outer /*, others */) { { name: 'registers', shortName: 'reg', excludeFromCommandHistory: true }, { name: 'global', shortName: 'g' } ]; - Vim.ExCommandDispatcher = function() { + var ExCommandDispatcher = function() { this.buildCommandMap_(); }; - Vim.ExCommandDispatcher.prototype = { + ExCommandDispatcher.prototype = { processCommand: function(cm, input, opt_params) { var vim = cm.state.vim; var commandHistoryRegister = vimGlobalState.registerController.getRegister(':'); @@ -5257,7 +5183,7 @@ CodeMirror.multiplexingMode = function(outer /*, others */) { if (command.type == 'exToKey') { // Handle Ex to Key mapping. for (var i = 0; i < command.toKeys.length; i++) { - CodeMirror.Vim.handleKey(cm, command.toKeys[i]); + CodeMirror.Vim.handleKey(cm, command.toKeys[i], 'mapping'); } return; } else if (command.type == 'exToEx') { @@ -5381,7 +5307,7 @@ CodeMirror.multiplexingMode = function(outer /*, others */) { this.commandMap_[commandName] = { name: commandName, type: 'exToKey', - toKeys: parseKeyString(rhs), + toKeys: rhs, user: true }; } @@ -5389,7 +5315,7 @@ CodeMirror.multiplexingMode = function(outer /*, others */) { if (rhs != ':' && rhs.charAt(0) == ':') { // Key to Ex mapping. var mapping = { - keys: parseKeyString(lhs), + keys: lhs, type: 'keyToEx', exArgs: { input: rhs.substring(1) }, user: true}; @@ -5398,9 +5324,9 @@ CodeMirror.multiplexingMode = function(outer /*, others */) { } else { // Key to key mapping var mapping = { - keys: parseKeyString(lhs), + keys: lhs, type: 'keyToKey', - toKeys: parseKeyString(rhs), + toKeys: rhs, user: true }; if (ctx) { mapping.context = ctx; } @@ -5409,15 +5335,6 @@ CodeMirror.multiplexingMode = function(outer /*, others */) { } }, unmap: function(lhs, ctx) { - var arrayEquals = function(a, b) { - if (a === b) return true; - if (a == null || b == null) return true; - if (a.length != b.length) return false; - for (var i = 0; i < a.length; i++) { - if (a[i] !== b[i]) return false; - } - return true; - }; if (lhs != ':' && lhs.charAt(0) == ':') { // Ex to Ex or Ex to key mapping if (ctx) { throw Error('Mode not supported for ex mappings'); } @@ -5428,9 +5345,9 @@ CodeMirror.multiplexingMode = function(outer /*, others */) { } } else { // Key to Ex or key to key mapping - var keys = parseKeyString(lhs); + var keys = lhs; for (var i = 0; i < defaultKeymap.length; i++) { - if (arrayEquals(keys, defaultKeymap[i].keys) + if (keys == defaultKeymap[i].keys && defaultKeymap[i].context === ctx && defaultKeymap[i].user) { defaultKeymap.splice(i, 1); @@ -5442,21 +5359,6 @@ CodeMirror.multiplexingMode = function(outer /*, others */) { } }; - // Converts a key string sequence of the form abd into Vim's - // keymap representation. - function parseKeyString(str) { - var key, match; - var keys = []; - while (str) { - match = (/<\w+-.+?>|<\w+>|./).exec(str); - if (match === null)break; - key = match[0]; - str = str.substring(match.index + key.length); - keys.push(key); - } - return keys; - } - var exCommands = { map: function(cm, params, ctx) { var mapArgs = params.args; @@ -5468,6 +5370,7 @@ CodeMirror.multiplexingMode = function(outer /*, others */) { } exCommandDispatcher.map(mapArgs[0], mapArgs[1], ctx); }, + imap: function(cm, params) { this.map(cm, params, 'insert'); }, nmap: function(cm, params) { this.map(cm, params, 'normal'); }, vmap: function(cm, params) { this.map(cm, params, 'visual'); }, unmap: function(cm, params, ctx) { @@ -5842,7 +5745,7 @@ CodeMirror.multiplexingMode = function(outer /*, others */) { } }; - var exCommandDispatcher = new Vim.ExCommandDispatcher(); + var exCommandDispatcher = new ExCommandDispatcher(); /** * @param {CodeMirror} cm CodeMirror instance we are in. @@ -5930,6 +5833,7 @@ CodeMirror.multiplexingMode = function(outer /*, others */) { break; } if (done) { stop(close); } + return true; } // Actually do replace. @@ -5949,65 +5853,10 @@ CodeMirror.multiplexingMode = function(outer /*, others */) { }); } - // Register Vim with CodeMirror - function buildVimKeyMap() { - /** - * Handle the raw key event from CodeMirror. Translate the - * Shift + key modifier to the resulting letter, while preserving other - * modifers. - */ - function cmKeyToVimKey(key, modifier) { - var vimKey = key; - if (isUpperCase(vimKey) && modifier == 'Ctrl') { - vimKey = vimKey.toLowerCase(); - } - if (modifier) { - // Vim will parse modifier+key combination as a single key. - vimKey = modifier.charAt(0) + '-' + vimKey; - } - var specialKey = ({Enter:'CR',Backspace:'BS',Delete:'Del'})[vimKey]; - vimKey = specialKey ? specialKey : vimKey; - vimKey = vimKey.length > 1 ? '<'+ vimKey + '>' : vimKey; - return vimKey; - } - - // Closure to bind CodeMirror, key, modifier. - function keyMapper(vimKey) { - return function(cm) { - CodeMirror.signal(cm, 'vim-keypress', vimKey); - CodeMirror.Vim.handleKey(cm, vimKey); - }; - } - - var cmToVimKeymap = { - 'nofallthrough': true, - 'style': 'fat-cursor' - }; - function bindKeys(keys, modifier) { - for (var i = 0; i < keys.length; i++) { - var key = keys[i]; - if (!modifier && key.length == 1) { - // Wrap all keys without modifiers with '' to identify them by their - // key characters instead of key identifiers. - key = "'" + key + "'"; - } - var vimKey = cmKeyToVimKey(keys[i], modifier); - var cmKey = modifier ? modifier + '-' + key : key; - cmToVimKeymap[cmKey] = keyMapper(vimKey); - } - } - bindKeys(upperCaseAlphabet); - bindKeys(lowerCaseAlphabet); - bindKeys(upperCaseAlphabet, 'Ctrl'); - bindKeys(specialSymbols); - bindKeys(specialSymbols, 'Ctrl'); - bindKeys(numbers); - bindKeys(numbers, 'Ctrl'); - bindKeys(specialKeys); - bindKeys(specialKeys, 'Ctrl'); - return cmToVimKeymap; - } - CodeMirror.keyMap.vim = buildVimKeyMap(); + CodeMirror.keyMap.vim = { + attach: attachVimMap, + detach: detachVimMap + }; function exitInsertMode(cm) { var vim = cm.state.vim; @@ -6063,63 +5912,13 @@ CodeMirror.multiplexingMode = function(outer /*, others */) { } } - defineOption('enableInsertModeEscKeys', false, 'boolean'); - // Use this option to customize the two-character ESC keymap. - // If you want to use characters other than i j or k you'll have to add - // lines to the vim-insert and await-second keymaps later in this file. - defineOption('insertModeEscKeys', 'kj', 'string'); // The timeout in milliseconds for the two-character ESC keymap should be // adjusted according to your typing speed to prevent false positives. defineOption('insertModeEscKeysTimeout', 200, 'number'); - function firstEscCharacterHandler(ch) { - return function(cm){ - var keys = getOption('insertModeEscKeys'); - var firstEscCharacter = keys && keys.length > 1 && keys.charAt(0); - if (!getOption('enableInsertModeEscKeys')|| firstEscCharacter !== ch) { - return CodeMirror.Pass; - } else { - cm.replaceRange(ch, cm.getCursor(), cm.getCursor(), "+input"); - cm.setOption('keyMap', 'await-second'); - cm.state.vim.awaitingEscapeSecondCharacter = true; - setTimeout( - function(){ - if(cm.state.vim.awaitingEscapeSecondCharacter) { - cm.state.vim.awaitingEscapeSecondCharacter = false; - cm.setOption('keyMap', 'vim-insert'); - } - }, - getOption('insertModeEscKeysTimeout')); - } - }; - } - function secondEscCharacterHandler(ch){ - return function(cm) { - var keys = getOption('insertModeEscKeys'); - var secondEscCharacter = keys && keys.length > 1 && keys.charAt(1); - if (!getOption('enableInsertModeEscKeys')|| secondEscCharacter !== ch) { - return CodeMirror.Pass; - // This is not the handler you're looking for. Just insert as usual. - } else { - if (cm.state.vim.insertMode) { - var lastChange = vimGlobalState.macroModeState.lastInsertModeChanges; - if (lastChange && lastChange.changes.length) { - lastChange.changes.pop(); - } - } - cm.state.vim.awaitingEscapeSecondCharacter = false; - cm.replaceRange('', {ch: cm.getCursor().ch - 1, line: cm.getCursor().line}, - cm.getCursor(), "+input"); - exitInsertMode(cm); - } - }; - } CodeMirror.keyMap['vim-insert'] = { // TODO: override navigation keys so that Esc will cancel automatic // indentation from o, O, i_ - 'Esc': exitInsertMode, - 'Ctrl-[': exitInsertMode, - 'Ctrl-C': exitInsertMode, 'Ctrl-N': 'autocomplete', 'Ctrl-P': 'autocomplete', 'Enter': function(cm) { @@ -6127,26 +5926,22 @@ CodeMirror.multiplexingMode = function(outer /*, others */) { CodeMirror.commands.newlineAndIndent; fn(cm); }, - // The next few lines are where you'd add additional handlers if - // you wanted to use keys other than i j and k for two-character - // escape sequences. Don't forget to add them in the await-second - // section as well. - "'i'": firstEscCharacterHandler('i'), - "'j'": firstEscCharacterHandler('j'), - "'k'": firstEscCharacterHandler('k'), - fallthrough: ['default'] + fallthrough: ['default'], + attach: attachVimMap, + detach: detachVimMap }; CodeMirror.keyMap['await-second'] = { - "'i'": secondEscCharacterHandler('i'), - "'j'": secondEscCharacterHandler('j'), - "'k'": secondEscCharacterHandler('k'), - fallthrough: ['vim-insert'] + fallthrough: ['vim-insert'], + attach: attachVimMap, + detach: detachVimMap }; CodeMirror.keyMap['vim-replace'] = { 'Backspace': 'goCharLeft', - fallthrough: ['vim-insert'] + fallthrough: ['vim-insert'], + attach: attachVimMap, + detach: detachVimMap }; function executeMacroRegister(cm, vim, macroModeState, registerName) { @@ -6164,7 +5959,7 @@ CodeMirror.multiplexingMode = function(outer /*, others */) { match = (/<\w+-.+?>|<\w+>|./).exec(text); key = match[0]; text = text.substring(match.index + key.length); - CodeMirror.Vim.handleKey(cm, key); + CodeMirror.Vim.handleKey(cm, key, 'macro'); if (vim.insertMode) { var changes = register.insertModeChanges[imc++].changes; vimGlobalState.macroModeState.lastInsertModeChanges.changes = @@ -6241,28 +6036,49 @@ CodeMirror.multiplexingMode = function(outer /*, others */) { // Cursor moved outside the context of an edit. Reset the change. lastChange.changes = []; } - } else if (cm.doc.history.lastSelOrigin == '*mouse') { - // Reset lastHPos if mouse click was done in normal mode. - vim.lastHPos = cm.doc.getCursor().ch; - if (cm.somethingSelected()) { - // If something is still selected, enter visual mode. - vim.visualMode = true; - } + } else if (!cm.curOp.isVimOp) { + handleExternalSelection(cm, vim); } if (vim.visualMode) { - var from, head; - from = head = cm.getCursor('head'); - var anchor = cm.getCursor('anchor'); - var to = Pos(head.line, from.ch + (cursorIsBefore(anchor, head) ? -1 : 1)); - if (cursorIsBefore(to, from)) { - var temp = from; - from = to; - to = temp; - } - if (vim.fakeCursor) { - vim.fakeCursor.clear(); - } - vim.fakeCursor = cm.markText(from, to, {className: 'cm-animate-fat-cursor'}); + updateFakeCursor(cm); + } + } + function updateFakeCursor(cm) { + var vim = cm.state.vim; + var from = copyCursor(vim.sel.head); + var to = offsetCursor(from, 0, 1); + if (vim.fakeCursor) { + vim.fakeCursor.clear(); + } + vim.fakeCursor = cm.markText(from, to, {className: 'cm-animate-fat-cursor'}); + } + function handleExternalSelection(cm, vim) { + var anchor = cm.getCursor('anchor'); + var head = cm.getCursor('head'); + // Enter or exit visual mode to match mouse selection. + if (vim.visualMode && cursorEqual(head, anchor) && lineLength(cm, head.line) > head.ch) { + exitVisualMode(cm, false); + } else if (!vim.visualMode && !vim.insertMode && cm.somethingSelected()) { + vim.visualMode = true; + vim.visualLine = false; + CodeMirror.signal(cm, "vim-mode-change", {mode: "visual"}); + } + if (vim.visualMode) { + // Bind CodeMirror selection model to vim selection model. + // Mouse selections are considered visual characterwise. + var headOffset = !cursorIsBefore(head, anchor) ? -1 : 0; + var anchorOffset = cursorIsBefore(head, anchor) ? -1 : 0; + head = offsetCursor(head, 0, headOffset); + anchor = offsetCursor(anchor, 0, anchorOffset); + vim.sel = { + anchor: anchor, + head: head + }; + updateMark(cm, vim, '<', cursorMin(head, anchor)); + updateMark(cm, vim, '>', cursorMax(head, anchor)); + } else if (!vim.insertMode) { + // Reset lastHPos if selection was modified by something outside of vim mode e.g. by mouse. + vim.lastHPos = cm.getCursor().ch; } } @@ -6285,7 +6101,7 @@ CodeMirror.multiplexingMode = function(outer /*, others */) { return true; } if (keyName.indexOf('Delete') != -1 || keyName.indexOf('Backspace') != -1) { - CodeMirror.lookupKey(keyName, ['vim-insert'], onKeyFound); + CodeMirror.lookupKey(keyName, 'vim-insert', onKeyFound); } } @@ -6354,32 +6170,33 @@ CodeMirror.multiplexingMode = function(outer /*, others */) { } return true; } - var curStart = cm.getCursor(); + var head = cm.getCursor('head'); var inVisualBlock = vimGlobalState.macroModeState.lastInsertModeChanges.inVisualBlock; if (inVisualBlock) { // Set up block selection again for repeating the changes. var vim = cm.state.vim; - var block = vim.lastSelection.visualBlock; - var curEnd = Pos(curStart.line + block.height-1, curStart.ch); - cm.setCursor(curStart); - selectBlock(cm, curEnd); + var lastSel = vim.lastSelection; + var offset = getOffset(lastSel.anchor, lastSel.head); + selectForInsert(cm, head, offset.line + 1); repeat = cm.listSelections().length; - cm.setCursor(curStart); + cm.setCursor(head); } for (var i = 0; i < repeat; i++) { + if (inVisualBlock) { + cm.setCursor(offsetCursor(head, i, 0)); + } for (var j = 0; j < changes.length; j++) { var change = changes[j]; if (change instanceof InsertModeKey) { - CodeMirror.lookupKey(change.keyName, ['vim-insert'], keyHandler); + CodeMirror.lookupKey(change.keyName, 'vim-insert', keyHandler); } else { var cur = cm.getCursor(); cm.replaceRange(change, cur, cur); } } - if (inVisualBlock) { - curStart.line++; - cm.setCursor(curStart); - } + } + if (inVisualBlock) { + cm.setCursor(offsetCursor(head, 0, 1)); } } diff --git a/media/editors/codemirror/lib/addons.js b/media/editors/codemirror/lib/addons.js index b8a2f6e274ef9..a04ffd1099cac 100644 --- a/media/editors/codemirror/lib/addons.js +++ b/media/editors/codemirror/lib/addons.js @@ -1 +1 @@ -(function(a){if(typeof exports=="object"&&typeof module=="object"){a(require("../../lib/codemirror"))}else{if(typeof define=="function"&&define.amd){define(["../../lib/codemirror"],a)}else{a(CodeMirror)}}})(function(a){a.defineOption("fullScreen",false,function(d,f,e){if(e==a.Init){e=false}if(!e==!f){return}if(f){b(d)}else{c(d)}});function b(d){var e=d.getWrapperElement();d.state.fullScreenRestore={scrollTop:window.pageYOffset,scrollLeft:window.pageXOffset,width:e.style.width,height:e.style.height};e.style.width="";e.style.height="auto";e.className+=" CodeMirror-fullscreen";document.documentElement.style.overflow="hidden";d.refresh()}function c(d){var e=d.getWrapperElement();e.className=e.className.replace(/\s*CodeMirror-fullscreen\b/,"");document.documentElement.style.overflow="";var f=d.state.fullScreenRestore;e.style.width=f.width;e.style.height=f.height;window.scrollTo(f.scrollLeft,f.scrollTop);d.refresh()}});(function(a){if(typeof exports=="object"&&typeof module=="object"){a(require("../../lib/codemirror"))}else{if(typeof define=="function"&&define.amd){define(["../../lib/codemirror"],a)}else{a(CodeMirror)}}})(function(c){var h="()[]{}''\"\"";var g="[]{}";var i=/\s/;var f=c.Pos;c.defineOption("autoCloseBrackets",false,function(j,o,k){if(k!=c.Init&&k){j.removeKeyMap("autoCloseBrackets")}if(!o){return}var m=h,l=g;if(typeof o=="string"){m=o}else{if(typeof o=="object"){if(o.pairs!=null){m=o.pairs}if(o.explode!=null){l=o.explode}}}var n=b(m);if(l){n.Enter=a(l)}j.addKeyMap(n)});function d(j,l){var k=j.getRange(f(l.line,l.ch-1),f(l.line,l.ch+1));return k.length==2?k:null}function e(j,p,n){var k=j.getLine(p.line);var m=j.getTokenAt(p);if(/\bstring2?\b/.test(m.type)){return false}var o=new c.StringStream(k.slice(0,p.ch)+n+k.slice(p.ch),4);o.pos=o.start=m.start;for(;;){var l=j.getMode().token(o,m.state);if(o.pos>=p.ch+1){return/\bstring2?\b/.test(l)}o.start=o.pos}}function b(l){var m={name:"autoCloseBrackets",Backspace:function(n){if(n.getOption("disableInput")){return c.Pass}var o=n.listSelections();for(var p=0;p=0;p--){var r=o[p].head;n.replaceRange("",f(r.line,r.ch-1),f(r.line,r.ch+1))}}};var k="";for(var j=0;j1&&p.getRange(f(w.line,w.ch-2),w)==o+o&&(w.ch<=2||p.getRange(f(w.line,w.ch-3),f(w.line,w.ch-2))!=o)){s="addFour"}else{if(o=='"'||o=="'"){if(!c.isWordChar(u)&&e(p,w,o)){s="both"}else{return c.Pass}}else{if(p.getLine(w.line).length==w.ch||k.indexOf(u)>=0||i.test(u)){s="both"}else{return c.Pass}}}}}if(!v){v=s}else{if(v!=s){return c.Pass}}}p.operation(function(){if(v=="skip"){p.execCommand("goCharRight")}else{if(v=="skipThree"){for(var y=0;y<3;y++){p.execCommand("goCharRight")}}else{if(v=="surround"){var x=p.getSelections();for(var y=0;y'"]=function(l){return a(l)}}h.addKeyMap(j)});var d=["area","base","br","col","command","embed","hr","img","input","keygen","link","meta","param","source","track","wbr"];var c=["applet","blockquote","body","button","div","dl","fieldset","form","frameset","h1","h2","h3","h4","h5","h6","head","html","iframe","layer","legend","object","ol","p","select","table","ul"];function a(w){if(w.getOption("disableInput")){return b.Pass}var j=w.listSelections(),q=[];for(var r=0;rv.ch){p=p.slice(0,p.length-x.end+v.ch)}var t=p.toLowerCase();if(!p||x.type=="string"&&(x.end!=v.ch||!/[\"\']/.test(x.string.charAt(x.string.length-1))||x.string.length==1)||x.type=="tag"&&h.type=="closeTag"||x.string.indexOf("/")==(x.string.length-1)||m&&g(m,t)>-1||f(w,p,v,h,true)){return b.Pass}var o=u&&g(u,t)>-1;q[r]={indent:o,text:">"+(o?"\n\n":"")+"",newPos:o?b.Pos(v.line+1,0):b.Pos(v.line,v.ch+1)}}for(var r=j.length-1;r>=0;r--){var n=q[r];w.replaceRange(n.text,j[r].head,j[r].anchor,"+insert");var l=w.listSelections().slice(0);l[r]={head:n.newPos,anchor:n.newPos};w.setSelections(l);if(n.indent){w.indentLine(n.newPos.line,null,true);w.indentLine(n.newPos.line+1,null,true)}}}function e(h){if(h.getOption("disableInput")){return b.Pass}var j=h.listSelections(),n=[];for(var m=0;m"}else{if(h.getMode().name=="htmlmixed"&&k.mode.name=="css"){n[m]="/style>"}else{return b.Pass}}}else{if(!o.context||!o.context.tagName||f(h,o.context.tagName,p,o)){return b.Pass}n[m]="/"+o.context.tagName+">"}}h.replaceSelections(n);j=h.listSelections();for(var m=0;m",")":"(<","[":"]>","]":"[<","{":"}>","}":"{<"};function f(q,m,p,k){var s=q.getLineHandle(m.line),o=m.ch-1;var n=(o>=0&&a[s.text.charAt(o)])||a[s.text.charAt(++o)];if(!n){return null}var l=n.charAt(1)==">"?1:-1;if(p&&(l>0)!=(o==m.ch)){return null}var j=q.getTokenTypeAt(i(m.line,o+1));var r=g(q,i(m.line,o+(l>0?1:0)),l,j||null,k);if(r==null){return null}return{from:i(m.line,o),to:r&&r.pos,match:r&&r.ch==n.charAt(0),forward:l>0}}function g(w,r,n,k,m){var l=(m&&m.maxScanLineLength)||10000;var t=(m&&m.maxScanLines)||1000;var v=[];var x=m&&m.bracketRegex?m.bracketRegex:/[(){}[\]]/;var q=n>0?Math.min(r.line+t,w.lastLine()+1):Math.max(w.firstLine()-1,r.line-t);for(var o=r.line;o!=q;o+=n){var y=w.getLine(o);if(!y){continue}var u=n>0?0:y.length-1,p=n>0?y.length:-1;if(y.length>l){continue}if(o==r.line){u=r.ch-(n<0?1:0)}for(;u!=p;u+=n){var j=y.charAt(u);if(x.test(j)&&(k===undefined||w.getTokenTypeAt(i(o,u+1))==k)){var s=a[j];if((s.charAt(1)==">")==(n>0)){v.push(j)}else{if(!v.length){return{pos:i(o,u),ch:j}}else{v.pop()}}}}}return o-n==(n>0?w.lastLine():w.firstLine())?false:null}function b(s,n,m){var k=s.state.matchBrackets.maxHighlightLineLength||1000;var r=[],l=s.listSelections();for(var o=0;ob.lastLine()){return null}var o=b.getTokenAt(a.Pos(k,1));if(!/\S/.test(o.string)){o=b.getTokenAt(a.Pos(k,o.end+1))}if(o.type!="keyword"||o.string!="import"){return null}for(var l=k,m=Math.min(b.lastLine(),k+10);l<=m;++l){var n=b.getLine(l),j=n.indexOf(";");if(j!=-1){return{startCh:o.end,end:a.Pos(l,j)}}}}var h=h.line,d=g(h),f;if(!d||g(h-1)||((f=g(h-2))&&f.end.line==h-1)){return null}for(var c=d.end;;){var e=g(c.line+1);if(e==null){break}c=e.end}return{from:b.clipPos(a.Pos(h,d.startCh+1)),to:c}});a.registerHelper("fold","include",function(b,g){function f(h){if(hb.lastLine()){return null}var i=b.getTokenAt(a.Pos(h,1));if(!/\S/.test(i.string)){i=b.getTokenAt(a.Pos(h,i.end+1))}if(i.type=="meta"&&i.string.slice(0,8)=="#include"){return i.start+8}}var g=g.line,d=f(g);if(d==null||f(g-1)!=null){return null}for(var c=g;;){var e=f(c+1);if(e==null){break}++c}return{from:a.Pos(g,d+1),to:b.clipPos(a.Pos(c))}})});(function(a){if(typeof exports=="object"&&typeof module=="object"){a(require("../../lib/codemirror"))}else{if(typeof define=="function"&&define.amd){define(["../../lib/codemirror"],a)}else{a(CodeMirror)}}})(function(b){function d(n,m,o,i){if(o&&o.call){var g=o;o=null}else{var g=c(n,o,"rangeFinder")}if(typeof m=="number"){m=b.Pos(m,0)}var h=c(n,o,"minFoldSize");function f(p){var q=g(n,m);if(!q||q.to.line-q.from.linen.firstLine()){m=b.Pos(m.line-1,0);k=f(false)}}if(!k||k.cleared||i==="unfold"){return}var l=e(n,o);b.on(l,"mousedown",function(p){j.clear();b.e_preventDefault(p)});var j=n.markText(k.from,k.to,{replacedWith:l,clearOnEnter:true,__isFold:true});j.on("clear",function(q,p){b.signal(n,"unfold",n,q,p)});b.signal(n,"fold",n,k.from,k.to)}function e(f,g){var h=c(f,g,"widget");if(typeof h=="string"){var i=document.createTextNode(h);h=document.createElement("span");h.appendChild(i);h.className="CodeMirror-foldmarker"}return h}b.newFoldFunction=function(g,f){return function(h,i){d(h,i,{rangeFinder:g,widget:f})}};b.defineExtension("foldCode",function(h,f,g){d(this,h,f,g)});b.defineExtension("isFolded",function(h){var g=this.findMarksAt(h);for(var f=0;f20||o.from-p.to>20){b(m)}else{m.operation(function(){if(p.fromo.to){a(m,o.to,p.to);o.to=p.to}})}},n.updateViewportTimeSpan||400)}function e(m,p){var o=m.state.foldGutter,n=p.line;if(n>=o.from&&n=q.max){return}q.ch=0;q.text=q.cm.getLine(++q.line);return true}function n(q){if(q.line<=q.min){return}q.text=q.cm.getLine(--q.line);q.ch=q.text.length;return true}function g(s){for(;;){var r=s.text.indexOf(">",s.ch);if(r==-1){if(a(s)){continue}else{return}}if(!h(s,r+1)){s.ch=r+1;continue}var q=s.text.lastIndexOf("/",r);var t=q>-1&&!/\S/.test(s.text.slice(q+1,r));s.ch=r+1;return t?"selfClose":"regular"}}function k(r){for(;;){var q=r.ch?r.text.lastIndexOf("<",r.ch-1):-1;if(q==-1){if(n(r)){continue}else{return}}if(!h(r,q+1)){r.ch=q;continue}d.lastIndex=q;r.ch=q;var s=d.exec(r.text);if(s&&s.index==q){return s}}}function p(q){for(;;){d.lastIndex=q.ch;var r=d.exec(q.text);if(!r){if(a(q)){continue}else{return}}if(!h(q,r.index+1)){q.ch=r.index+1;continue}q.ch=r.index+r[0].length;return r}}function e(s){for(;;){var r=s.ch?s.text.lastIndexOf(">",s.ch-1):-1;if(r==-1){if(n(s)){continue}else{return}}if(!h(s,r+1)){s.ch=r;continue}var q=s.text.lastIndexOf("/",r);var t=q>-1&&!/\S/.test(s.text.slice(q+1,r));s.ch=r+1;return t?"selfClose":"regular"}}function f(t,r){var q=[];for(;;){var v=p(t),s,x=t.line,w=t.ch-(v?v[0].length:0);if(!v||!(s=g(t))){return}if(s=="selfClose"){continue}if(v[1]){for(var u=q.length-1;u>=0;--u){if(q[u]==v[2]){q.length=u;break}}if(u<0&&(!r||r==v[2])){return{tag:v[2],from:m(x,w),to:m(t.line,t.ch)}}}else{q.push(v[2])}}}function c(s,r){var q=[];for(;;){var w=e(s);if(!w){return}if(w=="selfClose"){k(s);continue}var v=s.line,u=s.ch;var x=k(s);if(!x){return}if(x[1]){q.push(x[2])}else{for(var t=q.length-1;t>=0;--t){if(q[t]==x[2]){q.length=t;break}}if(t<0&&(!r||r==x[2])){return{tag:x[2],from:m(s.line,s.ch),to:m(v,u)}}}}}i.registerHelper("fold","xml",function(q,v){var s=new b(q,v.line,0);for(;;){var t=p(s),r;if(!t||s.line!=v.line||!(r=g(s))){return}if(!t[1]&&r!="selfClose"){var v=m(s.line,s.ch);var u=f(s,t[2]);return u&&{from:v,to:u.from}}}});i.findMatchingTag=function(q,x,t){var s=new b(q,x.line,x.ch,t);if(s.text.indexOf(">")==-1&&s.text.indexOf("<")==-1){return}var r=g(s),w=r&&m(s.line,s.ch);var v=r&&k(s);if(!r||!v||l(s,x)>0){return}var u={from:m(s.line,s.ch),to:w,tag:v[2]};if(r=="selfClose"){return{open:u,close:null,at:"open"}}if(v[1]){return{open:c(s,v[2]),close:u,at:"close"}}else{s=new b(q,w.line,w.ch,t);return{open:u,close:f(s,v[2]),at:"open"}}};i.findEnclosingTag=function(q,w,s){var r=new b(q,w.line,w.ch,s);for(;;){var u=c(r);if(!u){break}var t=new b(q,w.line,w.ch,s);var v=f(t,u.tag);if(v){return{open:u,close:v}}}};i.scanForClosingTag=function(q,u,t,s){var r=new b(q,u.line,u.ch,s?{from:0,to:s}:null);return f(r,t)}});(function(a){if(typeof exports=="object"&&typeof module=="object"){a(require("../../lib/codemirror"))}else{if(typeof define=="function"&&define.amd){define(["../../lib/codemirror"],a)}else{a(CodeMirror)}}})(function(a){if(!a.modeURL){a.modeURL="../mode/%N/%N.js"}var d={};function c(e,g){var f=g;return function(){if(--f==0){e()}}}function b(k,e){var j=a.modes[k].dependencies;if(!j){return e()}var h=[];for(var g=0;g100){return clearInterval(j)}if(a.modes.hasOwnProperty(k)){clearInterval(j);d[k]=null;b(k,function(){for(var l=0;l-1){o.string=m.slice(0,p)}var n=k.mode.token(o,f.inner);if(p>-1){o.string=m}if(k.innerStyle){if(n){n=n+" "+k.innerStyle}else{n=k.innerStyle}}return n}},indent:function(g,f){var h=g.innerActive?g.innerActive.mode:c;if(!h.indent){return a.Pass}return h.indent(g.innerActive?g.inner:g.outer,f)},blankLine:function(h){var j=h.innerActive?h.innerActive.mode:c;if(j.blankLine){j.blankLine(h.innerActive?h.inner:h.outer)}if(!h.innerActive){for(var g=0;g"],type:"keyToKey",toKeys:["h"]},{keys:[""],type:"keyToKey",toKeys:["l"]},{keys:[""],type:"keyToKey",toKeys:["k"]},{keys:[""],type:"keyToKey",toKeys:["j"]},{keys:[""],type:"keyToKey",toKeys:["l"]},{keys:[""],type:"keyToKey",toKeys:["h"]},{keys:[""],type:"keyToKey",toKeys:["W"]},{keys:[""],type:"keyToKey",toKeys:["B"]},{keys:[""],type:"keyToKey",toKeys:["w"]},{keys:[""],type:"keyToKey",toKeys:["b"]},{keys:[""],type:"keyToKey",toKeys:["j"]},{keys:[""],type:"keyToKey",toKeys:["k"]},{keys:[""],type:"keyToKey",toKeys:[""]},{keys:[""],type:"keyToKey",toKeys:[""]},{keys:["s"],type:"keyToKey",toKeys:["c","l"],context:"normal"},{keys:["s"],type:"keyToKey",toKeys:["x","i"],context:"visual"},{keys:["S"],type:"keyToKey",toKeys:["c","c"],context:"normal"},{keys:["S"],type:"keyToKey",toKeys:["d","c","c"],context:"visual"},{keys:[""],type:"keyToKey",toKeys:["0"]},{keys:[""],type:"keyToKey",toKeys:["$"]},{keys:[""],type:"keyToKey",toKeys:[""]},{keys:[""],type:"keyToKey",toKeys:[""]},{keys:[""],type:"keyToKey",toKeys:["j","^"],context:"normal"},{keys:["H"],type:"motion",motion:"moveToTopLine",motionArgs:{linewise:true,toJumplist:true}},{keys:["M"],type:"motion",motion:"moveToMiddleLine",motionArgs:{linewise:true,toJumplist:true}},{keys:["L"],type:"motion",motion:"moveToBottomLine",motionArgs:{linewise:true,toJumplist:true}},{keys:["h"],type:"motion",motion:"moveByCharacters",motionArgs:{forward:false}},{keys:["l"],type:"motion",motion:"moveByCharacters",motionArgs:{forward:true}},{keys:["j"],type:"motion",motion:"moveByLines",motionArgs:{forward:true,linewise:true}},{keys:["k"],type:"motion",motion:"moveByLines",motionArgs:{forward:false,linewise:true}},{keys:["g","j"],type:"motion",motion:"moveByDisplayLines",motionArgs:{forward:true}},{keys:["g","k"],type:"motion",motion:"moveByDisplayLines",motionArgs:{forward:false}},{keys:["w"],type:"motion",motion:"moveByWords",motionArgs:{forward:true,wordEnd:false}},{keys:["W"],type:"motion",motion:"moveByWords",motionArgs:{forward:true,wordEnd:false,bigWord:true}},{keys:["e"],type:"motion",motion:"moveByWords",motionArgs:{forward:true,wordEnd:true,inclusive:true}},{keys:["E"],type:"motion",motion:"moveByWords",motionArgs:{forward:true,wordEnd:true,bigWord:true,inclusive:true}},{keys:["b"],type:"motion",motion:"moveByWords",motionArgs:{forward:false,wordEnd:false}},{keys:["B"],type:"motion",motion:"moveByWords",motionArgs:{forward:false,wordEnd:false,bigWord:true}},{keys:["g","e"],type:"motion",motion:"moveByWords",motionArgs:{forward:false,wordEnd:true,inclusive:true}},{keys:["g","E"],type:"motion",motion:"moveByWords",motionArgs:{forward:false,wordEnd:true,bigWord:true,inclusive:true}},{keys:["{"],type:"motion",motion:"moveByParagraph",motionArgs:{forward:false,toJumplist:true}},{keys:["}"],type:"motion",motion:"moveByParagraph",motionArgs:{forward:true,toJumplist:true}},{keys:[""],type:"motion",motion:"moveByPage",motionArgs:{forward:true}},{keys:[""],type:"motion",motion:"moveByPage",motionArgs:{forward:false}},{keys:[""],type:"motion",motion:"moveByScroll",motionArgs:{forward:true,explicitRepeat:true}},{keys:[""],type:"motion",motion:"moveByScroll",motionArgs:{forward:false,explicitRepeat:true}},{keys:["g","g"],type:"motion",motion:"moveToLineOrEdgeOfDocument",motionArgs:{forward:false,explicitRepeat:true,linewise:true,toJumplist:true}},{keys:["G"],type:"motion",motion:"moveToLineOrEdgeOfDocument",motionArgs:{forward:true,explicitRepeat:true,linewise:true,toJumplist:true}},{keys:["0"],type:"motion",motion:"moveToStartOfLine"},{keys:["^"],type:"motion",motion:"moveToFirstNonWhiteSpaceCharacter"},{keys:["+"],type:"motion",motion:"moveByLines",motionArgs:{forward:true,toFirstChar:true}},{keys:["-"],type:"motion",motion:"moveByLines",motionArgs:{forward:false,toFirstChar:true}},{keys:["_"],type:"motion",motion:"moveByLines",motionArgs:{forward:true,toFirstChar:true,repeatOffset:-1}},{keys:["$"],type:"motion",motion:"moveToEol",motionArgs:{inclusive:true}},{keys:["%"],type:"motion",motion:"moveToMatchedSymbol",motionArgs:{inclusive:true,toJumplist:true}},{keys:["f","character"],type:"motion",motion:"moveToCharacter",motionArgs:{forward:true,inclusive:true}},{keys:["F","character"],type:"motion",motion:"moveToCharacter",motionArgs:{forward:false}},{keys:["t","character"],type:"motion",motion:"moveTillCharacter",motionArgs:{forward:true,inclusive:true}},{keys:["T","character"],type:"motion",motion:"moveTillCharacter",motionArgs:{forward:false}},{keys:[";"],type:"motion",motion:"repeatLastCharacterSearch",motionArgs:{forward:true}},{keys:[","],type:"motion",motion:"repeatLastCharacterSearch",motionArgs:{forward:false}},{keys:["'","character"],type:"motion",motion:"goToMark",motionArgs:{toJumplist:true,linewise:true}},{keys:["`","character"],type:"motion",motion:"goToMark",motionArgs:{toJumplist:true}},{keys:["]","`"],type:"motion",motion:"jumpToMark",motionArgs:{forward:true}},{keys:["[","`"],type:"motion",motion:"jumpToMark",motionArgs:{forward:false}},{keys:["]","'"],type:"motion",motion:"jumpToMark",motionArgs:{forward:true,linewise:true}},{keys:["[","'"],type:"motion",motion:"jumpToMark",motionArgs:{forward:false,linewise:true}},{keys:["]","p"],type:"action",action:"paste",isEdit:true,actionArgs:{after:true,isEdit:true,matchIndent:true}},{keys:["[","p"],type:"action",action:"paste",isEdit:true,actionArgs:{after:false,isEdit:true,matchIndent:true}},{keys:["]","character"],type:"motion",motion:"moveToSymbol",motionArgs:{forward:true,toJumplist:true}},{keys:["[","character"],type:"motion",motion:"moveToSymbol",motionArgs:{forward:false,toJumplist:true}},{keys:["|"],type:"motion",motion:"moveToColumn",motionArgs:{}},{keys:["o"],type:"motion",motion:"moveToOtherHighlightedEnd",motionArgs:{},context:"visual"},{keys:["O"],type:"motion",motion:"moveToOtherHighlightedEnd",motionArgs:{sameLine:true},context:"visual"},{keys:["d"],type:"operator",operator:"delete"},{keys:["y"],type:"operator",operator:"yank"},{keys:["c"],type:"operator",operator:"change"},{keys:[">"],type:"operator",operator:"indent",operatorArgs:{indentRight:true}},{keys:["<"],type:"operator",operator:"indent",operatorArgs:{indentRight:false}},{keys:["g","~"],type:"operator",operator:"swapcase"},{keys:["n"],type:"motion",motion:"findNext",motionArgs:{forward:true,toJumplist:true}},{keys:["N"],type:"motion",motion:"findNext",motionArgs:{forward:false,toJumplist:true}},{keys:["x"],type:"operatorMotion",operator:"delete",motion:"moveByCharacters",motionArgs:{forward:true},operatorMotionArgs:{visualLine:false}},{keys:["X"],type:"operatorMotion",operator:"delete",motion:"moveByCharacters",motionArgs:{forward:false},operatorMotionArgs:{visualLine:true}},{keys:["D"],type:"operatorMotion",operator:"delete",motion:"moveToEol",motionArgs:{inclusive:true},operatorMotionArgs:{visualLine:true}},{keys:["Y"],type:"operatorMotion",operator:"yank",motion:"moveToEol",motionArgs:{inclusive:true},operatorMotionArgs:{visualLine:true}},{keys:["C"],type:"operatorMotion",operator:"change",motion:"moveToEol",motionArgs:{inclusive:true},operatorMotionArgs:{visualLine:true}},{keys:["~"],type:"operatorMotion",operator:"swapcase",operatorArgs:{shouldMoveCursor:true},motion:"moveByCharacters",motionArgs:{forward:true}},{keys:[""],type:"action",action:"jumpListWalk",actionArgs:{forward:true}},{keys:[""],type:"action",action:"jumpListWalk",actionArgs:{forward:false}},{keys:[""],type:"action",action:"scroll",actionArgs:{forward:true,linewise:true}},{keys:[""],type:"action",action:"scroll",actionArgs:{forward:false,linewise:true}},{keys:["a"],type:"action",action:"enterInsertMode",isEdit:true,actionArgs:{insertAt:"charAfter"}},{keys:["A"],type:"action",action:"enterInsertMode",isEdit:true,actionArgs:{insertAt:"eol"}},{keys:["A"],type:"action",action:"enterInsertMode",isEdit:true,actionArgs:{insertAt:"endOfSelectedArea"},context:"visual"},{keys:["i"],type:"action",action:"enterInsertMode",isEdit:true,actionArgs:{insertAt:"inplace"}},{keys:["I"],type:"action",action:"enterInsertMode",isEdit:true,actionArgs:{insertAt:"firstNonBlank"}},{keys:["o"],type:"action",action:"newLineAndEnterInsertMode",isEdit:true,interlaceInsertRepeat:true,actionArgs:{after:true}},{keys:["O"],type:"action",action:"newLineAndEnterInsertMode",isEdit:true,interlaceInsertRepeat:true,actionArgs:{after:false}},{keys:["v"],type:"action",action:"toggleVisualMode"},{keys:["V"],type:"action",action:"toggleVisualMode",actionArgs:{linewise:true}},{keys:[""],type:"action",action:"toggleVisualMode",actionArgs:{blockwise:true}},{keys:["g","v"],type:"action",action:"reselectLastSelection"},{keys:["J"],type:"action",action:"joinLines",isEdit:true},{keys:["p"],type:"action",action:"paste",isEdit:true,actionArgs:{after:true,isEdit:true}},{keys:["P"],type:"action",action:"paste",isEdit:true,actionArgs:{after:false,isEdit:true}},{keys:["r","character"],type:"action",action:"replace",isEdit:true},{keys:["@","character"],type:"action",action:"replayMacro"},{keys:["q","character"],type:"action",action:"enterMacroRecordMode"},{keys:["R"],type:"action",action:"enterInsertMode",isEdit:true,actionArgs:{replace:true}},{keys:["u"],type:"action",action:"undo"},{keys:["u"],type:"action",action:"changeCase",actionArgs:{toLower:true},context:"visual",isEdit:true},{keys:["U"],type:"action",action:"changeCase",actionArgs:{toLower:false},context:"visual",isEdit:true},{keys:[""],type:"action",action:"redo"},{keys:["m","character"],type:"action",action:"setMark"},{keys:['"',"character"],type:"action",action:"setRegister"},{keys:["z","z"],type:"action",action:"scrollToCursor",actionArgs:{position:"center"}},{keys:["z","."],type:"action",action:"scrollToCursor",actionArgs:{position:"center"},motion:"moveToFirstNonWhiteSpaceCharacter"},{keys:["z","t"],type:"action",action:"scrollToCursor",actionArgs:{position:"top"}},{keys:["z",""],type:"action",action:"scrollToCursor",actionArgs:{position:"top"},motion:"moveToFirstNonWhiteSpaceCharacter"},{keys:["z","-"],type:"action",action:"scrollToCursor",actionArgs:{position:"bottom"}},{keys:["z","b"],type:"action",action:"scrollToCursor",actionArgs:{position:"bottom"},motion:"moveToFirstNonWhiteSpaceCharacter"},{keys:["."],type:"action",action:"repeatLastEdit"},{keys:[""],type:"action",action:"incrementNumberToken",isEdit:true,actionArgs:{increase:true,backtrack:false}},{keys:[""],type:"action",action:"incrementNumberToken",isEdit:true,actionArgs:{increase:false,backtrack:false}},{keys:["a","character"],type:"motion",motion:"textObjectManipulation"},{keys:["i","character"],type:"motion",motion:"textObjectManipulation",motionArgs:{textObjectInner:true}},{keys:["/"],type:"search",searchArgs:{forward:true,querySrc:"prompt",toJumplist:true}},{keys:["?"],type:"search",searchArgs:{forward:false,querySrc:"prompt",toJumplist:true}},{keys:["*"],type:"search",searchArgs:{forward:true,querySrc:"wordUnderCursor",wholeWordOnly:true,toJumplist:true}},{keys:["#"],type:"search",searchArgs:{forward:false,querySrc:"wordUnderCursor",wholeWordOnly:true,toJumplist:true}},{keys:["g","*"],type:"search",searchArgs:{forward:true,querySrc:"wordUnderCursor",toJumplist:true}},{keys:["g","#"],type:"search",searchArgs:{forward:false,querySrc:"wordUnderCursor",toJumplist:true}},{keys:[":"],type:"ex"}];var c=b.Pos;var d=function(){b.defineOption("vimMode",false,function(bg,bh){if(bh){bg.setOption("keyMap","vim");bg.setOption("disableInput",true);bg.setOption("showCursorWhenSelecting",false);b.signal(bg,"vim-mode-change",{mode:"normal"});bg.on("cursorActivity",Q);B(bg);b.on(bg.getInputField(),"paste",L(bg))}else{if(bg.state.vim){bg.setOption("keyMap","default");bg.setOption("disableInput",false);bg.off("cursorActivity",Q);b.off(bg.getInputField(),"paste",L(bg));bg.state.vim=null}}});function L(bg){var bh=bg.state.vim;if(!bh.onPasteFn){bh.onPasteFn=function(){if(!bh.insertMode){bg.setCursor(y(bg.getCursor(),0,1));o.enterInsertMode(bg,{},bh)}}}return bh.onPasteFn}var aL=/[\d]/;var ah=[(/\w/),(/[^\w\s]/)],a6=[(/\S/)];function ag(bj,bh){var bi=[];for(var bg=bj;bg"]);var k=[].concat(W,ad,M,["-",'"',".",":","/"]);function e(bg,bh){return bh>=bg.firstLine()&&bh<=bg.lastLine()}function z(bg){return(/^[a-z]$/).test(bg)}function G(bg){return"()[]{}".indexOf(bg)!=-1}function V(bg){return aL.test(bg)}function v(bg){return(/^[A-Z]$/).test(bg)}function J(bg){return(/^\s*$/).test(bg)}function E(bi,bg){for(var bh=0;bhbj){bm=bj}else{if(bm0?1:-1;var bp;var bo=bn.getCursor();do{bm+=bq;bs=bh[(bk+bm)%bk];if(bs&&(bp=bs.find())&&!be(bo,bp)){break}}while(bmbi)}return bs}return{cachedCursor:undefined,add:bl,move:bg}};var g=function(bg){if(bg){return{changes:bg.changes,expectCursorActivityForChange:bg.expectCursorActivityForChange}}return{changes:[],expectCursorActivityForChange:false}};function am(){this.latestRegister=undefined;this.isPlaying=false;this.isRecording=false;this.replaySearchQueries=[];this.onRecordingDone=undefined;this.lastInsertModeChanges=g()}am.prototype={exitMacroRecordMode:function(){var bg=p.macroModeState;if(bg.onRecordingDone){bg.onRecordingDone()}bg.onRecordingDone=undefined;bg.isRecording=false},enterMacroRecordMode:function(bg,bi){var bh=p.registerController.getRegister(bi);if(bh){bh.clear();this.latestRegister=bi;if(bg.openDialog){this.onRecordingDone=bg.openDialog("(recording)["+bi+"]",null,{bottom:true})}this.isRecording=true}}};function B(bg){if(!bg.state.vim){bg.state.vim={inputState:new ao(),lastEditInputState:undefined,lastEditActionCommand:undefined,lastHPos:-1,lastHSPos:-1,lastMotion:null,marks:{},fakeCursor:null,insertMode:false,insertModeRepeat:undefined,visualMode:false,visualLine:false,visualBlock:false,lastSelection:null,lastPastedText:null,awaitingEscapeSecondCharacter:false}}return bg.state.vim}var p;function u(){p={searchQuery:null,searchIsReversed:false,lastSubstituteReplacePart:undefined,jumpList:af(),macroModeState:new am,lastChararacterSearch:{increment:0,forward:true,selectedCharacter:""},registerController:new Y({}),searchHistoryController:new aQ({}),exCommandHistoryController:new aQ({})};for(var bg in aj){var bh=aj[bg];bh.value=bh.defaultValue}}var aD={buildKeyMap:function(){},getRegisterController:function(){return p.registerController},resetVimGlobalState_:u,getVimGlobalState_:function(){return p},maybeInitVimState_:B,InsertModeKey:a3,map:function(bh,bi,bg){l.map(bh,bi,bg)},setOption:ax,getOption:n,defineOption:az,defineEx:function(bg,bi,bh){if(bg.indexOf(bi)!==0){throw new Error('(Vim.defineEx) "'+bi+'" is not a prefix of "'+bg+'", command not registered')}aR[bg]=bh;l.commandMap_[bi]={name:bg,shortName:bi,type:"api"}},handleKey:function(bg,bj){var bl;var bh=B(bg);var bk=p.macroModeState;if(bk.isRecording){if(bj=="q"){bk.exitMacroRecordMode();i(bg);return}}if(bj==""){i(bg);if(bh.visualMode){aG(bg)}return}if(!bh.visualMode&&!be(bg.getCursor("head"),bg.getCursor("anchor"))){bh.visualMode=true;bh.visualLine=false;b.signal(bg,"vim-mode-change",{mode:"visual"});bg.on("mousedown",aG)}if(bj!="0"||(bj=="0"&&bh.inputState.getRepeat()===0)){bl=aW.matchCommand(bj,a,bh)}if(!bl){if(V(bj)){bh.inputState.pushRepeatDigit(bj)}if(bk.isRecording){D(bk,bj)}return}if(bl.type=="keyToKey"){for(var bi=0;bi0||this.motionRepeat.length>0){bg=1;if(this.prefixRepeat.length>0){bg*=parseInt(this.prefixRepeat.join(""),10)}if(this.motionRepeat.length>0){bg*=parseInt(this.motionRepeat.join(""),10)}}return bg};function i(bg,bh){bg.state.vim.inputState=new ao();b.signal(bg,"vim-command-done",bh)}function a7(bi,bh,bg){this.clear();this.keyBuffer=[bi||""];this.insertModeChanges=[];this.searchQueries=[];this.linewise=!!bh;this.blockwise=!!bg}a7.prototype={setText:function(bi,bh,bg){this.keyBuffer=[bi||""];this.linewise=!!bh;this.blockwise=!!bg},pushText:function(bh,bg){if(bg){if(!this.linewise){this.keyBuffer.push("\n")}this.linewise=true}this.keyBuffer.push(bh)},pushInsertModeChanges:function(bg){this.insertModeChanges.push(g(bg))},pushSearchQuery:function(bg){this.searchQueries.push(bg)},clear:function(){this.keyBuffer=[];this.insertModeChanges=[];this.searchQueries=[];this.linewise=false},toString:function(){return this.keyBuffer.join("")}};function Y(bg){this.registers=bg;this.unnamedRegister=bg['"']=new a7();bg["."]=new a7();bg[":"]=new a7();bg["/"]=new a7()}Y.prototype={pushText:function(bk,bh,bm,bl,bi){if(bl&&bm.charAt(0)=="\n"){bm=bm.slice(1)+"\n"}if(bl&&bm.charAt(bm.length-1)!=="\n"){bm+="\n"}var bj=this.isValidRegister(bk)?this.getRegister(bk):null;if(!bj){switch(bh){case"yank":this.registers["0"]=new a7(bm,bl,bi);break;case"delete":case"change":if(bm.indexOf("\n")==-1){this.registers["-"]=new a7(bm,bl)}else{this.shiftNumericRegisters_();this.registers["1"]=new a7(bm,bl)}break}this.unnamedRegister.setText(bm,bl,bi);return}var bg=v(bk);if(bg){bj.pushText(bm,bl)}else{bj.setText(bm,bl,bi)}this.unnamedRegister.setText(bj.toString(),bl)},getRegister:function(bg){if(!this.isValidRegister(bg)){return this.unnamedRegister}bg=bg.toLowerCase();if(!this.registers[bg]){this.registers[bg]=new a7()}return this.registers[bg]},isValidRegister:function(bg){return bg&&E(bg,k)},shiftNumericRegisters_:function(){for(var bg=9;bg>=2;bg--){this.registers[bg]=this.getRegister(""+(bg-1))}}};function aQ(){this.historyBuffer=[];this.iterator;this.initialPrefix=null}aQ.prototype={nextMatch:function(bh,bg){var bm=this.historyBuffer;var bj=bg?-1:1;if(this.initialPrefix===null){this.initialPrefix=bh}for(var bl=this.iterator+bj;bg?bl>=0:bl=bm.length){this.iterator=bm.length;return this.initialPrefix}if(bl<0){return bh}},pushInput:function(bg){var bh=this.historyBuffer.indexOf(bg);if(bh>-1){this.historyBuffer.splice(bh,1)}if(bg.length){this.historyBuffer.push(bg)}},reset:function(){this.initialPrefix=null;this.iterator=this.historyBuffer.length}};var aW={matchCommand:function(br,bq,bj){var bn=bj.inputState;var bs=bn.keyBuffer.concat(br);var bm=[];var bg;for(var bk=0;bk1){switch(bg){case"":bg="\n";break;case"":bg=" ";break;default:continue}}}bm.push(bi)}}function bp(bt){if(bs.length",onKeyDown:bi})}else{aO(bg,{onClose:bj,prefix:":",onKeyDown:bi})}}},evalInput:function(bp,bG){var bv=bG.inputState;var bD=bv.motion;var bw=bv.motionArgs||{};var bq=bv.operator;var bM=bv.operatorArgs||{};var bx=bv.registerName;var bh=x(bp.getCursor("head"));var bE=x(bp.getCursor("anchor"));var bn=x(bh);var bu=x(bn);var bH;var br;if(bq){this.recordLastEdit(bG,bv)}if(bv.repeatOverride!==undefined){br=bv.repeatOverride}else{br=bv.getRepeat()}if(br>0&&bw.explicitRepeat){bw.repeatIsExplicit=true}else{if(bw.noRepeat||(!bw.explicitRepeat&&br===0)){br=1;bw.repeatIsExplicit=false}}if(bv.selectedCharacter){bw.selectedCharacter=bM.selectedCharacter=bv.selectedCharacter}bw.repeat=br;i(bp);if(bD){var bF=aP[bD](bp,bw,bG);bG.lastMotion=aP[bD];if(!bF){return}if(bw.toJumplist){var bL=p.jumpList;var bs=bL.cachedCursor;if(bs){a0(bp,bs,bF);delete bL.cachedCursor}else{a0(bp,bu,bF)}}if(bF instanceof Array){bn=bF[0];bH=bF[1]}else{bH=bF}if(!bH){bH=c(bn.line,bn.ch)}if(bG.visualMode){var bl=0;if(aC(bE,bh)&&(be(bE,bH)||aC(bH,bE))){bE.ch+=1;bl=-1}else{if(aC(bh,bE)&&(be(bE,bH)||aC(bE,bH))){bE.ch-=1;bl=1}}if(!bG.visualBlock&&!(bF instanceof Array)){bH.ch+=bl}if(bG.lastHPos!=Infinity){bG.lastHPos=bH.ch}bh=bH;bE=(bF instanceof Array)?bn:bE;if(bG.visualLine){if(aC(bE,bh)){bE.ch=0;var bg=bp.lastLine();if(bh.line>bg){bh.line=bg}bh.ch=aJ(bp,bh.line)}else{bh.ch=0;bE.ch=aJ(bp,bE.line)}}else{if(bG.visualBlock){bE=A(bp,bh)}}if(!bG.visualBlock){bp.setSelection(bE,bh)}aF(bp,bG,"<",aC(bE,bh)?bE:bh);aF(bp,bG,">",aC(bE,bh)?bh:bE)}else{if(!bq){bH=P(bp,bH);bp.setCursor(bH.line,bH.ch)}}}if(bq){var bA=false;bG.lastMotion=null;var bt=bG.lastSelection;bM.repeat=br;if(bG.visualMode){bn=bE;bH=bh;bw.inclusive=true;bM.shouldMoveCursor=false}if(bH&&aC(bH,bn)){var bK=bn;bn=bH;bH=bK;bA=true}else{if(!bH){bH=x(bn)}}if(bw.inclusive&&!bG.visualMode){bH.ch++}if(bM.selOffset){bH.line=bn.line+bM.selOffset.line;if(bM.selOffset.line){bH.ch=bM.selOffset.ch}else{bH.ch=bn.ch+bM.selOffset.ch}if(bt&&bt.visualBlock){var bo=bt.visualBlock;var bC=bo.width;var bB=bo.height;bH=c(bn.line+bB,bn.ch+bC);var bi=[];for(var bI=bn.line;bIbm&&bn.line==bm)){return}if(bh.toFirstChar){bj=aN(bl.getLine(bo));bi.lastHPos=bj}bi.lastHSPos=bl.charCoords(c(bo,bj),"div").left;return c(bo,bj)},moveByDisplayLines:function(bn,bi,bj){var bo=bn.getCursor();switch(bj.lastMotion){case this.moveByDisplayLines:case this.moveByScroll:case this.moveByLines:case this.moveToColumn:case this.moveToEol:break;default:bj.lastHSPos=bn.charCoords(bo,"div").left}var bg=bi.repeat;var bm=bn.findPosV(bo,(bi.forward?bg:-bg),"line",bj.lastHSPos);if(bm.hitSide){if(bi.forward){var bh=bn.charCoords(bm,"div");var bk={top:bh.top+8,left:bj.lastHSPos};var bm=bn.coordsChar(bk,"div")}else{var bl=bn.charCoords(c(bn.firstLine(),0),"div");bl.left=bj.lastHSPos;bm=bn.coordsChar(bl,"div")}}bj.lastHPos=bm.ch;return bm},moveByPage:function(bh,bi){var bg=bh.getCursor();var bj=bi.repeat;return bh.findPosV(bg,(bi.forward?bj:-bj),"page")},moveByParagraph:function(bg,bi){var bh=bg.getCursor().line;var bk=bi.repeat;var bl=bi.forward?1:-1;for(var bj=0;bj"]?bt.marks[">"].find():bp.getCursor("head");p.registerController.pushText(bx.registerName,"change",bq,bx.linewise);if(bx.linewise){if(bw){var bu=bo.line;while(bu<=bv.line){var br=aJ(bp,bu);var bl=c(bu,br);var bm=c(bu,bo.ch);bu++;bp.replaceRange("",bm,bl)}}else{bs="\n";if(bv.line==bo.line&&bv.line==bp.lastLine()){bs=""}bp.replaceRange(bs,bo,bv);bp.indentLine(bo.line,"smart");bo.ch=null;bp.setCursor(bo)}}else{var bq=bp.getRange(bo,bv);if(!J(bq)){var bn=(/\s+$/).exec(bq);if(bn){bv=y(bv,0,-bn[0].length)}}if(bw){bp.replaceSelections(bs)}else{bp.setCursor(bo);bp.replaceRange("",bo,bv)}}bt.marks[">"]=bp.setBookmark(bg);o.enterInsertMode(bp,{},bp.state.vim)},"delete":function(bs,bl,bn){var bj=bs.listSelections();var bi=bj[0],bm=bj[bj.length-1];var bp=aC(bi.anchor,bi.head)?bi.anchor:bi.head;var bt=aC(bm.anchor,bm.head)?bm.head:bm.anchor;var bv,br;var bq=bn.visualBlock;if(bn.visualMode){bv=bn.marks[">"].find();br=bn.marks["<"].find()}else{if(bn.lastSelection){bv=bn.lastSelection.curStartMark.find();br=bn.lastSelection.curEndMark.find();bq=bn.lastSelection.visualBlock}}var bu=bs.getSelection();p.registerController.pushText(bl.registerName,"delete",bu,bl.linewise,bq);var bk=new Array(bj.length).join("1").split("1");if(bl.linewise&&bt.line==bs.lastLine()&&bp.line==bt.line){var bo=x(bt);bp.line--;bp.ch=aJ(bs,bp.line);bt=bo;bs.replaceRange("",bp,bt)}else{bs.replaceSelections(bk)}if(bv){var bh=bs.setBookmark(br);var bg=bs.setBookmark(bv);if(bn.visualMode){bn.marks["<"]=bh;bn.marks[">"]=bg}else{bn.lastSelection.curStartMark=bh;bn.lastSelection.curEndMark=bg}}if(bl.linewise){bs.setCursor(aP.moveToFirstNonWhiteSpaceCharacter(bs))}else{bs.setCursor(bp)}},indent:function(bn,bi,bk,bm,bo){var bp=bm.line;var bh=bo.line;var bg=(bk.visualMode)?bi.repeat:1;if(bi.linewise){bh--}for(var bl=bp;bl<=bh;bl++){for(var bj=0;bjbj.top){bq.line+=(bl-bj.top)/bn;bq.line=Math.ceil(bq.line);bo.setCursor(bq);bj=bo.charCoords(bq,"local");bo.scrollTo(null,bj.top)}else{bo.scrollTo(null,bl)}}else{var bh=bl+bo.getScrollInfo().clientHeight;if(bh",aC(bg,bl)?bl:bg)},reselectLastSelection:function(bm,bi,bh){var bj=bh.marks["<"].find();var bn=bh.marks[">"].find();var bg=bh.lastSelection;if(bg){var bl=bg.curStartMark.find();var bo=bg.curEndMark.find();var bk=bg.visualBlock;aZ(bm,bh,bj,bn);if(bk){bm.setCursor(bl);bl=A(bm,bo)}else{bm.setSelection(bl,bo);bl=bm.getCursor("anchor");bo=bm.getCursor("head")}if(bh.visualMode){aF(bm,bh,"<",aC(bl,bo)?bl:bo);aF(bm,bh,">",aC(bl,bo)?bo:bl)}bh.visualMode=true;if(bg.visualLine){bh.visualLine=true;bh.visualBlock=false}else{if(bg.visualBlock){bh.visualLine=false;bh.visualBlock=true}else{bh.visualBlock=bh.visualLine=false}}b.signal(bm,"vim-mode-change",{mode:"visual",subMode:bh.visualLine?"linewise":""})}},joinLines:function(bh,bi,bj){var bg,bl;if(bj.visualMode){bg=bh.getCursor("anchor");bl=bh.getCursor("head");bl.ch=aJ(bh,bl.line)-1}else{var bk=Math.max(bi.repeat,2);bg=bh.getCursor();bl=P(bh,c(bg.line+bk-1,Infinity))}var bm=0;bh.operation(function(){for(var bp=bg.line;bp1){var bx=Array(bt.repeat+1).join(bx)}var bq=bh.linewise;var bs=bh.blockwise;if(bq){if(bB.visualMode){bx=bB.visualLine?bx.slice(0,-1):"\n"+bx.slice(0,bx.length-1)+"\n"}else{if(bt.after){bx="\n"+bx.slice(0,bx.length-1);bn.ch=aJ(bu,bn.line)}else{bn.ch=0}}}else{if(bs){bx=bx.split("\n");for(var bC=0;bCbu.lastLine()){bu.replaceRange("\n",c(bv,0))}var bE=aJ(bu,bv);if(bEbq.length){bm=bq.length}bp=c(bn.line,bm)}if(bj=="\n"){if(!bk.visualMode){bo.replaceRange("",bn,bp)}(b.commands.newlineAndIndentContinueComment||b.commands.newlineAndIndent)(bo)}else{var bg=bo.getRange(bn,bp);bg=bg.replace(/[^\n]/g,bj);if(bk.visualBlock){var bl=new Array(bo.options.tabSize+1).join(" ");bg=bo.getSelection();bg=bg.replace(/\t/g,bl).replace(/[^\n]/g,bj).split("\n");bo.replaceSelections(bg)}else{bo.replaceRange(bg,bn,bp)}if(bk.visualMode){bn=aC(bh[0].anchor,bh[0].head)?bh[0].anchor:bh[0].head;bo.setCursor(bn);aG(bo)}else{bo.setCursor(y(bp,0,-1))}}},incrementNumberToken:function(bq,bh){var br=bq.getCursor();var bm=bq.getLine(br.line);var bt=/-?\d+/g;var bl;var bg;var bk;var bs;var bi;while((bl=bt.exec(bm))!==null){bi=bl[0];bg=bl.index;bk=bg+bi.length;if(br.chbv.line){bw="down"}else{if(bh.ch!=bv.ch){bw=bh.ch>bv.ch?"right":"left"}bu=br.getCursor("anchor")}}var bx=q(bi,bv);bh=br.clipPos(bh);var bs=q(bi,bh)<0?false:true;var by=!be(bo,bh);var bj=function(){if(by){if(bv.ch>=bu.ch){bu.ch++}}else{if(bv.ch==aJ(br,bv.line)){if(be(bi[bx].anchor,bi[bx].head)&&bi.length>1){if(bw=="up"){if(bs||bx>0){bm=bp.line;bk=bh.line;bu=bi[bx-1].anchor}}else{if(bs||bx==0){bk=bg.line;bm=bh.line;bu=bi[bx+1].anchor}}if(bh.ch>=bu.ch){bu.ch--}}}}};switch(bw){case"up":bm=bs?bp.line:bh.line;bk=bs?bh.line:bg.line;bu=bg;bj();break;case"down":bm=bs?bh.line:bp.line;bk=bs?bg.line:bh.line;bu=bp;bj();break;case"left":if((bh.ch<=bu.ch)&&(bv.ch>bu.ch)){bu.ch++;bh.ch--}break;case"right":if((bu.ch<=bh.ch)&&(bv.ch"].find()||bm.getCursor("head")}if(bk.lastPastedText){bn=bm.posFromIndex(bm.indexFromPos(bl)+bk.lastPastedText.length);bk.lastPastedText=null}var bg=bm.listSelections();var bi=q(bg,bl,"head")>-1;if(bk.visualBlock){var bo=Math.abs(bl.line-bn.line)+1;var bh=Math.abs(bl.ch-bn.ch);var bj={height:bo,width:bh}}bk.lastSelection={curStartMark:bm.setBookmark(bi?bn:bl),curEndMark:bm.setBookmark(bi?bl:bn),visualMode:bk.visualMode,visualLine:bk.visualLine,visualBlock:bj}}function aG(bg){bg.off("mousedown",aG);var bh=bg.state.vim;var bi=bg.getCursor("anchor");var bj=bg.getCursor("head");if(bh.visualBlock&&(aC(bi,bj))){bj.ch--}aZ(bg,bh);bh.visualMode=false;bh.visualLine=false;bh.visualBlock=false;if(!be(bi,bj)){bg.setCursor(P(bg,bj))}b.signal(bg,"vim-mode-change",{mode:"normal"});if(bh.fakeCursor){bh.fakeCursor.clear()}}function ac(bh,bg,bl){var bk=bh.getRange(bg,bl);if(/\n\s*$/.test(bk)){var bj=bk.split("\n");bj.pop();var bi;for(var bi=bj.pop();bj.length>0&&bi&&J(bi);bi=bj.pop()){bl.line--;bl.ch=0}if(bi){bl.line--;bl.ch=aJ(bh,bl.line)}else{bl.ch=0}}}function aY(bh,bg,bi){bg.ch=0;bi.ch=0;bi.line++}function aN(bh){if(!bh){return 0}var bg=bh.search(/\S/);return bg==-1?bh.length:bg}function at(bp,bl,bz,bh,bA){var bj=bp.getCursor();var bs=bp.getLine(bj.line);var bv=bj.ch;var bu=bs.substring(bv);var bw;if(bA){bw=bu.search(/\w/)}else{bw=bu.search(/\S/)}if(bw==-1){return null}bv+=bw;bu=bs.substring(bv);var by=bs.substring(0,bv);var bB;if(bh){bB=/^\S+/}else{if((/\w/).test(bs.charAt(bv))){bB=/^\w+/}else{bB=/^[^\w\s]+/}}var bm=bB.exec(bu);var bt=bv;var bi=bv+bm[0].length;var bk=j(by);var bq=bB.exec(bk);if(bq){bt-=bq[0].length}if(bl){var br=bs.substring(bi);var bg=br.match(/^\s*/)[0].length;if(bg>0){bi+=bg}else{var bo=bk.length-bt;var bn=bk.substring(bo);var bx=bn.match(/^\s*/)[0].length;bt-=bx}}return{start:c(bj.line,bt),end:c(bj.line,bi)}}function a0(bg,bh,bi){if(!be(bh,bi)){p.jumpList.add(bg,bh,bi)}}function aq(bg,bh){p.lastChararacterSearch.increment=bg;p.lastChararacterSearch.forward=bh.forward;p.lastChararacterSearch.selectedCharacter=bh.selectedCharacter}var K={"(":"bracket",")":"bracket","{":"bracket","}":"bracket","[":"section","]":"section","*":"comment","/":"comment",m:"method",M:"method","#":"preprocess"};var aM={bracket:{isComplete:function(bg){if(bg.nextCh===bg.symb){bg.depth++;if(bg.depth>=1){return true}}else{if(bg.nextCh===bg.reverseSymb){bg.depth--}}return false}},section:{init:function(bg){bg.curMoveThrough=true;bg.symb=(bg.forward?"]":"[")===bg.symb?"{":"}"},isComplete:function(bg){return bg.index===0&&bg.nextCh===bg.symb}},comment:{isComplete:function(bh){var bg=bh.lastCh==="*"&&bh.nextCh==="/";bh.lastCh=bh.nextCh;return bg}},method:{init:function(bg){bg.symb=(bg.symb==="m"?"{":"}");bg.reverseSymb=bg.symb==="{"?"}":"{"},isComplete:function(bg){if(bg.nextCh===bg.symb){return true}return false}},preprocess:{init:function(bg){bg.index=0},isComplete:function(bh){if(bh.nextCh==="#"){var bg=bh.lineText.match(/#(\w+)/)[1];if(bg==="endif"){if(bh.forward&&bh.depth===0){return true}bh.depth++}else{if(bg==="if"){if(!bh.forward&&bh.depth===0){return true}bh.depth--}}if(bg==="else"&&bh.depth===0){return true}}return false}}};function ba(bp,bh,bk,bi){var bs=x(bp.getCursor());var bq=bk?1:-1;var bj=bk?bp.lineCount():-1;var bo=bs.ch;var bu=bs.line;var bn=bp.getLine(bu);var bg={lineText:bn,nextCh:bn.charAt(bo),lastCh:null,index:bo,symb:bi,reverseSymb:(bk?{")":"(","}":"{"}:{"(":")","{":"}"})[bi],forward:bk,depth:0,curMoveThrough:false};var bl=K[bi];if(!bl){return bs}var bt=aM[bl].init;var br=aM[bl].isComplete;if(bt){bt(bg)}while(bu!==bj&&bh){bg.index+=bq;bg.nextCh=bg.lineText.charAt(bg.index);if(!bg.nextCh){bu+=bq;bg.lineText=bp.getLine(bu)||"";if(bq>0){bg.index=0}else{var bm=bg.lineText.length;bg.index=(bm>0)?(bm-1):0}bg.nextCh=bg.lineText.charAt(bg.index)}if(br(bg)){bs.line=bu;bs.ch=bg.index;bh--}}if(bg.nextCh||bg.curMoveThrough){return c(bu,bg.index)}return bs}function bc(bq,br,bj,bo,bp){var bk=br.line;var bn=br.ch;var bu=bq.getLine(bk);var bh=bj?1:-1;var bl=bo?a6:ah;if(bp&&bu==""){bk+=bh;bu=bq.getLine(bk);if(!e(bq,bk)){return null}bn=(bj)?0:bu.length}while(true){if(bp&&bu==""){return{from:0,to:0,line:bk}}var bm=(bh>0)?bu.length:-1;var bt=bm,bs=bm;while(bn!=bm){var bg=false;for(var bi=0;bi0)?0:bu.length}throw new Error("The impossible happened.")}function ap(bq,bh,bl,bu,bo){var bs=bq.getCursor();var bm=x(bs);var bn=[];if(bl&&!bu||!bl&&bu){bh++}var bp=!(bl&&bu);for(var bj=0;bjbk.ch)||(bh.line>bk.line)){var bm=bh;bh=bk;bk=bm}if(bo){bk.ch+=1}else{bh.ch+=1}return{start:bh,end:bk}}function aE(bo,bi,bn){var bp=x(bo.getCursor());var bq=bo.getLine(bp.line);var bm=bq.split("");var bh,bj,bk,bl;var bg=bm.indexOf(bi);if(bp.ch-1&&!bh;bk--){if(bm[bk]==bi){bh=bk+1}}}if(bh&&!bj){for(bk=bh,bl=bm.length;bk'+bh+"",{bottom:true,duration:5000})}else{alert(bh)}}function av(bh,bi){var bg="";if(bh){bg+=''+bh+""}bg+=' ';if(bi){bg+='';bg+=bi;bg+=""}return bg}var I="(Javascript regexp)";function aO(bh,bi){var bj=(bi.prefix||"")+" "+(bi.desc||"");var bg=av(bi.prefix,bi.desc);R(bh,bg,bj,bi.onClose,bi)}function O(bh,bg){if(bh instanceof RegExp&&bg instanceof RegExp){var bj=["global","multiline","ignoreCase","source"];for(var bi=0;bi=bh&&bi<=bg)}else{return bi==bh}}}function aX(bg){var bj=bg.getScrollInfo();var bi=6;var bm=10;var bl=bg.coordsChar({left:0,top:bi+bj.top},"local");var bh=bj.clientHeight-bm+bj.top;var bk=bg.coordsChar({left:0,top:bh},"local");return{top:bl.line,bottom:bk.line}}var w=[{name:"map"},{name:"nmap",shortName:"nm"},{name:"vmap",shortName:"vm"},{name:"unmap"},{name:"write",shortName:"w"},{name:"undo",shortName:"u"},{name:"redo",shortName:"red"},{name:"set",shortName:"set"},{name:"sort",shortName:"sor"},{name:"substitute",shortName:"s",possiblyAsync:true},{name:"nohlsearch",shortName:"noh"},{name:"delmarks",shortName:"delm"},{name:"registers",shortName:"reg",excludeFromCommandHistory:true},{name:"global",shortName:"g"}];d.ExCommandDispatcher=function(){this.buildCommandMap_()};d.ExCommandDispatcher.prototype={processCommand:function(br,bq,bh){var bl=br.state.vim;var bi=p.registerController.getRegister(":");var bo=bi.toString();if(bl.visualMode){aG(br)}var bg=new b.StringStream(bq);bi.setText(bq);var bk=bh||{};bk.input=bq;try{this.parseInput_(br,bg,bk)}catch(bp){a4(br,bp);throw bp}var bj;var bn;if(!bk.commandName){if(bk.line!==undefined){bn="move"}}else{bj=this.matchCommand_(bk.commandName);if(bj){bn=bj.name;if(bj.excludeFromCommandHistory){bi.setText(bo)}this.parseCommandArgs_(bg,bk,bj);if(bj.type=="exToKey"){for(var bm=0;bm0;bg--){var bi=bh.substring(0,bg);if(this.commandMap_[bi]){var bj=this.commandMap_[bi];if(bj.name.indexOf(bh)===0){return bj}}}return null},buildCommandMap_:function(){this.commandMap_={};for(var bh=0;bh|<\w+>|./).exec(bj);if(bg===null){break}bh=bg[0];bj=bj.substring(bg.index+bh.length);bi.push(bh)}return bi}var aR={map:function(bg,bj,bh){var bi=bj.args;if(!bi||bi.length<2){if(bg){a4(bg,"Invalid mapping: "+bj.input)}return}l.map(bi[0],bi[1],bh)},nmap:function(bg,bh){this.map(bg,bh,"normal")},vmap:function(bg,bh){this.map(bg,bh,"visual")},unmap:function(bg,bj,bh){var bi=bj.args;if(!bi||bi.length<1){if(bg){a4(bg,"No such mapping: "+bj.input)}return}l.unmap(bi[0],bh)},move:function(bg,bh){aW.processCommand(bg,bg.state.vim,{type:"motion",motion:"moveToLineOrEdgeOfDocument",motionArgs:{forward:false,explicitRepeat:true,linewise:true},repeatOverride:bh.line+1})},set:function(bo,bl){var bi=bl.args;if(!bi||bi.length<1){if(bo){a4(bo,"Invalid mapping: "+bl.input)}return}var bm=bi[0].split("=");var bh=bm[0];var bn=bm[1];var bk=false;if(bh.charAt(bh.length-1)=="?"){if(bn){throw Error("Trailing characters: "+bl.argString)}bh=bh.substring(0,bh.length-1);bk=true}if(bn===undefined&&bh.substring(0,2)=="no"){bh=bh.substring(2);bn=false}var bj=aj[bh]&&aj[bh].type=="boolean";if(bj&&bn==undefined){bn=true}if(!bj&&!bn||bk){var bg=n(bh);if(bg===true||bg===false){a4(bo," "+(bg?"":"no")+bh)}else{a4(bo," "+bh+"="+bg)}}else{ax(bh,bn)}},registers:function(bl,bh){var bn=bh.args;var bk=p.registerController.registers;var bi="----------Registers----------

";if(!bn){for(var bg in bk){var bo=bk[bg].toString();if(bo.length){bi+='"'+bg+" "+bo+"
"}}}else{var bg;bn=bn.join("");for(var bj=0;bj"}}a4(bl,bi)},sort:function(bp,bz){var bq,bj,bh,bi;function bk(){if(bz.argString){var bD=new b.StringStream(bz.argString);if(bD.eat("!")){bq=true}if(bD.eol()){return}if(!bD.eatSpace()){return"Invalid arguments"}var bF=bD.match(/[a-z]+/);if(bF){bF=bF[0];bj=bF.indexOf("i")!=-1;bh=bF.indexOf("u")!=-1;var bC=bF.indexOf("d")!=-1&&1;var bE=bF.indexOf("x")!=-1&&1;var bB=bF.indexOf("o")!=-1&&1;if(bC+bE+bB>1){return"Invalid arguments"}bi=bC&&"decimal"||bE&&"hex"||bB&&"octal"}if(bD.eatSpace()&&bD.match(/\/.*\//)){"patterns not supported"}}}var bl=bk();if(bl){a4(bp,bl+": "+bz.argString);return}var bu=bz.line||bp.firstLine();var by=bz.lineEnd||bz.line||bp.lastLine();if(bu==by){return}var bo=c(bu,0);var bw=c(by,aJ(bp,by));var bt=bp.getRange(bo,bw).split("\n");var bm=(bi=="decimal")?/(-?)([\d]+)/:(bi=="hex")?/(-?)(?:0x)?([0-9a-f]+)/i:(bi=="octal")?/([0-7]+)/:null;var bn=(bi=="decimal")?10:(bi=="hex")?16:(bi=="octal")?8:null;var br=[],bv=[];if(bi){for(var bx=0;bx"}}if(!bj){a4(bt,bp);return}var bo=0;var bu=function(){if(bo=bp){a4(bq,"Invalid argument: "+bl.argString.substring(bo));return}for(var bm=0;bm<=bp-bh;bm++){var bk=String.fromCharCode(bh+bm);delete bg.marks[bk]}}else{a4(bq,"Invalid argument: "+bj+"-");return}}else{delete bg.marks[bi]}}}};var l=new d.ExCommandDispatcher();function aT(bu,bh,bj,bp,bn,bi,br,bl,bv){bu.state.vim.exMode=true;var bm=false;var bt=bi.from();function bq(){bu.operation(function(){while(!bm){bk();bo()}bs()})}function bk(){var bx=bu.getRange(bi.from(),bi.to());var bw=bx.replace(br,bl);bi.replace(bw)}function bo(){var bw;while(bw=bi.findNext()&&T(bi.from(),bp,bn)){if(!bj&&bt&&bi.from().line==bt.line){continue}bu.scrollIntoView(bi.from(),30);bu.setSelection(bi.from(),bi.to());bt=bi.from();bm=false;return}bm=true}function bs(bx){if(bx){bx()}bu.focus();if(bt){bu.setCursor(bt);var bw=bu.state.vim;bw.exMode=false;bw.lastHPos=bw.lastHSPos=bt.ch}if(bv){bv()}}function bg(bz,bw,bA){b.e_stop(bz);var bx=b.keyName(bz);switch(bx){case"Y":bk();bo();break;case"N":bo();break;case"A":var by=bv;bv=undefined;bu.operation(bq);bv=by;break;case"L":bk();case"Q":case"Esc":case"Ctrl-C":case"Ctrl-[":bs(bA);break}if(bm){bs(bA)}}bo();if(bm){a4(bu,"No matches for "+br.source);return}if(!bh){bq();if(bv){bv()}return}aO(bu,{prefix:"replace with "+bl+" (y/n/a/q/l)",onKeyDown:bg})}function ar(){function bi(bm,bl){var bk=bm;if(v(bk)&&bl=="Ctrl"){bk=bk.toLowerCase()}if(bl){bk=bl.charAt(0)+"-"+bk}var bn=({Enter:"CR",Backspace:"BS",Delete:"Del"})[bk];bk=bn?bn:bk;bk=bk.length>1?"<"+bk+">":bk;return bk}function bh(bk){return function(bl){b.signal(bl,"vim-keypress",bk);b.Vim.handleKey(bl,bk)}}var bg={nofallthrough:true,style:"fat-cursor"};function bj(bp,bl){for(var bo=0;bo1){t(bo,bh,bh.insertModeRepeat-1,true);bh.lastEditInputState.repeatOverride=bh.insertModeRepeat}delete bh.insertModeRepeat;bh.insertMode=false;bo.setCursor(bo.getCursor().line,bo.getCursor().ch-1);bo.setOption("keyMap","vim");bo.setOption("disableInput",true);bo.toggleOverwrite(false);bm.setText(bk.changes.join(""));b.signal(bo,"vim-mode-change",{mode:"normal"});if(bj.isRecording){ae(bj)}}az("enableInsertModeEscKeys",false,"boolean");az("insertModeEscKeys","kj","string");az("insertModeEscKeysTimeout",200,"number");function X(bg){return function(bh){var bj=n("insertModeEscKeys");var bi=bj&&bj.length>1&&bj.charAt(0);if(!n("enableInsertModeEscKeys")||bi!==bg){return b.Pass}else{bh.replaceRange(bg,bh.getCursor(),bh.getCursor(),"+input");bh.setOption("keyMap","await-second");bh.state.vim.awaitingEscapeSecondCharacter=true;setTimeout(function(){if(bh.state.vim.awaitingEscapeSecondCharacter){bh.state.vim.awaitingEscapeSecondCharacter=false;bh.setOption("keyMap","vim-insert")}},n("insertModeEscKeysTimeout"))}}}function ak(bg){return function(bh){var bj=n("insertModeEscKeys");var bk=bj&&bj.length>1&&bj.charAt(1);if(!n("enableInsertModeEscKeys")||bk!==bg){return b.Pass}else{if(bh.state.vim.insertMode){var bi=p.macroModeState.lastInsertModeChanges;if(bi&&bi.changes.length){bi.changes.pop()}}bh.state.vim.awaitingEscapeSecondCharacter=false;bh.replaceRange("",{ch:bh.getCursor().ch-1,line:bh.getCursor().line},bh.getCursor(),"+input");r(bh)}}}b.keyMap["vim-insert"]={Esc:r,"Ctrl-[":r,"Ctrl-C":r,"Ctrl-N":"autocomplete","Ctrl-P":"autocomplete",Enter:function(bg){var bh=b.commands.newlineAndIndentContinueComment||b.commands.newlineAndIndent;bh(bg)},"'i'":X("i"),"'j'":X("j"),"'k'":X("k"),fallthrough:["default"]};b.keyMap["await-second"]={"'i'":ak("i"),"'j'":ak("j"),"'k'":ak("k"),fallthrough:["vim-insert"]};b.keyMap["vim-replace"]={Backspace:"goCharLeft",fallthrough:["vim-insert"]};function C(bo,bi,bj,bg){var bq=p.registerController.getRegister(bg);var bh=bq.keyBuffer;var bm=0;bj.isPlaying=true;bj.replaySearchQueries=bq.searchQueries.slice(0);for(var bk=0;bk|<\w+>|./).exec(br);bp=bl[0];br=br.substring(bl.index+bp.length);b.Vim.handleKey(bo,bp);if(bi.insertMode){var bn=bq.insertModeChanges[bm++].changes;p.macroModeState.lastInsertModeChanges.changes=bn;ai(bo,bn,1);r(bo)}}}bj.isPlaying=false}function D(bj,bg){if(bj.isPlaying){return}var bi=bj.latestRegister;var bh=p.registerController.getRegister(bi);if(bh){bh.pushText(bg)}}function ae(bi){if(bi.isPlaying){return}var bh=bi.latestRegister;var bg=p.registerController.getRegister(bh);if(bg){bg.pushInsertModeChanges(bi.lastInsertModeChanges)}}function H(bj,bi){if(bj.isPlaying){return}var bh=bj.latestRegister;var bg=p.registerController.getRegister(bh);if(bg){bg.pushSearchQuery(bi)}}function a1(bh,bg){var bj=p.macroModeState;var bi=bj.lastInsertModeChanges;if(!bj.isPlaying){while(bg){bi.expectCursorActivityForChange=true;if(bg.origin=="+input"||bg.origin=="paste"||bg.origin===undefined){var bk=bg.text.join("\n");bi.changes.push(bk)}bg=bg.next}}}function Q(bn){var bg=bn.state.vim;if(bg.insertMode){var bh=p.macroModeState;if(bh.isPlaying){return}var bi=bh.lastInsertModeChanges;if(bi.expectCursorActivityForChange){bi.expectCursorActivityForChange=false}else{bi.changes=[]}}else{if(bn.doc.history.lastSelOrigin=="*mouse"){bg.lastHPos=bn.doc.getCursor().ch;if(bn.somethingSelected()){bg.visualMode=true}}}if(bg.visualMode){var bl,bk;bl=bk=bn.getCursor("head");var bj=bn.getCursor("anchor");var bm=c(bk.line,bl.ch+(aC(bj,bk)?-1:1));if(aC(bm,bl)){var bo=bl;bl=bm;bm=bo}if(bg.fakeCursor){bg.fakeCursor.clear()}bg.fakeCursor=bn.markText(bl,bm,{className:"cm-animate-fat-cursor"})}}function a3(bg){this.keyName=bg}function N(bk){var bj=p.macroModeState;var bi=bj.lastInsertModeChanges;var bh=b.keyName(bk);function bg(){bi.changes.push(new a3(bh));return true}if(bh.indexOf("Delete")!=-1||bh.indexOf("Backspace")!=-1){b.lookupKey(bh,["vim-insert"],bg)}}function t(bo,bj,bh,bg){var bl=p.macroModeState;bl.isPlaying=true;var bp=!!bj.lastEditActionCommand;var bm=bj.inputState;function bi(){if(bp){aW.processAction(bo,bj,bj.lastEditActionCommand)}else{aW.evalInput(bo,bj)}}function bn(br){if(bl.lastInsertModeChanges.changes.length>0){br=!bj.lastEditActionCommand?1:br;var bq=bl.lastInsertModeChanges;ai(bo,bq.changes,br)}}bj.inputState=bj.lastEditInputState;if(bp&&bj.lastEditActionCommand.interlaceInsertRepeat){for(var bk=0;bk=p.ch+1){return/\bstring2?\b/.test(l)}o.start=o.pos}}function b(l){var m={name:"autoCloseBrackets",Backspace:function(n){if(n.getOption("disableInput")){return c.Pass}var o=n.listSelections();for(var p=0;p=0;p--){var r=o[p].head;n.replaceRange("",f(r.line,r.ch-1),f(r.line,r.ch+1))}}};var k="";for(var j=0;j1&&p.getRange(f(w.line,w.ch-2),w)==o+o&&(w.ch<=2||p.getRange(f(w.line,w.ch-3),f(w.line,w.ch-2))!=o)){s="addFour"}else{if(o=='"'||o=="'"){if(!c.isWordChar(u)&&e(p,w,o)){s="both"}else{return c.Pass}}else{if(p.getLine(w.line).length==w.ch||k.indexOf(u)>=0||i.test(u)){s="both"}else{return c.Pass}}}}}if(!v){v=s}else{if(v!=s){return c.Pass}}}p.operation(function(){if(v=="skip"){p.execCommand("goCharRight")}else{if(v=="skipThree"){for(var y=0;y<3;y++){p.execCommand("goCharRight")}}else{if(v=="surround"){var x=p.getSelections();for(var y=0;y'"]=function(l){return a(l)}}h.addKeyMap(j)});var d=["area","base","br","col","command","embed","hr","img","input","keygen","link","meta","param","source","track","wbr"];var c=["applet","blockquote","body","button","div","dl","fieldset","form","frameset","h1","h2","h3","h4","h5","h6","head","html","iframe","layer","legend","object","ol","p","select","table","ul"];function a(w){if(w.getOption("disableInput")){return b.Pass}var j=w.listSelections(),q=[];for(var r=0;rv.ch){p=p.slice(0,p.length-x.end+v.ch)}var t=p.toLowerCase();if(!p||x.type=="string"&&(x.end!=v.ch||!/[\"\']/.test(x.string.charAt(x.string.length-1))||x.string.length==1)||x.type=="tag"&&h.type=="closeTag"||x.string.indexOf("/")==(x.string.length-1)||m&&g(m,t)>-1||f(w,p,v,h,true)){return b.Pass}var o=u&&g(u,t)>-1;q[r]={indent:o,text:">"+(o?"\n\n":"")+"",newPos:o?b.Pos(v.line+1,0):b.Pos(v.line,v.ch+1)}}for(var r=j.length-1;r>=0;r--){var n=q[r];w.replaceRange(n.text,j[r].head,j[r].anchor,"+insert");var l=w.listSelections().slice(0);l[r]={head:n.newPos,anchor:n.newPos};w.setSelections(l);if(n.indent){w.indentLine(n.newPos.line,null,true);w.indentLine(n.newPos.line+1,null,true)}}}function e(h){if(h.getOption("disableInput")){return b.Pass}var j=h.listSelections(),n=[];for(var m=0;m"}else{if(h.getMode().name=="htmlmixed"&&k.mode.name=="css"){n[m]="/style>"}else{return b.Pass}}}else{if(!o.context||!o.context.tagName||f(h,o.context.tagName,p,o)){return b.Pass}n[m]="/"+o.context.tagName+">"}}h.replaceSelections(n);j=h.listSelections();for(var m=0;m",")":"(<","[":"]>","]":"[<","{":"}>","}":"{<"};function f(q,m,p,k){var s=q.getLineHandle(m.line),o=m.ch-1;var n=(o>=0&&a[s.text.charAt(o)])||a[s.text.charAt(++o)];if(!n){return null}var l=n.charAt(1)==">"?1:-1;if(p&&(l>0)!=(o==m.ch)){return null}var j=q.getTokenTypeAt(i(m.line,o+1));var r=g(q,i(m.line,o+(l>0?1:0)),l,j||null,k);if(r==null){return null}return{from:i(m.line,o),to:r&&r.pos,match:r&&r.ch==n.charAt(0),forward:l>0}}function g(w,r,n,k,m){var l=(m&&m.maxScanLineLength)||10000;var t=(m&&m.maxScanLines)||1000;var v=[];var x=m&&m.bracketRegex?m.bracketRegex:/[(){}[\]]/;var q=n>0?Math.min(r.line+t,w.lastLine()+1):Math.max(w.firstLine()-1,r.line-t);for(var o=r.line;o!=q;o+=n){var y=w.getLine(o);if(!y){continue}var u=n>0?0:y.length-1,p=n>0?y.length:-1;if(y.length>l){continue}if(o==r.line){u=r.ch-(n<0?1:0)}for(;u!=p;u+=n){var j=y.charAt(u);if(x.test(j)&&(k===undefined||w.getTokenTypeAt(i(o,u+1))==k)){var s=a[j];if((s.charAt(1)==">")==(n>0)){v.push(j)}else{if(!v.length){return{pos:i(o,u),ch:j}}else{v.pop()}}}}}return o-n==(n>0?w.lastLine():w.firstLine())?false:null}function b(s,n,m){var k=s.state.matchBrackets.maxHighlightLineLength||1000;var r=[],l=s.listSelections();for(var o=0;ob.lastLine()){return null}var o=b.getTokenAt(a.Pos(k,1));if(!/\S/.test(o.string)){o=b.getTokenAt(a.Pos(k,o.end+1))}if(o.type!="keyword"||o.string!="import"){return null}for(var l=k,m=Math.min(b.lastLine(),k+10);l<=m;++l){var n=b.getLine(l),j=n.indexOf(";");if(j!=-1){return{startCh:o.end,end:a.Pos(l,j)}}}}var h=h.line,d=g(h),f;if(!d||g(h-1)||((f=g(h-2))&&f.end.line==h-1)){return null}for(var c=d.end;;){var e=g(c.line+1);if(e==null){break}c=e.end}return{from:b.clipPos(a.Pos(h,d.startCh+1)),to:c}});a.registerHelper("fold","include",function(b,g){function f(h){if(hb.lastLine()){return null}var i=b.getTokenAt(a.Pos(h,1));if(!/\S/.test(i.string)){i=b.getTokenAt(a.Pos(h,i.end+1))}if(i.type=="meta"&&i.string.slice(0,8)=="#include"){return i.start+8}}var g=g.line,d=f(g);if(d==null||f(g-1)!=null){return null}for(var c=g;;){var e=f(c+1);if(e==null){break}++c}return{from:a.Pos(g,d+1),to:b.clipPos(a.Pos(c))}})});(function(a){if(typeof exports=="object"&&typeof module=="object"){a(require("../../lib/codemirror"))}else{if(typeof define=="function"&&define.amd){define(["../../lib/codemirror"],a)}else{a(CodeMirror)}}})(function(b){function d(n,m,o,i){if(o&&o.call){var g=o;o=null}else{var g=c(n,o,"rangeFinder")}if(typeof m=="number"){m=b.Pos(m,0)}var h=c(n,o,"minFoldSize");function f(p){var q=g(n,m);if(!q||q.to.line-q.from.linen.firstLine()){m=b.Pos(m.line-1,0);k=f(false)}}if(!k||k.cleared||i==="unfold"){return}var l=e(n,o);b.on(l,"mousedown",function(p){j.clear();b.e_preventDefault(p)});var j=n.markText(k.from,k.to,{replacedWith:l,clearOnEnter:true,__isFold:true});j.on("clear",function(q,p){b.signal(n,"unfold",n,q,p)});b.signal(n,"fold",n,k.from,k.to)}function e(f,g){var h=c(f,g,"widget");if(typeof h=="string"){var i=document.createTextNode(h);h=document.createElement("span");h.appendChild(i);h.className="CodeMirror-foldmarker"}return h}b.newFoldFunction=function(g,f){return function(h,i){d(h,i,{rangeFinder:g,widget:f})}};b.defineExtension("foldCode",function(h,f,g){d(this,h,f,g)});b.defineExtension("isFolded",function(h){var g=this.findMarksAt(h);for(var f=0;f20||o.from-p.to>20){b(m)}else{m.operation(function(){if(p.fromo.to){a(m,o.to,p.to);o.to=p.to}})}},n.updateViewportTimeSpan||400)}function e(m,p){var o=m.state.foldGutter,n=p.line;if(n>=o.from&&n=q.max){return}q.ch=0;q.text=q.cm.getLine(++q.line);return true}function n(q){if(q.line<=q.min){return}q.text=q.cm.getLine(--q.line);q.ch=q.text.length;return true}function g(s){for(;;){var r=s.text.indexOf(">",s.ch);if(r==-1){if(a(s)){continue}else{return}}if(!h(s,r+1)){s.ch=r+1;continue}var q=s.text.lastIndexOf("/",r);var t=q>-1&&!/\S/.test(s.text.slice(q+1,r));s.ch=r+1;return t?"selfClose":"regular"}}function k(r){for(;;){var q=r.ch?r.text.lastIndexOf("<",r.ch-1):-1;if(q==-1){if(n(r)){continue}else{return}}if(!h(r,q+1)){r.ch=q;continue}d.lastIndex=q;r.ch=q;var s=d.exec(r.text);if(s&&s.index==q){return s}}}function p(q){for(;;){d.lastIndex=q.ch;var r=d.exec(q.text);if(!r){if(a(q)){continue}else{return}}if(!h(q,r.index+1)){q.ch=r.index+1;continue}q.ch=r.index+r[0].length;return r}}function e(s){for(;;){var r=s.ch?s.text.lastIndexOf(">",s.ch-1):-1;if(r==-1){if(n(s)){continue}else{return}}if(!h(s,r+1)){s.ch=r;continue}var q=s.text.lastIndexOf("/",r);var t=q>-1&&!/\S/.test(s.text.slice(q+1,r));s.ch=r+1;return t?"selfClose":"regular"}}function f(t,r){var q=[];for(;;){var v=p(t),s,x=t.line,w=t.ch-(v?v[0].length:0);if(!v||!(s=g(t))){return}if(s=="selfClose"){continue}if(v[1]){for(var u=q.length-1;u>=0;--u){if(q[u]==v[2]){q.length=u;break}}if(u<0&&(!r||r==v[2])){return{tag:v[2],from:m(x,w),to:m(t.line,t.ch)}}}else{q.push(v[2])}}}function c(s,r){var q=[];for(;;){var w=e(s);if(!w){return}if(w=="selfClose"){k(s);continue}var v=s.line,u=s.ch;var x=k(s);if(!x){return}if(x[1]){q.push(x[2])}else{for(var t=q.length-1;t>=0;--t){if(q[t]==x[2]){q.length=t;break}}if(t<0&&(!r||r==x[2])){return{tag:x[2],from:m(s.line,s.ch),to:m(v,u)}}}}}i.registerHelper("fold","xml",function(q,v){var s=new b(q,v.line,0);for(;;){var t=p(s),r;if(!t||s.line!=v.line||!(r=g(s))){return}if(!t[1]&&r!="selfClose"){var v=m(s.line,s.ch);var u=f(s,t[2]);return u&&{from:v,to:u.from}}}});i.findMatchingTag=function(q,x,t){var s=new b(q,x.line,x.ch,t);if(s.text.indexOf(">")==-1&&s.text.indexOf("<")==-1){return}var r=g(s),w=r&&m(s.line,s.ch);var v=r&&k(s);if(!r||!v||l(s,x)>0){return}var u={from:m(s.line,s.ch),to:w,tag:v[2]};if(r=="selfClose"){return{open:u,close:null,at:"open"}}if(v[1]){return{open:c(s,v[2]),close:u,at:"close"}}else{s=new b(q,w.line,w.ch,t);return{open:u,close:f(s,v[2]),at:"open"}}};i.findEnclosingTag=function(q,w,s){var r=new b(q,w.line,w.ch,s);for(;;){var u=c(r);if(!u){break}var t=new b(q,w.line,w.ch,s);var v=f(t,u.tag);if(v){return{open:u,close:v}}}};i.scanForClosingTag=function(q,u,t,s){var r=new b(q,u.line,u.ch,s?{from:0,to:s}:null);return f(r,t)}});(function(a){if(typeof exports=="object"&&typeof module=="object"){a(require("../../lib/codemirror"),"cjs")}else{if(typeof define=="function"&&define.amd){define(["../../lib/codemirror"],function(b){a(b,"amd")})}else{a(CodeMirror,"plain")}}})(function(a,c){if(!a.modeURL){a.modeURL="../mode/%N/%N.js"}var e={};function d(f,h){var g=h;return function(){if(--g==0){f()}}}function b(l,f){var k=a.modes[l].dependencies;if(!k){return f()}var j=[];for(var h=0;h-1){o.string=m.slice(0,p)}var n=k.mode.token(o,f.inner);if(p>-1){o.string=m}if(k.innerStyle){if(n){n=n+" "+k.innerStyle}else{n=k.innerStyle}}return n}},indent:function(g,f){var h=g.innerActive?g.innerActive.mode:c;if(!h.indent){return a.Pass}return h.indent(g.innerActive?g.inner:g.outer,f)},blankLine:function(h){var j=h.innerActive?h.innerActive.mode:c;if(j.blankLine){j.blankLine(h.innerActive?h.inner:h.outer)}if(!h.innerActive){for(var g=0;g",type:"keyToKey",toKeys:"h"},{keys:"",type:"keyToKey",toKeys:"l"},{keys:"",type:"keyToKey",toKeys:"k"},{keys:"",type:"keyToKey",toKeys:"j"},{keys:"",type:"keyToKey",toKeys:"l"},{keys:"",type:"keyToKey",toKeys:"h"},{keys:"",type:"keyToKey",toKeys:"W"},{keys:"",type:"keyToKey",toKeys:"B"},{keys:"",type:"keyToKey",toKeys:"w"},{keys:"",type:"keyToKey",toKeys:"b"},{keys:"",type:"keyToKey",toKeys:"j"},{keys:"",type:"keyToKey",toKeys:"k"},{keys:"",type:"keyToKey",toKeys:""},{keys:"",type:"keyToKey",toKeys:""},{keys:"",type:"keyToKey",toKeys:"",context:"insert"},{keys:"",type:"keyToKey",toKeys:"",context:"insert"},{keys:"s",type:"keyToKey",toKeys:"cl",context:"normal"},{keys:"s",type:"keyToKey",toKeys:"xi",context:"visual"},{keys:"S",type:"keyToKey",toKeys:"cc",context:"normal"},{keys:"S",type:"keyToKey",toKeys:"dcc",context:"visual"},{keys:"",type:"keyToKey",toKeys:"0"},{keys:"",type:"keyToKey",toKeys:"$"},{keys:"",type:"keyToKey",toKeys:""},{keys:"",type:"keyToKey",toKeys:""},{keys:"",type:"keyToKey",toKeys:"j^",context:"normal"},{keys:"H",type:"motion",motion:"moveToTopLine",motionArgs:{linewise:true,toJumplist:true}},{keys:"M",type:"motion",motion:"moveToMiddleLine",motionArgs:{linewise:true,toJumplist:true}},{keys:"L",type:"motion",motion:"moveToBottomLine",motionArgs:{linewise:true,toJumplist:true}},{keys:"h",type:"motion",motion:"moveByCharacters",motionArgs:{forward:false}},{keys:"l",type:"motion",motion:"moveByCharacters",motionArgs:{forward:true}},{keys:"j",type:"motion",motion:"moveByLines",motionArgs:{forward:true,linewise:true}},{keys:"k",type:"motion",motion:"moveByLines",motionArgs:{forward:false,linewise:true}},{keys:"gj",type:"motion",motion:"moveByDisplayLines",motionArgs:{forward:true}},{keys:"gk",type:"motion",motion:"moveByDisplayLines",motionArgs:{forward:false}},{keys:"w",type:"motion",motion:"moveByWords",motionArgs:{forward:true,wordEnd:false}},{keys:"W",type:"motion",motion:"moveByWords",motionArgs:{forward:true,wordEnd:false,bigWord:true}},{keys:"e",type:"motion",motion:"moveByWords",motionArgs:{forward:true,wordEnd:true,inclusive:true}},{keys:"E",type:"motion",motion:"moveByWords",motionArgs:{forward:true,wordEnd:true,bigWord:true,inclusive:true}},{keys:"b",type:"motion",motion:"moveByWords",motionArgs:{forward:false,wordEnd:false}},{keys:"B",type:"motion",motion:"moveByWords",motionArgs:{forward:false,wordEnd:false,bigWord:true}},{keys:"ge",type:"motion",motion:"moveByWords",motionArgs:{forward:false,wordEnd:true,inclusive:true}},{keys:"gE",type:"motion",motion:"moveByWords",motionArgs:{forward:false,wordEnd:true,bigWord:true,inclusive:true}},{keys:"{",type:"motion",motion:"moveByParagraph",motionArgs:{forward:false,toJumplist:true}},{keys:"}",type:"motion",motion:"moveByParagraph",motionArgs:{forward:true,toJumplist:true}},{keys:"",type:"motion",motion:"moveByPage",motionArgs:{forward:true}},{keys:"",type:"motion",motion:"moveByPage",motionArgs:{forward:false}},{keys:"",type:"motion",motion:"moveByScroll",motionArgs:{forward:true,explicitRepeat:true}},{keys:"",type:"motion",motion:"moveByScroll",motionArgs:{forward:false,explicitRepeat:true}},{keys:"gg",type:"motion",motion:"moveToLineOrEdgeOfDocument",motionArgs:{forward:false,explicitRepeat:true,linewise:true,toJumplist:true}},{keys:"G",type:"motion",motion:"moveToLineOrEdgeOfDocument",motionArgs:{forward:true,explicitRepeat:true,linewise:true,toJumplist:true}},{keys:"0",type:"motion",motion:"moveToStartOfLine"},{keys:"^",type:"motion",motion:"moveToFirstNonWhiteSpaceCharacter"},{keys:"+",type:"motion",motion:"moveByLines",motionArgs:{forward:true,toFirstChar:true}},{keys:"-",type:"motion",motion:"moveByLines",motionArgs:{forward:false,toFirstChar:true}},{keys:"_",type:"motion",motion:"moveByLines",motionArgs:{forward:true,toFirstChar:true,repeatOffset:-1}},{keys:"$",type:"motion",motion:"moveToEol",motionArgs:{inclusive:true}},{keys:"%",type:"motion",motion:"moveToMatchedSymbol",motionArgs:{inclusive:true,toJumplist:true}},{keys:"f",type:"motion",motion:"moveToCharacter",motionArgs:{forward:true,inclusive:true}},{keys:"F",type:"motion",motion:"moveToCharacter",motionArgs:{forward:false}},{keys:"t",type:"motion",motion:"moveTillCharacter",motionArgs:{forward:true,inclusive:true}},{keys:"T",type:"motion",motion:"moveTillCharacter",motionArgs:{forward:false}},{keys:";",type:"motion",motion:"repeatLastCharacterSearch",motionArgs:{forward:true}},{keys:",",type:"motion",motion:"repeatLastCharacterSearch",motionArgs:{forward:false}},{keys:"'",type:"motion",motion:"goToMark",motionArgs:{toJumplist:true,linewise:true}},{keys:"`",type:"motion",motion:"goToMark",motionArgs:{toJumplist:true}},{keys:"]`",type:"motion",motion:"jumpToMark",motionArgs:{forward:true}},{keys:"[`",type:"motion",motion:"jumpToMark",motionArgs:{forward:false}},{keys:"]'",type:"motion",motion:"jumpToMark",motionArgs:{forward:true,linewise:true}},{keys:"['",type:"motion",motion:"jumpToMark",motionArgs:{forward:false,linewise:true}},{keys:"]p",type:"action",action:"paste",isEdit:true,actionArgs:{after:true,isEdit:true,matchIndent:true}},{keys:"[p",type:"action",action:"paste",isEdit:true,actionArgs:{after:false,isEdit:true,matchIndent:true}},{keys:"]",type:"motion",motion:"moveToSymbol",motionArgs:{forward:true,toJumplist:true}},{keys:"[",type:"motion",motion:"moveToSymbol",motionArgs:{forward:false,toJumplist:true}},{keys:"|",type:"motion",motion:"moveToColumn"},{keys:"o",type:"motion",motion:"moveToOtherHighlightedEnd",context:"visual"},{keys:"O",type:"motion",motion:"moveToOtherHighlightedEnd",motionArgs:{sameLine:true},context:"visual"},{keys:"d",type:"operator",operator:"delete"},{keys:"y",type:"operator",operator:"yank"},{keys:"c",type:"operator",operator:"change"},{keys:">",type:"operator",operator:"indent",operatorArgs:{indentRight:true}},{keys:"<",type:"operator",operator:"indent",operatorArgs:{indentRight:false}},{keys:"g~",type:"operator",operator:"changeCase"},{keys:"gu",type:"operator",operator:"changeCase",operatorArgs:{toLower:true},isEdit:true},{keys:"gU",type:"operator",operator:"changeCase",operatorArgs:{toLower:false},isEdit:true},{keys:"n",type:"motion",motion:"findNext",motionArgs:{forward:true,toJumplist:true}},{keys:"N",type:"motion",motion:"findNext",motionArgs:{forward:false,toJumplist:true}},{keys:"x",type:"operatorMotion",operator:"delete",motion:"moveByCharacters",motionArgs:{forward:true},operatorMotionArgs:{visualLine:false}},{keys:"X",type:"operatorMotion",operator:"delete",motion:"moveByCharacters",motionArgs:{forward:false},operatorMotionArgs:{visualLine:true}},{keys:"D",type:"operatorMotion",operator:"delete",motion:"moveToEol",motionArgs:{inclusive:true},context:"normal"},{keys:"D",type:"operator",operator:"delete",operatorArgs:{linewise:true},context:"visual"},{keys:"Y",type:"operatorMotion",operator:"yank",motion:"moveToEol",motionArgs:{inclusive:true},context:"normal"},{keys:"Y",type:"operator",operator:"yank",operatorArgs:{linewise:true},context:"visual"},{keys:"C",type:"operatorMotion",operator:"change",motion:"moveToEol",motionArgs:{inclusive:true},context:"normal"},{keys:"C",type:"operator",operator:"change",operatorArgs:{linewise:true},context:"visual"},{keys:"~",type:"operatorMotion",operator:"changeCase",motion:"moveByCharacters",motionArgs:{forward:true},operatorArgs:{shouldMoveCursor:true},context:"normal"},{keys:"~",type:"operator",operator:"changeCase",context:"visual"},{keys:"",type:"operatorMotion",operator:"delete",motion:"moveByWords",motionArgs:{forward:false,wordEnd:false},context:"insert"},{keys:"",type:"action",action:"jumpListWalk",actionArgs:{forward:true}},{keys:"",type:"action",action:"jumpListWalk",actionArgs:{forward:false}},{keys:"",type:"action",action:"scroll",actionArgs:{forward:true,linewise:true}},{keys:"",type:"action",action:"scroll",actionArgs:{forward:false,linewise:true}},{keys:"a",type:"action",action:"enterInsertMode",isEdit:true,actionArgs:{insertAt:"charAfter"},context:"normal"},{keys:"A",type:"action",action:"enterInsertMode",isEdit:true,actionArgs:{insertAt:"eol"},context:"normal"},{keys:"A",type:"action",action:"enterInsertMode",isEdit:true,actionArgs:{insertAt:"endOfSelectedArea"},context:"visual"},{keys:"i",type:"action",action:"enterInsertMode",isEdit:true,actionArgs:{insertAt:"inplace"},context:"normal"},{keys:"I",type:"action",action:"enterInsertMode",isEdit:true,actionArgs:{insertAt:"firstNonBlank"},context:"normal"},{keys:"I",type:"action",action:"enterInsertMode",isEdit:true,actionArgs:{insertAt:"startOfSelectedArea"},context:"visual"},{keys:"o",type:"action",action:"newLineAndEnterInsertMode",isEdit:true,interlaceInsertRepeat:true,actionArgs:{after:true},context:"normal"},{keys:"O",type:"action",action:"newLineAndEnterInsertMode",isEdit:true,interlaceInsertRepeat:true,actionArgs:{after:false},context:"normal"},{keys:"v",type:"action",action:"toggleVisualMode"},{keys:"V",type:"action",action:"toggleVisualMode",actionArgs:{linewise:true}},{keys:"",type:"action",action:"toggleVisualMode",actionArgs:{blockwise:true}},{keys:"gv",type:"action",action:"reselectLastSelection"},{keys:"J",type:"action",action:"joinLines",isEdit:true},{keys:"p",type:"action",action:"paste",isEdit:true,actionArgs:{after:true,isEdit:true}},{keys:"P",type:"action",action:"paste",isEdit:true,actionArgs:{after:false,isEdit:true}},{keys:"r",type:"action",action:"replace",isEdit:true},{keys:"@",type:"action",action:"replayMacro"},{keys:"q",type:"action",action:"enterMacroRecordMode"},{keys:"R",type:"action",action:"enterInsertMode",isEdit:true,actionArgs:{replace:true}},{keys:"u",type:"action",action:"undo",context:"normal"},{keys:"u",type:"operator",operator:"changeCase",operatorArgs:{toLower:true},context:"visual",isEdit:true},{keys:"U",type:"operator",operator:"changeCase",operatorArgs:{toLower:false},context:"visual",isEdit:true},{keys:"",type:"action",action:"redo"},{keys:"m",type:"action",action:"setMark"},{keys:'"',type:"action",action:"setRegister"},{keys:"zz",type:"action",action:"scrollToCursor",actionArgs:{position:"center"}},{keys:"z.",type:"action",action:"scrollToCursor",actionArgs:{position:"center"},motion:"moveToFirstNonWhiteSpaceCharacter"},{keys:"zt",type:"action",action:"scrollToCursor",actionArgs:{position:"top"}},{keys:"z",type:"action",action:"scrollToCursor",actionArgs:{position:"top"},motion:"moveToFirstNonWhiteSpaceCharacter"},{keys:"z-",type:"action",action:"scrollToCursor",actionArgs:{position:"bottom"}},{keys:"zb",type:"action",action:"scrollToCursor",actionArgs:{position:"bottom"},motion:"moveToFirstNonWhiteSpaceCharacter"},{keys:".",type:"action",action:"repeatLastEdit"},{keys:"",type:"action",action:"incrementNumberToken",isEdit:true,actionArgs:{increase:true,backtrack:false}},{keys:"",type:"action",action:"incrementNumberToken",isEdit:true,actionArgs:{increase:false,backtrack:false}},{keys:"a",type:"motion",motion:"textObjectManipulation"},{keys:"i",type:"motion",motion:"textObjectManipulation",motionArgs:{textObjectInner:true}},{keys:"/",type:"search",searchArgs:{forward:true,querySrc:"prompt",toJumplist:true}},{keys:"?",type:"search",searchArgs:{forward:false,querySrc:"prompt",toJumplist:true}},{keys:"*",type:"search",searchArgs:{forward:true,querySrc:"wordUnderCursor",wholeWordOnly:true,toJumplist:true}},{keys:"#",type:"search",searchArgs:{forward:false,querySrc:"wordUnderCursor",wholeWordOnly:true,toJumplist:true}},{keys:"g*",type:"search",searchArgs:{forward:true,querySrc:"wordUnderCursor",toJumplist:true}},{keys:"g#",type:"search",searchArgs:{forward:false,querySrc:"wordUnderCursor",toJumplist:true}},{keys:":",type:"ex"}];var c=b.Pos;var g=[16,17,18,91];var d={Enter:"CR",Backspace:"BS",Delete:"Del"};var f=/Mac/.test(navigator.platform);var e=function(){function a2(bD){var bC=bD.keyCode;if(g.indexOf(bC)!=-1){return}var bB=bD.ctrlKey||bD.metaKey;var bA=b.keyNames[bC];bA=d[bA]||bA;var bz="";if(bD.ctrlKey){bz+="C-"}if(bD.altKey){bz+="A-"}if(f&&bD.metaKey||(!bB&&bD.shiftKey)&&bA.length<2){return}else{if(bD.shiftKey&&!/^[A-Za-z]$/.test(bA)){bz+="S-"}}if(bA.length==1){bA=bA.toLowerCase()}bz+=bA;if(bz.length>1){bz="<"+bz+">"}return bz}function Y(bz,bB){var bA=a2(bB);if(!bA){return}b.signal(bz,"vim-keypress",bA);if(b.Vim.handleKey(bz,bA,"user")){b.e_stop(bB)}}function Q(bz,bC){var bB=bC.charCode||bC.keyCode;if(bC.ctrlKey||bC.metaKey||bC.altKey||bC.shiftKey&&bB<32){return}var bA=String.fromCharCode(bB);b.signal(bz,"vim-keypress",bA);if(b.Vim.handleKey(bz,bA,"user")){b.e_stop(bC)}}function aW(bz){bz.setOption("disableInput",true);bz.setOption("showCursorWhenSelecting",false);b.signal(bz,"vim-mode-change",{mode:"normal"});bz.on("cursorActivity",ae);J(bz);b.on(bz.getInputField(),"paste",X(bz));bz.on("keypress",Q);bz.on("keydown",Y)}function aT(bz){bz.setOption("disableInput",false);bz.off("cursorActivity",ae);b.off(bz.getInputField(),"paste",X(bz));bz.state.vim=null;bz.off("keypress",Q);bz.off("keydown",Y)}function k(bz,bA){if(this==b.keyMap.vim){b.rmClass(bz.getWrapperElement(),"cm-fat-cursor")}if(!bA||bA.attach!=v){aT(bz,false)}}function v(bz,bA){if(this==b.keyMap.vim){b.addClass(bz.getWrapperElement(),"cm-fat-cursor")}if(!bA||bA.attach!=v){aW(bz)}}b.defineOption("vimMode",false,function(bz,bB,bA){if(bB&&bz.getOption("keyMap")!="vim"){bz.setOption("keyMap","vim")}else{if(!bB&&bA!=b.Init&&/^vim/.test(bz.getOption("keyMap"))){bz.setOption("keyMap","default")}}});function X(bz){var bA=bz.state.vim;if(!bA.onPasteFn){bA.onPasteFn=function(){if(!bA.insertMode){bz.setCursor(G(bz.getCursor(),0,1));s.enterInsertMode(bz,{},bA)}}}return bA.onPasteFn}var a0=/[\d]/;var av=[(/\w/),(/[^\w\s]/)],bn=[(/\S/)];function au(bC,bA){var bB=[];for(var bz=bC;bz"]);var o=[].concat(al,aq,Z,["-",'"',".",":","/"]);function i(bz,bA){return bA>=bz.firstLine()&&bA<=bz.lastLine()}function H(bz){return(/^[a-z]$/).test(bz)}function P(bz){return"()[]{}".indexOf(bz)!=-1}function ak(bz){return a0.test(bz)}function D(bz){return(/^[A-Z]$/).test(bz)}function W(bz){return(/^\s*$/).test(bz)}function M(bB,bz){for(var bA=0;bAbC){bF=bC}else{if(bF0?1:-1;var bI;var bH=bG.getCursor();do{bF+=bJ;bL=bA[(bD+bF)%bD];if(bL&&(bI=bL.find())&&!bw(bH,bI)){break}}while(bFbB)}return bL}return{cachedCursor:undefined,add:bE,move:bz}};var l=function(bz){if(bz){return{changes:bz.changes,expectCursorActivityForChange:bz.expectCursorActivityForChange}}return{changes:[],expectCursorActivityForChange:false}};function aB(){this.latestRegister=undefined;this.isPlaying=false;this.isRecording=false;this.replaySearchQueries=[];this.onRecordingDone=undefined;this.lastInsertModeChanges=l()}aB.prototype={exitMacroRecordMode:function(){var bz=t.macroModeState;if(bz.onRecordingDone){bz.onRecordingDone()}bz.onRecordingDone=undefined;bz.isRecording=false},enterMacroRecordMode:function(bz,bB){var bA=t.registerController.getRegister(bB);if(bA){bA.clear();this.latestRegister=bB;if(bz.openDialog){this.onRecordingDone=bz.openDialog("(recording)["+bB+"]",null,{bottom:true})}this.isRecording=true}}};function J(bz){if(!bz.state.vim){bz.state.vim={inputState:new aD(),lastEditInputState:undefined,lastEditActionCommand:undefined,lastHPos:-1,lastHSPos:-1,lastMotion:null,marks:{},fakeCursor:null,insertMode:false,insertModeRepeat:undefined,visualMode:false,visualLine:false,visualBlock:false,lastSelection:null,lastPastedText:null,sel:{}}}return bz.state.vim}var t;function C(){t={searchQuery:null,searchIsReversed:false,lastSubstituteReplacePart:undefined,jumpList:at(),macroModeState:new aB,lastChararacterSearch:{increment:0,forward:true,selectedCharacter:""},registerController:new am({}),searchHistoryController:new a5({}),exCommandHistoryController:new a5({})};for(var bz in ax){var bA=ax[bz];bA.value=bA.defaultValue}}var bu;var aQ={buildKeyMap:function(){},getRegisterController:function(){return t.registerController},resetVimGlobalState_:C,getVimGlobalState_:function(){return t},maybeInitVimState_:J,InsertModeKey:bk,map:function(bA,bB,bz){p.map(bA,bB,bz)},setOption:aK,getOption:r,defineOption:aM,defineEx:function(bz,bB,bA){if(bz.indexOf(bB)!==0){throw new Error('(Vim.defineEx) "'+bB+'" is not a prefix of "'+bz+'", command not registered')}a6[bz]=bA;p.commandMap_[bB]={name:bz,shortName:bB,type:"api"}},handleKey:function(bE,bF,bD){var bB=J(bE);function bG(){var bI=t.macroModeState;if(bI.isRecording){if(bF=="q"){bI.exitMacroRecordMode();m(bE);return true}if(bD!="mapping"){L(bI,bF)}}}function bH(){if(bF==""){m(bE);if(bB.visualMode){aU(bE)}else{if(bB.insertMode){y(bE)}}return true}}function bz(bJ){var bI;while(bJ){bI=(/<\w+-.+?>|<\w+>|./).exec(bJ);bF=bI[0];bJ=bJ.substring(bI.index+bF.length);b.Vim.handleKey(bE,bF,"mapping")}}function bC(){if(bH()){return true}var bK=bB.inputState.keyBuffer=bB.inputState.keyBuffer+bF;var bL=bF.length==1;var bI=bc.matchCommand(bK,a,bB.inputState,"insert");while(bK.length>1&&bI.type!="full"){var bK=bB.inputState.keyBuffer=bK.slice(1);var bM=bc.matchCommand(bK,a,bB.inputState,"insert");if(bM.type!="none"){bI=bM}}if(bI.type=="none"){m(bE);return false}else{if(bI.type=="partial"){if(bu){window.clearTimeout(bu)}bu=window.setTimeout(function(){if(bB.insertMode&&bB.inputState.keyBuffer){m(bE)}},r("insertModeEscKeysTimeout"));return !bL}}if(bu){window.clearTimeout(bu)}if(bL){var bJ=bE.getCursor();bE.replaceRange("",G(bJ,0,-(bK.length-1)),bJ,"+input")}m(bE);var bN=bI.command;if(bN.type=="keyToKey"){bz(bN.toKeys)}else{bc.processCommand(bE,bB,bN)}return true}function bA(){if(bG()||bH()){return true}var bK=bB.inputState.keyBuffer=bB.inputState.keyBuffer+bF;if(/^[1-9]\d*$/.test(bK)){return true}var bM=/^(\d*)(.*)$/.exec(bK);if(!bM){m(bE);return false}var bJ=bB.visualMode?"visual":"normal";var bI=bc.matchCommand(bM[2]||bM[1],a,bB.inputState,bJ);if(bI.type=="none"){m(bE);return false}else{if(bI.type=="partial"){return true}}bB.inputState.keyBuffer="";var bL=bI.command;var bM=/^(\d*)(.*)$/.exec(bK);if(bM[1]&&bM[1]!="0"){bB.inputState.pushRepeatDigit(bM[1])}if(bL.type=="keyToKey"){bz(bL.toKeys)}else{bc.processCommand(bE,bB,bL)}return true}return bE.operation(function(){bE.curOp.isVimOp=true;try{if(bB.insertMode){return bC()}else{return bA()}}catch(bI){bE.state.vim=undefined;J(bE);throw bI}})},handleEx:function(bz,bA){p.processCommand(bz,bA)}};function aD(){this.prefixRepeat=[];this.motionRepeat=[];this.operator=null;this.operatorArgs=null;this.motion=null;this.motionArgs=null;this.keyBuffer=[];this.registerName=null}aD.prototype.pushRepeatDigit=function(bz){if(!this.operator){this.prefixRepeat=this.prefixRepeat.concat(bz)}else{this.motionRepeat=this.motionRepeat.concat(bz)}};aD.prototype.getRepeat=function(){var bz=0;if(this.prefixRepeat.length>0||this.motionRepeat.length>0){bz=1;if(this.prefixRepeat.length>0){bz*=parseInt(this.prefixRepeat.join(""),10)}if(this.motionRepeat.length>0){bz*=parseInt(this.motionRepeat.join(""),10)}}return bz};function m(bz,bA){bz.state.vim.inputState=new aD();b.signal(bz,"vim-command-done",bA)}function bo(bB,bA,bz){this.clear();this.keyBuffer=[bB||""];this.insertModeChanges=[];this.searchQueries=[];this.linewise=!!bA;this.blockwise=!!bz}bo.prototype={setText:function(bB,bA,bz){this.keyBuffer=[bB||""];this.linewise=!!bA;this.blockwise=!!bz},pushText:function(bA,bz){if(bz){if(!this.linewise){this.keyBuffer.push("\n")}this.linewise=true}this.keyBuffer.push(bA)},pushInsertModeChanges:function(bz){this.insertModeChanges.push(l(bz))},pushSearchQuery:function(bz){this.searchQueries.push(bz)},clear:function(){this.keyBuffer=[];this.insertModeChanges=[];this.searchQueries=[];this.linewise=false},toString:function(){return this.keyBuffer.join("")}};function am(bz){this.registers=bz;this.unnamedRegister=bz['"']=new bo();bz["."]=new bo();bz[":"]=new bo();bz["/"]=new bo()}am.prototype={pushText:function(bD,bA,bF,bE,bB){if(bE&&bF.charAt(0)=="\n"){bF=bF.slice(1)+"\n"}if(bE&&bF.charAt(bF.length-1)!=="\n"){bF+="\n"}var bC=this.isValidRegister(bD)?this.getRegister(bD):null;if(!bC){switch(bA){case"yank":this.registers["0"]=new bo(bF,bE,bB);break;case"delete":case"change":if(bF.indexOf("\n")==-1){this.registers["-"]=new bo(bF,bE)}else{this.shiftNumericRegisters_();this.registers["1"]=new bo(bF,bE)}break}this.unnamedRegister.setText(bF,bE,bB);return}var bz=D(bD);if(bz){bC.pushText(bF,bE)}else{bC.setText(bF,bE,bB)}this.unnamedRegister.setText(bC.toString(),bE)},getRegister:function(bz){if(!this.isValidRegister(bz)){return this.unnamedRegister}bz=bz.toLowerCase();if(!this.registers[bz]){this.registers[bz]=new bo()}return this.registers[bz]},isValidRegister:function(bz){return bz&&M(bz,o)},shiftNumericRegisters_:function(){for(var bz=9;bz>=2;bz--){this.registers[bz]=this.getRegister(""+(bz-1))}}};function a5(){this.historyBuffer=[];this.iterator;this.initialPrefix=null}a5.prototype={nextMatch:function(bA,bz){var bF=this.historyBuffer;var bC=bz?-1:1;if(this.initialPrefix===null){this.initialPrefix=bA}for(var bE=this.iterator+bC;bz?bE>=0:bE=bF.length){this.iterator=bF.length;return this.initialPrefix}if(bE<0){return bA}},pushInput:function(bz){var bA=this.historyBuffer.indexOf(bz);if(bA>-1){this.historyBuffer.splice(bA,1)}if(bz.length){this.historyBuffer.push(bz)}},reset:function(){this.initialPrefix=null;this.iterator=this.historyBuffer.length}};var bc={matchCommand:function(bE,bG,bz,bC){var bF=bl(bE,bG,bC,bz);if(!bF.full&&!bF.partial){return{type:"none"}}else{if(!bF.full&&bF.partial){return{type:"partial"}}}var bD;for(var bB=0;bB"){bz.selectedCharacter=T(bE)}return{type:"full",command:bD}},processCommand:function(bz,bA,bB){bA.inputState.repeatOverride=bB.repeatOverride;switch(bB.type){case"motion":this.processMotion(bz,bA,bB);break;case"operator":this.processOperator(bz,bA,bB);break;case"operatorMotion":this.processOperatorMotion(bz,bA,bB);break;case"action":this.processAction(bz,bA,bB);break;case"search":this.processSearch(bz,bA,bB);m(bz);break;case"ex":case"keyToEx":this.processEx(bz,bA,bB);m(bz);break;default:break}},processMotion:function(bz,bA,bB){bA.inputState.motion=bB.motion;bA.inputState.motionArgs=bj(bB.motionArgs);this.evalInput(bz,bA)},processOperator:function(bA,bB,bC){var bz=bB.inputState;if(bz.operator){if(bz.operator==bC.operator){bz.motion="expandToLine";bz.motionArgs={linewise:true};this.evalInput(bA,bB);return}else{m(bA)}}bz.operator=bC.operator;bz.operatorArgs=bj(bC.operatorArgs);if(bB.visualMode){this.evalInput(bA,bB)}},processOperatorMotion:function(bz,bC,bD){var bB=bC.visualMode;var bA=bj(bD.operatorMotionArgs);if(bA){if(bB&&bA.visualLine){bC.visualLine=true}}this.processOperator(bz,bC,bD);if(!bB){this.processMotion(bz,bC,bD)}},processAction:function(bA,bC,bF){var bz=bC.inputState;var bE=bz.getRepeat();var bD=!!bE;var bB=bj(bF.actionArgs)||{};if(bz.selectedCharacter){bB.selectedCharacter=bz.selectedCharacter}if(bF.operator){this.processOperator(bA,bC,bF)}if(bF.motion){this.processMotion(bA,bC,bF)}if(bF.motion||bF.operator){this.evalInput(bA,bC)}bB.repeat=bE||1;bB.repeatIsExplicit=bD;bB.registerName=bz.registerName;m(bA);bC.lastMotion=null;if(bF.isEdit){this.recordLastEdit(bC,bz,bF)}s[bF.action](bA,bB,bC)},processSearch:function(bO,bH,bG){if(!bO.getSearchCursor){return}var bJ=bG.searchArgs.forward;var bE=bG.searchArgs.wholeWordOnly;aJ(bO).setReversed(!bJ);var bK=(bJ)?"/":"?";var bM=aJ(bO).getQuery();var bB=bO.getScrollInfo();function bF(bR,bP,bQ){t.searchHistoryController.pushInput(bR);t.searchHistoryController.reset();try{bv(bO,bR,bP,bQ)}catch(bS){bm(bO,"Invalid regex: "+bR);return}bc.processMotion(bO,bH,{type:"motion",motion:"findNext",motionArgs:{forward:true,toJumplist:bG.searchArgs.toJumplist}})}function bN(bP){bO.scrollTo(bB.left,bB.top);bF(bP,true,true);var bQ=t.macroModeState;if(bQ.isRecording){R(bQ,bP)}}function bD(bT,bS,bU){var bR=b.keyName(bT),bP;if(bR=="Up"||bR=="Down"){bP=bR=="Up"?true:false;bS=t.searchHistoryController.nextMatch(bS,bP)||"";bU(bS)}else{if(bR!="Left"&&bR!="Right"&&bR!="Ctrl"&&bR!="Alt"&&bR!="Shift"){t.searchHistoryController.reset()}}var bQ;try{bQ=bv(bO,bS,true,true)}catch(bT){}if(bQ){bO.scrollIntoView(bx(bO,!bJ,bQ),30)}else{aN(bO);bO.scrollTo(bB.left,bB.top)}}function bA(bR,bQ,bS){var bP=b.keyName(bR);if(bP=="Esc"||bP=="Ctrl-C"||bP=="Ctrl-["){t.searchHistoryController.pushInput(bQ);t.searchHistoryController.reset();bv(bO,bM);aN(bO);bO.scrollTo(bB.left,bB.top);b.e_stop(bR);bS();bO.focus()}}switch(bG.searchArgs.querySrc){case"prompt":var bI=t.macroModeState;if(bI.isPlaying){var bL=bI.replaySearchQueries.shift();bF(bL,true,false)}else{a3(bO,{onClose:bN,prefix:bK,desc:S,onKeyUp:bD,onKeyDown:bA})}break;case"wordUnderCursor":var bC=aG(bO,false,true,false,true);var bz=true;if(!bC){bC=aG(bO,false,true,false,false);bz=false}if(!bC){return}var bL=bO.getLine(bC.start.line).substring(bC.start.ch,bC.end.ch);if(bz&&bE){bL="\\b"+bL+"\\b"}else{bL=j(bL)}t.jumpList.cachedCursor=bO.getCursor();bO.setCursor(bC.start);bF(bL,true,false);break}},processEx:function(bz,bA,bD){function bC(bE){t.exCommandHistoryController.pushInput(bE);t.exCommandHistoryController.reset();p.processCommand(bz,bE)}function bB(bH,bF,bI){var bG=b.keyName(bH),bE;if(bG=="Esc"||bG=="Ctrl-C"||bG=="Ctrl-["){t.exCommandHistoryController.pushInput(bF);t.exCommandHistoryController.reset();b.e_stop(bH);bI();bz.focus()}if(bG=="Up"||bG=="Down"){bE=bG=="Up"?true:false;bF=t.exCommandHistoryController.nextMatch(bF,bE)||"";bI(bF)}else{if(bG!="Left"&&bG!="Right"&&bG!="Ctrl"&&bG!="Alt"&&bG!="Shift"){t.exCommandHistoryController.reset()}}}if(bD.type=="keyToEx"){p.processCommand(bz,bD.exArgs.input)}else{if(bA.visualMode){a3(bz,{onClose:bC,prefix:":",value:"'<,'>",onKeyDown:bB})}else{a3(bz,{onClose:bC,prefix:":",onKeyDown:bB})}}},evalInput:function(bH,bT){var bM=bT.inputState;var bQ=bM.motion;var bN=bM.motionArgs||{};var bI=bM.operator;var b3=bM.operatorArgs||{};var bO=bM.registerName;var bU=bT.sel;var b4=F(bT.visualMode?bU.head:bH.getCursor("head"));var bF=F(bT.visualMode?bU.anchor:bH.getCursor("anchor"));var bC=F(b4);var bB=F(bF);var bS,bL;var bJ;if(bI){this.recordLastEdit(bT,bM)}if(bM.repeatOverride!==undefined){bJ=bM.repeatOverride}else{bJ=bM.getRepeat()}if(bJ>0&&bN.explicitRepeat){bN.repeatIsExplicit=true}else{if(bN.noRepeat||(!bN.explicitRepeat&&bJ===0)){bJ=1;bN.repeatIsExplicit=false}}if(bM.selectedCharacter){bN.selectedCharacter=b3.selectedCharacter=bM.selectedCharacter}bN.repeat=bJ;m(bH);if(bQ){var bR=a4[bQ](bH,b4,bN,bT);bT.lastMotion=a4[bQ];if(!bR){return}if(bN.toJumplist){var b2=t.jumpList;var bK=b2.cachedCursor;if(bK){bg(bH,bK,bR);delete b2.cachedCursor}else{bg(bH,b4,bR)}}if(bR instanceof Array){bL=bR[0];bS=bR[1]}else{bS=bR}if(!bS){bS=F(b4)}if(bT.visualMode){bS=ad(bH,bS,bT.visualBlock);if(bL){bL=ad(bH,bL,true)}bL=bL||bB;bU.anchor=bL;bU.head=bS;O(bH);aS(bH,bT,"<",aP(bL,bS)?bL:bS);aS(bH,bT,">",aP(bL,bS)?bS:bL)}else{if(!bI){bS=ad(bH,bS);bH.setCursor(bS.line,bS.ch)}}}if(bI){if(b3.lastSel){bL=bB;var bz=b3.lastSel;var bZ=Math.abs(bz.head.line-bz.anchor.line);var b1=Math.abs(bz.head.ch-bz.anchor.ch);if(bz.visualLine){bS=c(bB.line+bZ,bB.ch)}else{if(bz.visualBlock){bS=c(bB.line+bZ,bB.ch+b1)}else{if(bz.head.line==bz.anchor.line){bS=c(bB.line,bB.ch+b1)}else{bS=c(bB.line+bZ,bB.ch)}}}bT.visualMode=true;bT.visualLine=bz.visualLine;bT.visualBlock=bz.visualBlock;bU=bT.sel={anchor:bL,head:bS};O(bH)}else{if(bT.visualMode){b3.lastSel={anchor:F(bU.anchor),head:F(bU.head),visualBlock:bT.visualBlock,visualLine:bT.visualLine}}}var bG,bV,bD,bP;var bE;if(bT.visualMode){bG=az(bU.head,bU.anchor);bV=ba(bU.head,bU.anchor);bD=bT.visualLine||b3.linewise;bP=bT.visualBlock?"block":bD?"line":"char";bE=by(bH,{anchor:bG,head:bV},bP);if(bD){var bA=bE.ranges;if(bP=="block"){for(var bW=0;bWbG&&bH.line==bG)){return}if(bA.toFirstChar){bC=a1(bF.getLine(bI));bB.lastHPos=bC}bB.lastHSPos=bF.charCoords(c(bI,bC),"div").left;return c(bI,bC)},moveByDisplayLines:function(bH,bG,bB,bC){var bI=bG;switch(bC.lastMotion){case this.moveByDisplayLines:case this.moveByScroll:case this.moveByLines:case this.moveToColumn:case this.moveToEol:break;default:bC.lastHSPos=bH.charCoords(bI,"div").left}var bz=bB.repeat;var bF=bH.findPosV(bI,(bB.forward?bz:-bz),"line",bC.lastHSPos);if(bF.hitSide){if(bB.forward){var bA=bH.charCoords(bF,"div");var bD={top:bA.top+8,left:bC.lastHSPos};var bF=bH.coordsChar(bD,"div")}else{var bE=bH.charCoords(c(bH.firstLine(),0),"div");bE.left=bC.lastHSPos;bF=bH.coordsChar(bE,"div")}}bC.lastHPos=bF.ch;return bF},moveByPage:function(bA,bC,bB){var bz=bC;var bD=bB.repeat;return bA.findPosV(bz,(bB.forward?bD:-bD),"page")},moveByParagraph:function(bz,bD,bB){var bA=bD.line;var bE=bB.repeat;var bF=bB.forward?1:-1;for(var bC=0;bC1);s.enterInsertMode(bI,{head:bF},bI.state.vim)},"delete":function(bG,bE,bz){var bD,bH;var bB=bG.state.vim;if(!bB.visualBlock){var bC=bz[0].anchor,bF=bz[0].head;if(bE.linewise&&bF.line!=bG.firstLine()&&bC.line==bG.lastLine()&&bC.line==bF.line-1){if(bC.line==bG.firstLine()){bC.ch=0}else{bC=c(bC.line-1,aX(bG,bC.line-1))}}bH=bG.getRange(bC,bF);bG.replaceRange("",bC,bF);bD=bC;if(bE.linewise){bD=a4.moveToFirstNonWhiteSpaceCharacter(bG,bC)}}else{bH=bG.getSelection();var bA=B("",bz.length);bG.replaceSelections(bA);bD=bz[0].anchor}t.registerController.pushText(bE.registerName,"delete",bH,bE.linewise,bB.visualBlock);return bD},indent:function(bG,bF,bz){var bD=bG.state.vim;var bH=bz[0].anchor.line;var bB=bD.visualBlock?bz[bz.length-1].anchor.line:bz[0].head.line;var bA=(bD.visualMode)?bF.repeat:1;if(bF.linewise){bB--}for(var bE=bH;bE<=bB;bE++){for(var bC=0;bCbC.top){bJ.line+=(bE-bC.top)/bG;bJ.line=Math.ceil(bJ.line);bH.setCursor(bJ);bC=bH.charCoords(bJ,"local");bH.scrollTo(null,bC.top)}else{bH.scrollTo(null,bE)}}else{var bA=bE+bH.getScrollInfo().clientHeight;if(bA=bF.anchor.line){bD=G(bF.head,0,1)}else{bD=c(bF.anchor.line,0)}}else{bD=c(Math.min(bF.head.line,bF.anchor.line),Math.max(bF.head.ch+1,bF.anchor.ch));bz=Math.abs(bF.head.line-bF.anchor.line)+1}}else{if(bE=="inplace"){if(bC.visualMode){return}}}}}}}bA.setOption("keyMap","vim-insert");bA.setOption("disableInput",false);if(bB&&bB.replace){bA.toggleOverwrite(true);bA.setOption("keyMap","vim-replace");b.signal(bA,"vim-mode-change",{mode:"replace"})}else{bA.setOption("keyMap","vim-insert");b.signal(bA,"vim-mode-change",{mode:"insert"})}if(!t.macroModeState.isPlaying){bA.on("change",bi);b.on(bA.getInputField(),"keydown",aa)}if(bC.visualMode){aU(bA)}aV(bA,bD,bz)},toggleVisualMode:function(bz,bA,bB){var bE=bA.repeat;var bC=bz.getCursor();var bD;if(!bB.visualMode){bB.visualMode=true;bB.visualLine=!!bA.linewise;bB.visualBlock=!!bA.blockwise;bD=ad(bz,c(bC.line,bC.ch+bE-1),true);bB.sel={anchor:bC,head:bD};b.signal(bz,"vim-mode-change",{mode:"visual",subMode:bB.visualLine?"linewise":bB.visualBlock?"blockwise":""});O(bz);aS(bz,bB,"<",az(bC,bD));aS(bz,bB,">",ba(bC,bD))}else{if(bB.visualLine^bA.linewise||bB.visualBlock^bA.blockwise){bB.visualLine=!!bA.linewise;bB.visualBlock=!!bA.blockwise;b.signal(bz,"vim-mode-change",{mode:"visual",subMode:bB.visualLine?"linewise":bB.visualBlock?"blockwise":""});O(bz)}else{aU(bz)}}},reselectLastSelection:function(bz,bE,bB){var bA=bB.lastSelection;if(bB.visualMode){bh(bz,bB)}if(bA){var bC=bA.anchorMark.find();var bD=bA.headMark.find();if(!bC||!bD){return}bB.sel={anchor:bC,head:bD};bB.visualMode=true;bB.visualLine=bA.visualLine;bB.visualBlock=bA.visualBlock;O(bz);aS(bz,bB,"<",az(bC,bD));aS(bz,bB,">",ba(bC,bD));b.signal(bz,"vim-mode-change",{mode:"visual",subMode:bB.visualLine?"linewise":bB.visualBlock?"blockwise":""})}},joinLines:function(bG,bA,bC){var bF,bI;if(bC.visualMode){bF=bG.getCursor("anchor");bI=bG.getCursor("head");bI.ch=aX(bG,bI.line)-1}else{var bz=Math.max(bA.repeat,2);bF=bG.getCursor();bI=ad(bG,c(bF.line+bz-1,Infinity))}var bB=0;for(var bE=bF.line;bE1){var bQ=Array(bM.repeat+1).join(bQ)}var bJ=bA.linewise;var bL=bA.blockwise;if(bJ){if(bV.visualMode){bQ=bV.visualLine?bQ.slice(0,-1):"\n"+bQ.slice(0,bQ.length-1)+"\n"}else{if(bM.after){bQ="\n"+bQ.slice(0,bQ.length-1);bG.ch=aX(bN,bG.line)}else{bG.ch=0}}}else{if(bL){bQ=bQ.split("\n");for(var bW=0;bWbN.lastLine()){bN.replaceRange("\n",c(bO,0))}var bY=aX(bN,bO);if(bYbJ.length){bF=bJ.length}bI=c(bG.line,bF)}if(bC=="\n"){if(!bD.visualMode){bH.replaceRange("",bG,bI)}(b.commands.newlineAndIndentContinueComment||b.commands.newlineAndIndent)(bH)}else{var bz=bH.getRange(bG,bI);bz=bz.replace(/[^\n]/g,bC);if(bD.visualBlock){var bE=new Array(bH.getOption("tabSize")+1).join(" ");bz=bH.getSelection();bz=bz.replace(/\t/g,bE).replace(/[^\n]/g,bC).split("\n");bH.replaceSelections(bz)}else{bH.replaceRange(bz,bG,bI)}if(bD.visualMode){bG=aP(bA[0].anchor,bA[0].head)?bA[0].anchor:bA[0].head;bH.setCursor(bG);aU(bH)}else{bH.setCursor(G(bI,0,-1))}}},incrementNumberToken:function(bJ,bA){var bK=bJ.getCursor();var bF=bJ.getLine(bK.line);var bM=/-?\d+/g;var bE;var bz;var bD;var bL;var bB;while((bE=bM.exec(bF))!==null){bB=bE[0];bz=bE.index;bD=bz+bB.length;if(bK.ch"){var bA=bz.length-11;var bD=bC.slice(0,bA);var bB=bz.slice(0,bA);return bD==bB&&bC.length>bA?"full":bB.indexOf(bD)==0?"partial":false}else{return bC==bz?"full":bz.indexOf(bC)==0?"partial":false}}function T(bB){var bA=/^.*(<[\w\-]+>)$/.exec(bB);var bz=bA?bA[1]:bB.slice(-1);if(bz.length>1){switch(bz){case"":bz="\n";break;case"":bz=" ";break;default:break}}return bz}function aA(bz,bA,bB){return function(){for(var bC=0;bC2){bz=az.apply(undefined,Array.prototype.slice.call(arguments,1))}return aP(bA,bz)?bA:bz}function ba(bA,bz){if(arguments.length>2){bz=ba.apply(undefined,Array.prototype.slice.call(arguments,1))}return aP(bA,bz)?bz:bA}function ay(bC,bB,bA){var bD=aP(bC,bB);var bz=aP(bB,bA);return bD&&bz}function aX(bz,bA){return bz.getLine(bA).length}function n(bz){return bz.split("").reverse().join("")}function a9(bz){if(bz.trim){return bz.trim()}return bz.replace(/^\s+|\s+$/g,"")}function j(bz){return bz.replace(/([.?*+$\[\]\/\\(){}|\-])/g,"\\$1")}function aY(bz,bD,bC){var bB=aX(bz,bD);var bA=new Array(bC-bB+1).join(" ");bz.setCursor(c(bD,bB));bz.replaceRange(bA,bz.getCursor())}function I(bH,bA){var bC=[],bB=bH.listSelections();var bD=F(bH.clipPos(bA));var bS=!bw(bA,bD);var bF=bH.getCursor("head");var bR=w(bB,bF);var bI=bw(bB[bR].head,bB[bR].anchor);var bQ=bB.length-1;var bG=bQ-bR>bR?bQ:0;var bE=bB[bG].anchor;var bN=Math.min(bE.line,bD.line);var bz=Math.max(bE.line,bD.line);var bJ=bE.ch,bK=bD.ch;var bP=bB[bG].head.ch-bJ;var bM=bK-bJ;if(bP>0&&bM<=0){bJ++;if(!bS){bK--}}else{if(bP<0&&bM>=0){bJ--;if(!bI){bK++}}else{if(bP<0&&bM==-1){bJ--;bK++}}}for(var bL=bN;bL<=bz;bL++){var bO={anchor:new c(bL,bJ),head:new c(bL,bK)};bC.push(bO)}bR=bD.line==bz?bC.length-1:0;bH.setSelections(bC);bA.ch=bK;bE.ch=bJ;return bE}function aV(bA,bC,bz){var bE=[];for(var bB=0;bBbM){bK.line=bM}bK.ch=aX(bN,bK.line)}else{bK.ch=0;bH.ch=aX(bN,bH.line)}return{ranges:[{anchor:bH,head:bK}],primary:0}}else{if(bI=="block"){var bJ=Math.min(bH.line,bK.line),bF=Math.min(bH.ch,bK.ch),bz=Math.max(bH.line,bK.line),bO=Math.max(bH.ch,bK.ch)+1;var bP=bz-bJ+1;var bE=bK.line==bJ?0:bP-1;var bA=[];for(var bG=0;bG0&&bB&&W(bB);bB=bC.pop()){bE.line--;bE.ch=0}if(bB){bE.line--;bE.ch=aX(bA,bE.line)}else{bE.ch=0}}}function be(bA,bz,bB){bz.ch=0;bB.ch=0;bB.line++}function a1(bA){if(!bA){return 0}var bz=bA.search(/\S/);return bz==-1?bA.length:bz}function aG(bI,bE,bS,bA,bT){var bC=h(bI);var bL=bI.getLine(bC.line);var bO=bC.ch;var bN=bL.substring(bO);var bP;if(bT){bP=bN.search(/\w/)}else{bP=bN.search(/\S/)}if(bP==-1){return null}bO+=bP;bN=bL.substring(bO);var bR=bL.substring(0,bO);var bU;if(bA){bU=/^\S+/}else{if((/\w/).test(bL.charAt(bO))){bU=/^\w+/}else{bU=/^[^\w\s]+/}}var bF=bU.exec(bN);var bM=bO;var bB=bO+bF[0].length;var bD=n(bR);var bJ=bU.exec(bD);if(bJ){bM-=bJ[0].length}if(bE){var bK=bL.substring(bB);var bz=bK.match(/^\s*/)[0].length;if(bz>0){bB+=bz}else{var bH=bD.length-bM;var bG=bD.substring(bH);var bQ=bG.match(/^\s*/)[0].length;bM-=bQ}}return{start:c(bC.line,bM),end:c(bC.line,bB)}}function bg(bz,bA,bB){if(!bw(bA,bB)){t.jumpList.add(bz,bA,bB)}}function aF(bz,bA){t.lastChararacterSearch.increment=bz;t.lastChararacterSearch.forward=bA.forward;t.lastChararacterSearch.selectedCharacter=bA.selectedCharacter}var V={"(":"bracket",")":"bracket","{":"bracket","}":"bracket","[":"section","]":"section","*":"comment","/":"comment",m:"method",M:"method","#":"preprocess"};var aZ={bracket:{isComplete:function(bz){if(bz.nextCh===bz.symb){bz.depth++;if(bz.depth>=1){return true}}else{if(bz.nextCh===bz.reverseSymb){bz.depth--}}return false}},section:{init:function(bz){bz.curMoveThrough=true;bz.symb=(bz.forward?"]":"[")===bz.symb?"{":"}"},isComplete:function(bz){return bz.index===0&&bz.nextCh===bz.symb}},comment:{isComplete:function(bA){var bz=bA.lastCh==="*"&&bA.nextCh==="/";bA.lastCh=bA.nextCh;return bz}},method:{init:function(bz){bz.symb=(bz.symb==="m"?"{":"}");bz.reverseSymb=bz.symb==="{"?"}":"{"},isComplete:function(bz){if(bz.nextCh===bz.symb){return true}return false}},preprocess:{init:function(bz){bz.index=0},isComplete:function(bA){if(bA.nextCh==="#"){var bz=bA.lineText.match(/#(\w+)/)[1];if(bz==="endif"){if(bA.forward&&bA.depth===0){return true}bA.depth++}else{if(bz==="if"){if(!bA.forward&&bA.depth===0){return true}bA.depth--}}if(bz==="else"&&bA.depth===0){return true}}return false}}};function br(bI,bA,bD,bB){var bL=F(bI.getCursor());var bJ=bD?1:-1;var bC=bD?bI.lineCount():-1;var bH=bL.ch;var bN=bL.line;var bG=bI.getLine(bN);var bz={lineText:bG,nextCh:bG.charAt(bH),lastCh:null,index:bH,symb:bB,reverseSymb:(bD?{")":"(","}":"{"}:{"(":")","{":"}"})[bB],forward:bD,depth:0,curMoveThrough:false};var bE=V[bB];if(!bE){return bL}var bM=aZ[bE].init;var bK=aZ[bE].isComplete;if(bM){bM(bz)}while(bN!==bC&&bA){bz.index+=bJ;bz.nextCh=bz.lineText.charAt(bz.index);if(!bz.nextCh){bN+=bJ;bz.lineText=bI.getLine(bN)||"";if(bJ>0){bz.index=0}else{var bF=bz.lineText.length;bz.index=(bF>0)?(bF-1):0}bz.nextCh=bz.lineText.charAt(bz.index)}if(bK(bz)){bL.line=bN;bL.ch=bz.index;bA--}}if(bz.nextCh||bz.curMoveThrough){return c(bN,bz.index)}return bL}function bt(bJ,bK,bC,bH,bI){var bD=bK.line;var bG=bK.ch;var bN=bJ.getLine(bD);var bA=bC?1:-1;var bE=bH?bn:av;if(bI&&bN==""){bD+=bA;bN=bJ.getLine(bD);if(!i(bJ,bD)){return null}bG=(bC)?0:bN.length}while(true){if(bI&&bN==""){return{from:0,to:0,line:bD}}var bF=(bA>0)?bN.length:-1;var bM=bF,bL=bF;while(bG!=bF){var bz=false;for(var bB=0;bB0)?0:bN.length}throw new Error("The impossible happened.")}function aE(bJ,bL,bA,bE,bN,bH){var bF=F(bL);var bG=[];if(bE&&!bN||!bE&&bN){bA++}var bI=!(bE&&bN);for(var bC=0;bCbD.ch)||(bA.line>bD.line)){var bF=bA;bA=bD;bD=bF}if(bI){bD.ch+=1}else{bA.ch+=1}return{start:bA,end:bD}}function aR(bI,bG,bB,bH){var bJ=F(bG);var bK=bI.getLine(bJ.line);var bF=bK.split("");var bA,bC,bD,bE;var bz=bF.indexOf(bB);if(bJ.ch-1&&!bA;bD--){if(bF[bD]==bB){bA=bD+1}}}if(bA&&!bC){for(bD=bA,bE=bF.length;bD'+bA+"
",{bottom:true,duration:5000})}else{alert(bA)}}function aI(bA,bB){var bz="";if(bA){bz+=''+bA+""}bz+=' ';if(bB){bz+='';bz+=bB;bz+=""}return bz}var S="(Javascript regexp)";function a3(bA,bB){var bC=(bB.prefix||"")+" "+(bB.desc||"");var bz=aI(bB.prefix,bB.desc);af(bA,bz,bC,bB.onClose,bB)}function ab(bA,bz){if(bA instanceof RegExp&&bz instanceof RegExp){var bC=["global","multiline","ignoreCase","source"];for(var bB=0;bB=bA&&bB<=bz)}else{return bB==bA}}}function bd(bz){var bC=bz.getScrollInfo();var bB=6;var bF=10;var bE=bz.coordsChar({left:0,top:bB+bC.top},"local");var bA=bC.clientHeight-bF+bC.top;var bD=bz.coordsChar({left:0,top:bA},"local");return{top:bE.line,bottom:bD.line}}var E=[{name:"map"},{name:"imap",shortName:"im"},{name:"nmap",shortName:"nm"},{name:"vmap",shortName:"vm"},{name:"unmap"},{name:"write",shortName:"w"},{name:"undo",shortName:"u"},{name:"redo",shortName:"red"},{name:"set",shortName:"set"},{name:"sort",shortName:"sor"},{name:"substitute",shortName:"s",possiblyAsync:true},{name:"nohlsearch",shortName:"noh"},{name:"delmarks",shortName:"delm"},{name:"registers",shortName:"reg",excludeFromCommandHistory:true},{name:"global",shortName:"g"}];var ac=function(){this.buildCommandMap_()};ac.prototype={processCommand:function(bK,bJ,bA){var bE=bK.state.vim;var bB=t.registerController.getRegister(":");var bH=bB.toString();if(bE.visualMode){aU(bK)}var bz=new b.StringStream(bJ);bB.setText(bJ);var bD=bA||{};bD.input=bJ;try{this.parseInput_(bK,bz,bD)}catch(bI){bm(bK,bI);throw bI}var bC;var bG;if(!bD.commandName){if(bD.line!==undefined){bG="move"}}else{bC=this.matchCommand_(bD.commandName);if(bC){bG=bC.name;if(bC.excludeFromCommandHistory){bB.setText(bH)}this.parseCommandArgs_(bz,bD,bC);if(bC.type=="exToKey"){for(var bF=0;bF0;bz--){var bB=bA.substring(0,bz);if(this.commandMap_[bB]){var bC=this.commandMap_[bB];if(bC.name.indexOf(bA)===0){return bC}}}return null},buildCommandMap_:function(){this.commandMap_={};for(var bA=0;bA
";if(!bG){for(var bz in bD){var bH=bD[bz].toString();if(bH.length){bB+='"'+bz+" "+bH+"
"}}}else{var bz;bG=bG.join("");for(var bC=0;bC"}}bm(bE,bB)},sort:function(bI,bS){var bJ,bC,bA,bB;function bD(){if(bS.argString){var bW=new b.StringStream(bS.argString);if(bW.eat("!")){bJ=true}if(bW.eol()){return}if(!bW.eatSpace()){return"Invalid arguments"}var bY=bW.match(/[a-z]+/);if(bY){bY=bY[0];bC=bY.indexOf("i")!=-1;bA=bY.indexOf("u")!=-1;var bV=bY.indexOf("d")!=-1&&1;var bX=bY.indexOf("x")!=-1&&1;var bU=bY.indexOf("o")!=-1&&1;if(bV+bX+bU>1){return"Invalid arguments"}bB=bV&&"decimal"||bX&&"hex"||bU&&"octal"}if(bW.eatSpace()&&bW.match(/\/.*\//)){"patterns not supported"}}}var bE=bD();if(bE){bm(bI,bE+": "+bS.argString);return}var bN=bS.line||bI.firstLine();var bR=bS.lineEnd||bS.line||bI.lastLine();if(bN==bR){return}var bH=c(bN,0);var bP=c(bR,aX(bI,bR));var bM=bI.getRange(bH,bP).split("\n");var bF=(bB=="decimal")?/(-?)([\d]+)/:(bB=="hex")?/(-?)(?:0x)?([0-9a-f]+)/i:(bB=="octal")?/([0-7]+)/:null;var bG=(bB=="decimal")?10:(bB=="hex")?16:(bB=="octal")?8:null;var bK=[],bO=[];if(bB){for(var bQ=0;bQ"}}if(!bC){bm(bM,bI);return}var bH=0;var bN=function(){if(bH=bI){bm(bJ,"Invalid argument: "+bE.argString.substring(bH));return}for(var bF=0;bF<=bI-bA;bF++){var bD=String.fromCharCode(bA+bF);delete bz.marks[bD]}}else{bm(bJ,"Invalid argument: "+bC+"-");return}}else{delete bz.marks[bB]}}}};var p=new ac();function a8(bN,bA,bC,bI,bG,bB,bK,bE,bO){bN.state.vim.exMode=true;var bF=false;var bM=bB.from();function bJ(){bN.operation(function(){while(!bF){bD();bH()}bL()})}function bD(){var bQ=bN.getRange(bB.from(),bB.to());var bP=bQ.replace(bK,bE);bB.replace(bP)}function bH(){var bP;while(bP=bB.findNext()&&ai(bB.from(),bI,bG)){if(!bC&&bM&&bB.from().line==bM.line){continue}bN.scrollIntoView(bB.from(),30);bN.setSelection(bB.from(),bB.to());bM=bB.from();bF=false;return}bF=true}function bL(bQ){if(bQ){bQ()}bN.focus();if(bM){bN.setCursor(bM);var bP=bN.state.vim;bP.exMode=false;bP.lastHPos=bP.lastHSPos=bM.ch}if(bO){bO()}}function bz(bS,bP,bT){b.e_stop(bS);var bQ=b.keyName(bS);switch(bQ){case"Y":bD();bH();break;case"N":bH();break;case"A":var bR=bO;bO=undefined;bN.operation(bJ);bO=bR;break;case"L":bD();case"Q":case"Esc":case"Ctrl-C":case"Ctrl-[":bL(bT);break}if(bF){bL(bT)}return true}bH();if(bF){bm(bN,"No matches for "+bK.source);return}if(!bA){bJ();if(bO){bO()}return}a3(bN,{prefix:"replace with "+bE+" (y/n/a/q/l)",onKeyDown:bz})}b.keyMap.vim={attach:v,detach:k};function y(bH){var bA=bH.state.vim;var bC=t.macroModeState;var bF=t.registerController.getRegister(".");var bz=bC.isPlaying;var bD=bC.lastInsertModeChanges;var bI=[];if(!bz){var bE=bD.inVisualBlock?bA.lastSelection.visualBlock.height:1;var bG=bD.changes;var bI=[];var bB=0;while(bB1){A(bH,bA,bA.insertModeRepeat-1,true);bA.lastEditInputState.repeatOverride=bA.insertModeRepeat}delete bA.insertModeRepeat;bA.insertMode=false;bH.setCursor(bH.getCursor().line,bH.getCursor().ch-1);bH.setOption("keyMap","vim");bH.setOption("disableInput",true);bH.toggleOverwrite(false);bF.setText(bD.changes.join(""));b.signal(bH,"vim-mode-change",{mode:"normal"});if(bC.isRecording){ar(bC)}}aM("insertModeEscKeysTimeout",200,"number");b.keyMap["vim-insert"]={"Ctrl-N":"autocomplete","Ctrl-P":"autocomplete",Enter:function(bz){var bA=b.commands.newlineAndIndentContinueComment||b.commands.newlineAndIndent;bA(bz)},fallthrough:["default"],attach:v,detach:k};b.keyMap["await-second"]={fallthrough:["vim-insert"],attach:v,detach:k};b.keyMap["vim-replace"]={Backspace:"goCharLeft",fallthrough:["vim-insert"],attach:v,detach:k};function K(bH,bB,bC,bz){var bJ=t.registerController.getRegister(bz);var bA=bJ.keyBuffer;var bF=0;bC.isPlaying=true;bC.replaySearchQueries=bJ.searchQueries.slice(0);for(var bD=0;bD|<\w+>|./).exec(bK);bI=bE[0];bK=bK.substring(bE.index+bI.length);b.Vim.handleKey(bH,bI,"macro");if(bB.insertMode){var bG=bJ.insertModeChanges[bF++].changes;t.macroModeState.lastInsertModeChanges.changes=bG;aw(bH,bG,1);y(bH)}}}bC.isPlaying=false}function L(bC,bz){if(bC.isPlaying){return}var bB=bC.latestRegister;var bA=t.registerController.getRegister(bB);if(bA){bA.pushText(bz)}}function ar(bB){if(bB.isPlaying){return}var bA=bB.latestRegister;var bz=t.registerController.getRegister(bA);if(bz){bz.pushInsertModeChanges(bB.lastInsertModeChanges)}}function R(bC,bB){if(bC.isPlaying){return}var bA=bC.latestRegister;var bz=t.registerController.getRegister(bA);if(bz){bz.pushSearchQuery(bB)}}function bi(bA,bz){var bC=t.macroModeState;var bB=bC.lastInsertModeChanges;if(!bC.isPlaying){while(bz){bB.expectCursorActivityForChange=true;if(bz.origin=="+input"||bz.origin=="paste"||bz.origin===undefined){var bD=bz.text.join("\n");bB.changes.push(bD)}bz=bz.next}}}function ae(bz){var bA=bz.state.vim;if(bA.insertMode){var bC=t.macroModeState;if(bC.isPlaying){return}var bB=bC.lastInsertModeChanges;if(bB.expectCursorActivityForChange){bB.expectCursorActivityForChange=false}else{bB.changes=[]}}else{if(!bz.curOp.isVimOp){u(bz,bA)}}if(bA.visualMode){ag(bz)}}function ag(bz){var bA=bz.state.vim;var bC=F(bA.sel.head);var bB=G(bC,0,1);if(bA.fakeCursor){bA.fakeCursor.clear()}bA.fakeCursor=bz.markText(bC,bB,{className:"cm-animate-fat-cursor"})}function u(bz,bA){var bB=bz.getCursor("anchor");var bC=bz.getCursor("head");if(bA.visualMode&&bw(bC,bB)&&aX(bz,bC.line)>bC.ch){aU(bz,false)}else{if(!bA.visualMode&&!bA.insertMode&&bz.somethingSelected()){bA.visualMode=true;bA.visualLine=false;b.signal(bz,"vim-mode-change",{mode:"visual"})}}if(bA.visualMode){var bD=!aP(bC,bB)?-1:0;var bE=aP(bC,bB)?-1:0;bC=G(bC,0,bD);bB=G(bB,0,bE);bA.sel={anchor:bB,head:bC};aS(bz,bA,"<",az(bC,bB));aS(bz,bA,">",ba(bC,bB))}else{if(!bA.insertMode){bA.lastHPos=bz.getCursor().ch}}}function bk(bz){this.keyName=bz}function aa(bD){var bC=t.macroModeState;var bB=bC.lastInsertModeChanges;var bA=b.keyName(bD);function bz(){bB.changes.push(new bk(bA));return true}if(bA.indexOf("Delete")!=-1||bA.indexOf("Backspace")!=-1){b.lookupKey(bA,"vim-insert",bz)}}function A(bH,bC,bA,bz){var bE=t.macroModeState;bE.isPlaying=true;var bI=!!bC.lastEditActionCommand;var bF=bC.inputState;function bB(){if(bI){bc.processAction(bH,bC,bC.lastEditActionCommand)}else{bc.evalInput(bH,bC)}}function bG(bK){if(bE.lastInsertModeChanges.changes.length>0){bK=!bC.lastEditActionCommand?1:bK;var bJ=bE.lastInsertModeChanges;aw(bH,bJ.changes,bK)}}bC.inputState=bC.lastEditInputState;if(bI&&bC.lastEditActionCommand.interlaceInsertRepeat){for(var bD=0;bD (window.innerHeight || document.documentElement.clientHeight)) doScroll = false; @@ -3720,7 +3734,7 @@ // measured, the position of something may 'drift' during drawing). function scrollPosIntoView(cm, pos, end, margin) { if (margin == null) margin = 0; - for (;;) { + for (var limit = 0; limit < 5; limit++) { var changed = false, coords = cursorCoords(cm, pos); var endCoords = !end || end == pos ? coords : cursorCoords(cm, end); var scrollPos = calculateScrollPos(cm, Math.min(coords.left, endCoords.left), @@ -3769,7 +3783,7 @@ var screenleft = cm.curOp && cm.curOp.scrollLeft != null ? cm.curOp.scrollLeft : display.scroller.scrollLeft; var screenw = display.scroller.clientWidth - scrollerCutOff - display.gutters.offsetWidth; var tooWide = x2 - x1 > screenw; - if (tooWide) x2 = y1 + screen; + if (tooWide) x2 = x1 + screenw; if (x1 < 10) result.scrollLeft = 0; else if (x1 < screenleft) @@ -4024,12 +4038,12 @@ getDoc: function() {return this.doc;}, addKeyMap: function(map, bottom) { - this.state.keyMaps[bottom ? "push" : "unshift"](map); + this.state.keyMaps[bottom ? "push" : "unshift"](getKeyMap(map)); }, removeKeyMap: function(map) { var maps = this.state.keyMaps; for (var i = 0; i < maps.length; ++i) - if (maps[i] == map || (typeof maps[i] != "string" && maps[i].name == map)) { + if (maps[i] == map || maps[i].name == map) { maps.splice(i, 1); return true; } @@ -4086,20 +4100,11 @@ // Fetch the parser token for a given character. Useful for hacks // that want to inspect the mode state (say, for completion). getTokenAt: function(pos, precise) { - var doc = this.doc; - pos = clipPos(doc, pos); - var state = getStateBefore(this, pos.line, precise), mode = this.doc.mode; - var line = getLine(doc, pos.line); - var stream = new StringStream(line.text, this.options.tabSize); - while (stream.pos < pos.ch && !stream.eol()) { - stream.start = stream.pos; - var style = readToken(mode, stream, state); - } - return {start: stream.start, - end: stream.pos, - string: stream.current(), - type: style || null, - state: state}; + return takeToken(this, pos, precise); + }, + + getLineTokens: function(line, precise) { + return takeToken(this, Pos(line), precise, true); }, getTokenTypeAt: function(pos) { @@ -4502,7 +4507,12 @@ themeChanged(cm); guttersChanged(cm); }, true); - option("keyMap", "default", keyMapChanged); + option("keyMap", "default", function(cm, val, old) { + var next = getKeyMap(val); + var prev = old != CodeMirror.Init && getKeyMap(old); + if (prev && prev.detach) prev.detach(cm, next); + if (next.attach) next.attach(cm, prev || null); + }); option("extraKeys", null); option("lineWrapping", false, wrappingChanged, true); @@ -4570,10 +4580,8 @@ // load a mode. (Preferred mechanism is the require/define calls.) CodeMirror.defineMode = function(name, mode) { if (!CodeMirror.defaults.mode && name != "null") CodeMirror.defaults.mode = name; - if (arguments.length > 2) { - mode.dependencies = []; - for (var i = 2; i < arguments.length; ++i) mode.dependencies.push(arguments[i]); - } + if (arguments.length > 2) + mode.dependencies = Array.prototype.slice.call(arguments, 2); modes[name] = mode; }; @@ -4849,9 +4857,11 @@ toggleOverwrite: function(cm) {cm.toggleOverwrite();} }; + // STANDARD KEYMAPS var keyMap = CodeMirror.keyMap = {}; + keyMap.basic = { "Left": "goCharLeft", "Right": "goCharRight", "Up": "goLineUp", "Down": "goLineDown", "End": "goLineEnd", "Home": "goLineStartSmart", "PageUp": "goPageUp", "PageDown": "goPageDown", @@ -4865,7 +4875,7 @@ // are simply ignored. keyMap.pcDefault = { "Ctrl-A": "selectAll", "Ctrl-D": "deleteLine", "Ctrl-Z": "undo", "Shift-Ctrl-Z": "redo", "Ctrl-Y": "redo", - "Ctrl-Home": "goDocStart", "Ctrl-Up": "goDocStart", "Ctrl-End": "goDocEnd", "Ctrl-Down": "goDocEnd", + "Ctrl-Home": "goDocStart", "Ctrl-End": "goDocEnd", "Ctrl-Up": "goLineUp", "Ctrl-Down": "goLineDown", "Ctrl-Left": "goGroupLeft", "Ctrl-Right": "goGroupRight", "Alt-Left": "goLineStart", "Alt-Right": "goLineEnd", "Ctrl-Backspace": "delGroupBefore", "Ctrl-Delete": "delGroupAfter", "Ctrl-S": "save", "Ctrl-F": "find", "Ctrl-G": "findNext", "Shift-Ctrl-G": "findPrev", "Shift-Ctrl-F": "replace", "Shift-Ctrl-R": "replaceAll", @@ -4873,6 +4883,13 @@ "Ctrl-U": "undoSelection", "Shift-Ctrl-U": "redoSelection", "Alt-U": "redoSelection", fallthrough: "basic" }; + // Very basic readline/emacs-style bindings, which are standard on Mac. + keyMap.emacsy = { + "Ctrl-F": "goCharRight", "Ctrl-B": "goCharLeft", "Ctrl-P": "goLineUp", "Ctrl-N": "goLineDown", + "Alt-F": "goWordRight", "Alt-B": "goWordLeft", "Ctrl-A": "goLineStart", "Ctrl-E": "goLineEnd", + "Ctrl-V": "goPageDown", "Shift-Ctrl-V": "goPageUp", "Ctrl-D": "delCharAfter", "Ctrl-H": "delCharBefore", + "Alt-D": "delWordAfter", "Alt-Backspace": "delWordBefore", "Ctrl-K": "killLine", "Ctrl-T": "transposeChars" + }; keyMap.macDefault = { "Cmd-A": "selectAll", "Cmd-D": "deleteLine", "Cmd-Z": "undo", "Shift-Cmd-Z": "redo", "Cmd-Y": "redo", "Cmd-Home": "goDocStart", "Cmd-Up": "goDocStart", "Cmd-End": "goDocEnd", "Cmd-Down": "goDocEnd", "Alt-Left": "goGroupLeft", @@ -4880,73 +4897,103 @@ "Ctrl-Alt-Backspace": "delGroupAfter", "Alt-Delete": "delGroupAfter", "Cmd-S": "save", "Cmd-F": "find", "Cmd-G": "findNext", "Shift-Cmd-G": "findPrev", "Cmd-Alt-F": "replace", "Shift-Cmd-Alt-F": "replaceAll", "Cmd-[": "indentLess", "Cmd-]": "indentMore", "Cmd-Backspace": "delWrappedLineLeft", "Cmd-Delete": "delWrappedLineRight", - "Cmd-U": "undoSelection", "Shift-Cmd-U": "redoSelection", + "Cmd-U": "undoSelection", "Shift-Cmd-U": "redoSelection", "Ctrl-Up": "goDocStart", "Ctrl-Down": "goDocEnd", fallthrough: ["basic", "emacsy"] }; - // Very basic readline/emacs-style bindings, which are standard on Mac. - keyMap.emacsy = { - "Ctrl-F": "goCharRight", "Ctrl-B": "goCharLeft", "Ctrl-P": "goLineUp", "Ctrl-N": "goLineDown", - "Alt-F": "goWordRight", "Alt-B": "goWordLeft", "Ctrl-A": "goLineStart", "Ctrl-E": "goLineEnd", - "Ctrl-V": "goPageDown", "Shift-Ctrl-V": "goPageUp", "Ctrl-D": "delCharAfter", "Ctrl-H": "delCharBefore", - "Alt-D": "delWordAfter", "Alt-Backspace": "delWordBefore", "Ctrl-K": "killLine", "Ctrl-T": "transposeChars" - }; keyMap["default"] = mac ? keyMap.macDefault : keyMap.pcDefault; // KEYMAP DISPATCH - function getKeyMap(val) { - if (typeof val == "string") return keyMap[val]; - else return val; - } - - // Given an array of keymaps and a key name, call handle on any - // bindings found, until that returns a truthy value, at which point - // we consider the key handled. Implements things like binding a key - // to false stopping further handling and keymap fallthrough. - var lookupKey = CodeMirror.lookupKey = function(name, maps, handle) { - function lookup(map) { - map = getKeyMap(map); - var found = map[name]; - if (found === false) return "stop"; - if (found != null && handle(found)) return true; - if (map.nofallthrough) return "stop"; - - var fallthrough = map.fallthrough; - if (fallthrough == null) return false; - if (Object.prototype.toString.call(fallthrough) != "[object Array]") - return lookup(fallthrough); - for (var i = 0; i < fallthrough.length; ++i) { - var done = lookup(fallthrough[i]); - if (done) return done; + function normalizeKeyName(name) { + var parts = name.split(/-(?!$)/), name = parts[parts.length - 1]; + var alt, ctrl, shift, cmd; + for (var i = 0; i < parts.length - 1; i++) { + var mod = parts[i]; + if (/^(cmd|meta|m)$/i.test(mod)) cmd = true; + else if (/^a(lt)?$/i.test(mod)) alt = true; + else if (/^(c|ctrl|control)$/i.test(mod)) ctrl = true; + else if (/^s(hift)$/i.test(mod)) shift = true; + else throw new Error("Unrecognized modifier name: " + mod); + } + if (alt) name = "Alt-" + name; + if (ctrl) name = "Ctrl-" + name; + if (cmd) name = "Cmd-" + name; + if (shift) name = "Shift-" + name; + return name; + } + + // This is a kludge to keep keymaps mostly working as raw objects + // (backwards compatibility) while at the same time support features + // like normalization and multi-stroke key bindings. It compiles a + // new normalized keymap, and then updates the old object to reflect + // this. + CodeMirror.normalizeKeyMap = function(keymap) { + var copy = {}; + for (var keyname in keymap) if (keymap.hasOwnProperty(keyname)) { + var value = keymap[keyname]; + if (/^(name|fallthrough|(de|at)tach)$/.test(keyname)) continue; + if (value == "...") { delete keymap[keyname]; continue; } + + var keys = map(keyname.split(" "), normalizeKeyName); + for (var i = 0; i < keys.length; i++) { + var val, name; + if (i == keys.length - 1) { + name = keyname; + val = value; + } else { + name = keys.slice(0, i + 1).join(" "); + val = "..."; + } + var prev = copy[name]; + if (!prev) copy[name] = val; + else if (prev != val) throw new Error("Inconsistent bindings for " + name); } - return false; + delete keymap[keyname]; } + for (var prop in copy) keymap[prop] = copy[prop]; + return keymap; + }; + + var lookupKey = CodeMirror.lookupKey = function(key, map, handle) { + map = getKeyMap(map); + var found = map.call ? map.call(key) : map[key]; + if (found === false) return "nothing"; + if (found === "...") return "multi"; + if (found != null && handle(found)) return "handled"; - for (var i = 0; i < maps.length; ++i) { - var done = lookup(maps[i]); - if (done) return done != "stop"; + if (map.fallthrough) { + if (Object.prototype.toString.call(map.fallthrough) != "[object Array]") + return lookupKey(key, map.fallthrough, handle); + for (var i = 0; i < map.fallthrough.length; i++) { + var result = lookupKey(key, map.fallthrough[i], handle); + if (result) return result; + } } }; // Modifier key presses don't count as 'real' key presses for the // purpose of keymap fallthrough. - var isModifierKey = CodeMirror.isModifierKey = function(event) { - var name = keyNames[event.keyCode]; + var isModifierKey = CodeMirror.isModifierKey = function(value) { + var name = typeof value == "string" ? value : keyNames[value.keyCode]; return name == "Ctrl" || name == "Alt" || name == "Shift" || name == "Mod"; }; // Look up the name of a key as indicated by an event object. var keyName = CodeMirror.keyName = function(event, noShift) { if (presto && event.keyCode == 34 && event["char"]) return false; - var name = keyNames[event.keyCode]; + var base = keyNames[event.keyCode], name = base; if (name == null || event.altGraphKey) return false; - if (event.altKey) name = "Alt-" + name; - if (flipCtrlCmd ? event.metaKey : event.ctrlKey) name = "Ctrl-" + name; - if (flipCtrlCmd ? event.ctrlKey : event.metaKey) name = "Cmd-" + name; - if (!noShift && event.shiftKey) name = "Shift-" + name; + if (event.altKey && base != "Alt") name = "Alt-" + name; + if ((flipCtrlCmd ? event.metaKey : event.ctrlKey) && base != "Ctrl") name = "Ctrl-" + name; + if ((flipCtrlCmd ? event.ctrlKey : event.metaKey) && base != "Cmd") name = "Cmd-" + name; + if (!noShift && event.shiftKey && base != "Shift") name = "Shift-" + name; return name; }; + function getKeyMap(val) { + return typeof val == "string" ? keyMap[val] : val; + } + // FROMTEXTAREA CodeMirror.fromTextArea = function(textarea, options) { @@ -4988,6 +5035,7 @@ cm.save = save; cm.getTextArea = function() { return textarea; }; cm.toTextArea = function() { + cm.toTextArea = isNaN; // Prevent this from being ran twice save(); textarea.parentNode.removeChild(cm.getWrapperElement()); textarea.style.display = ""; @@ -5795,20 +5843,44 @@ if (inner.mode.blankLine) return inner.mode.blankLine(inner.state); } - function readToken(mode, stream, state) { + function readToken(mode, stream, state, inner) { for (var i = 0; i < 10; i++) { + if (inner) inner[0] = CodeMirror.innerMode(mode, state).mode; var style = mode.token(stream, state); if (stream.pos > stream.start) return style; } throw new Error("Mode " + mode.name + " failed to advance stream."); } + // Utility for getTokenAt and getLineTokens + function takeToken(cm, pos, precise, asArray) { + function getObj(copy) { + return {start: stream.start, end: stream.pos, + string: stream.current(), + type: style || null, + state: copy ? copyState(doc.mode, state) : state}; + } + + var doc = cm.doc, mode = doc.mode, style; + pos = clipPos(doc, pos); + var line = getLine(doc, pos.line), state = getStateBefore(cm, pos.line, precise); + var stream = new StringStream(line.text, cm.options.tabSize), tokens; + if (asArray) tokens = []; + while ((asArray || stream.pos < pos.ch) && !stream.eol()) { + stream.start = stream.pos; + style = readToken(mode, stream, state); + if (asArray) tokens.push(getObj(true)); + } + return asArray ? tokens : getObj(); + } + // Run the given mode's parser over a line, calling f for each token. function runMode(cm, text, mode, state, f, lineClasses, forceToEnd) { var flattenSpans = mode.flattenSpans; if (flattenSpans == null) flattenSpans = cm.options.flattenSpans; var curStart = 0, curStyle = null; var stream = new StringStream(text, cm.options.tabSize), style; + var inner = cm.options.addModeClass && [null]; if (text == "") extractLineClasses(callBlankLine(mode, state), lineClasses); while (!stream.eol()) { if (stream.pos > cm.options.maxHighlightLength) { @@ -5817,10 +5889,10 @@ stream.pos = text.length; style = null; } else { - style = extractLineClasses(readToken(mode, stream, state), lineClasses); + style = extractLineClasses(readToken(mode, stream, state, inner), lineClasses); } - if (cm.options.addModeClass) { - var mName = CodeMirror.innerMode(mode, state).mode.name; + if (inner) { + var mName = inner[0].name; if (mName) style = "m-" + (style ? mName + " " + style : mName); } if (!flattenSpans || curStyle != style) { @@ -5879,12 +5951,13 @@ return {styles: st, classes: lineClasses.bgClass || lineClasses.textClass ? lineClasses : null}; } - function getLineStyles(cm, line) { + function getLineStyles(cm, line, updateFrontier) { if (!line.styles || line.styles[0] != cm.state.modeGen) { var result = highlightLine(cm, line, line.stateAfter = getStateBefore(cm, lineNo(line))); line.styles = result.styles; if (result.classes) line.styleClasses = result.classes; else if (line.styleClasses) line.styleClasses = null; + if (updateFrontier === cm.doc.frontier) cm.doc.frontier++; } return line.styles; } @@ -5939,7 +6012,8 @@ if (hasBadBidiRects(cm.display.measure) && (order = getOrder(line))) builder.addToken = buildTokenBadBidi(builder.addToken, order); builder.map = []; - insertLineContent(line, builder, getLineStyles(cm, line)); + var allowFrontierUpdate = lineView != cm.display.externalMeasured && lineNo(line); + insertLineContent(line, builder, getLineStyles(cm, line, allowFrontierUpdate)); if (line.styleClasses) { if (line.styleClasses.bgClass) builder.bgClass = joinClasses(line.styleClasses.bgClass, builder.bgClass || ""); @@ -5961,9 +6035,14 @@ } } + // See issue #2901 + if (webkit && /\bcm-tab\b/.test(builder.content.lastChild.className)) + builder.content.className = "cm-tab-wrap-hack"; + signal(cm, "renderLine", cm, lineView.line, builder.pre); if (builder.pre.className) builder.textClass = joinClasses(builder.pre.className, builder.textClass || ""); + return builder; } @@ -6532,22 +6611,26 @@ }, addLineClass: docMethodOp(function(handle, where, cls) { - return changeLine(this, handle, "class", function(line) { - var prop = where == "text" ? "textClass" : where == "background" ? "bgClass" : "wrapClass"; + return changeLine(this, handle, where == "gutter" ? "gutter" : "class", function(line) { + var prop = where == "text" ? "textClass" + : where == "background" ? "bgClass" + : where == "gutter" ? "gutterClass" : "wrapClass"; if (!line[prop]) line[prop] = cls; - else if (new RegExp("(?:^|\\s)" + cls + "(?:$|\\s)").test(line[prop])) return false; + else if (classTest(cls).test(line[prop])) return false; else line[prop] += " " + cls; return true; }); }), removeLineClass: docMethodOp(function(handle, where, cls) { return changeLine(this, handle, "class", function(line) { - var prop = where == "text" ? "textClass" : where == "background" ? "bgClass" : "wrapClass"; + var prop = where == "text" ? "textClass" + : where == "background" ? "bgClass" + : where == "gutter" ? "gutterClass" : "wrapClass"; var cur = line[prop]; if (!cur) return false; else if (cls == null) line[prop] = null; else { - var found = cur.match(new RegExp("(?:^|\\s+)" + cls + "(?:$|\\s+)")); + var found = cur.match(classTest(cls)); if (!found) return false; var end = found.index + found[0].length; line[prop] = cur.slice(0, found.index) + (!found.index || end == cur.length ? "" : " ") + cur.slice(end) || null; @@ -7166,6 +7249,8 @@ // registering a (non-DOM) handler on the editor for the event name, // and preventDefault-ing the event in that handler. function signalDOMEvent(cm, e, override) { + if (typeof e == "string") + e = {type: e, preventDefault: function() { this.defaultPrevented = true; }}; signal(cm, override || e.type, cm, e); return e_defaultPrevented(e) || e.codemirrorIgnore; } @@ -7339,7 +7424,8 @@ }; else range = function(node, start, end) { var r = document.body.createTextRange(); - r.moveToElementText(node.parentNode); + try { r.moveToElementText(node.parentNode); } + catch(e) { return r; } r.collapse(true); r.moveEnd("character", end); r.moveStart("character", start); @@ -7371,14 +7457,19 @@ catch(e) { return document.body; } }; - function classTest(cls) { return new RegExp("\\b" + cls + "\\b\\s*"); } - function rmClass(node, cls) { - var test = classTest(cls); - if (test.test(node.className)) node.className = node.className.replace(test, ""); - } - function addClass(node, cls) { - if (!classTest(cls).test(node.className)) node.className += " " + cls; - } + function classTest(cls) { return new RegExp("(^|\\s)" + cls + "(?:$|\\s)\\s*"); } + var rmClass = CodeMirror.rmClass = function(node, cls) { + var current = node.className; + var match = classTest(cls).exec(current); + if (match) { + var after = current.slice(match.index + match[0].length); + node.className = current.slice(0, match.index) + (after ? match[1] + after : ""); + } + }; + var addClass = CodeMirror.addClass = function(node, cls) { + var current = node.className; + if (!classTest(cls).test(current)) node.className += (current ? " " : "") + cls; + }; function joinClasses(a, b) { var as = a.split(" "); for (var i = 0; i < as.length; i++) @@ -7825,7 +7916,7 @@ // THE END - CodeMirror.version = "4.6.0"; + CodeMirror.version = "4.8.0"; return CodeMirror; }); diff --git a/media/editors/codemirror/lib/codemirror.css b/media/editors/codemirror/lib/codemirror.css index b58ef2c8bb814..9f8547d69a452 100644 --- a/media/editors/codemirror/lib/codemirror.css +++ b/media/editors/codemirror/lib/codemirror.css @@ -1 +1 @@ -.CodeMirror{font-family:monospace;height:300px}.CodeMirror-scroll{overflow:auto}.CodeMirror-lines{padding:4px 0}.CodeMirror pre{padding:0 4px}.CodeMirror-scrollbar-filler,.CodeMirror-gutter-filler{background-color:white}.CodeMirror-gutters{border-right:1px solid #ddd;background-color:#f7f7f7;white-space:nowrap}.CodeMirror-linenumber{padding:0 3px 0 5px;min-width:20px;text-align:right;color:#999;-moz-box-sizing:content-box;box-sizing:content-box}.CodeMirror-guttermarker{color:black}.CodeMirror-guttermarker-subtle{color:#999}.CodeMirror div.CodeMirror-cursor{border-left:1px solid black}.CodeMirror div.CodeMirror-secondarycursor{border-left:1px solid silver}.CodeMirror.cm-keymap-fat-cursor div.CodeMirror-cursor{width:auto;border:0;background:#7e7}.CodeMirror.cm-keymap-fat-cursor div.CodeMirror-cursors{z-index:1}.cm-animate-fat-cursor{width:auto;border:0;-webkit-animation:blink 1.06s steps(1) infinite;-moz-animation:blink 1.06s steps(1) infinite;animation:blink 1.06s steps(1) infinite}@-moz-keyframes blink{0%{background:#7e7}50%{background:0}100%{background:#7e7}}@-webkit-keyframes blink{0%{background:#7e7}50%{background:0}100%{background:#7e7}}@keyframes blink{0%{background:#7e7}50%{background:0}100%{background:#7e7}}.cm-tab{display:inline-block}.CodeMirror-ruler{border-left:1px solid #ccc;position:absolute}.cm-s-default .cm-keyword{color:#708}.cm-s-default .cm-atom{color:#219}.cm-s-default .cm-number{color:#164}.cm-s-default .cm-def{color:#00f}.cm-s-default .cm-variable-2{color:#05a}.cm-s-default .cm-variable-3{color:#085}.cm-s-default .cm-comment{color:#a50}.cm-s-default .cm-string{color:#a11}.cm-s-default .cm-string-2{color:#f50}.cm-s-default .cm-meta{color:#555}.cm-s-default .cm-qualifier{color:#555}.cm-s-default .cm-builtin{color:#30a}.cm-s-default .cm-bracket{color:#997}.cm-s-default .cm-tag{color:#170}.cm-s-default .cm-attribute{color:#00c}.cm-s-default .cm-header{color:blue}.cm-s-default .cm-quote{color:#090}.cm-s-default .cm-hr{color:#999}.cm-s-default .cm-link{color:#00c}.cm-negative{color:#d44}.cm-positive{color:#292}.cm-header,.cm-strong{font-weight:bold}.cm-em{font-style:italic}.cm-link{text-decoration:underline}.cm-s-default .cm-error{color:#f00}.cm-invalidchar{color:#f00}div.CodeMirror span.CodeMirror-matchingbracket{color:#0f0}div.CodeMirror span.CodeMirror-nonmatchingbracket{color:#f22}.CodeMirror-matchingtag{background:rgba(255,150,0,.3)}.CodeMirror-activeline-background{background:#e8f2ff}.CodeMirror{line-height:1;position:relative;overflow:hidden;background:white;color:black}.CodeMirror-scroll{margin-bottom:-30px;margin-right:-30px;padding-bottom:30px;height:100%;outline:0;position:relative;-moz-box-sizing:content-box;box-sizing:content-box}.CodeMirror-sizer{position:relative;border-right:30px solid transparent;-moz-box-sizing:content-box;box-sizing:content-box}.CodeMirror-vscrollbar,.CodeMirror-hscrollbar,.CodeMirror-scrollbar-filler,.CodeMirror-gutter-filler{position:absolute;z-index:6;display:none}.CodeMirror-vscrollbar{right:0;top:0;overflow-x:hidden;overflow-y:scroll}.CodeMirror-hscrollbar{bottom:0;left:0;overflow-y:hidden;overflow-x:scroll}.CodeMirror-scrollbar-filler{right:0;bottom:0}.CodeMirror-gutter-filler{left:0;bottom:0}.CodeMirror-gutters{position:absolute;left:0;top:0;padding-bottom:30px;z-index:3}.CodeMirror-gutter{white-space:normal;height:100%;-moz-box-sizing:content-box;box-sizing:content-box;padding-bottom:30px;margin-bottom:-32px;display:inline-block;*zoom:1;*display:inline}.CodeMirror-gutter-elt{position:absolute;cursor:default;z-index:4}.CodeMirror-lines{cursor:text;min-height:1px}.CodeMirror pre{-moz-border-radius:0;-webkit-border-radius:0;border-radius:0;border-width:0;background:transparent;font-family:inherit;font-size:inherit;margin:0;white-space:pre;word-wrap:normal;line-height:inherit;color:inherit;z-index:2;position:relative;overflow:visible}.CodeMirror-wrap pre{word-wrap:break-word;white-space:pre-wrap;word-break:normal}.CodeMirror-linebackground{position:absolute;left:0;right:0;top:0;bottom:0;z-index:0}.CodeMirror-linewidget{position:relative;z-index:2;overflow:auto}.CodeMirror-wrap .CodeMirror-scroll{overflow-x:hidden}.CodeMirror-measure{position:absolute;width:100%;height:0;overflow:hidden;visibility:hidden}.CodeMirror-measure pre{position:static}.CodeMirror div.CodeMirror-cursor{position:absolute;border-right:0;width:0}div.CodeMirror-cursors{visibility:hidden;position:relative;z-index:3}.CodeMirror-focused div.CodeMirror-cursors{visibility:visible}.CodeMirror-selected{background:#d9d9d9}.CodeMirror-focused .CodeMirror-selected{background:#d7d4f0}.CodeMirror-crosshair{cursor:crosshair}.cm-searching{background:#ffa;background:rgba(255,255,0,.4)}.CodeMirror span{*vertical-align:text-bottom}.cm-force-border{padding-right:.1px}@media print{.CodeMirror div.CodeMirror-cursors{visibility:hidden}}span.CodeMirror-selectedtext{background:0} \ No newline at end of file +.CodeMirror{font-family:monospace;height:300px}.CodeMirror-scroll{overflow:auto}.CodeMirror-lines{padding:4px 0}.CodeMirror pre{padding:0 4px}.CodeMirror-scrollbar-filler,.CodeMirror-gutter-filler{background-color:white}.CodeMirror-gutters{border-right:1px solid #ddd;background-color:#f7f7f7;white-space:nowrap}.CodeMirror-linenumber{padding:0 3px 0 5px;min-width:20px;text-align:right;color:#999;-moz-box-sizing:content-box;box-sizing:content-box}.CodeMirror-guttermarker{color:black}.CodeMirror-guttermarker-subtle{color:#999}.CodeMirror div.CodeMirror-cursor{border-left:1px solid black}.CodeMirror div.CodeMirror-secondarycursor{border-left:1px solid silver}.CodeMirror.cm-fat-cursor div.CodeMirror-cursor{width:auto;border:0;background:#7e7}.CodeMirror.cm-fat-cursor div.CodeMirror-cursors{z-index:1}.cm-animate-fat-cursor{width:auto;border:0;-webkit-animation:blink 1.06s steps(1) infinite;-moz-animation:blink 1.06s steps(1) infinite;animation:blink 1.06s steps(1) infinite}@-moz-keyframes blink{0%{background:#7e7}50%{background:0}100%{background:#7e7}}@-webkit-keyframes blink{0%{background:#7e7}50%{background:0}100%{background:#7e7}}@keyframes blink{0%{background:#7e7}50%{background:0}100%{background:#7e7}}.cm-tab{display:inline-block;text-decoration:inherit}.CodeMirror-ruler{border-left:1px solid #ccc;position:absolute}.cm-s-default .cm-keyword{color:#708}.cm-s-default .cm-atom{color:#219}.cm-s-default .cm-number{color:#164}.cm-s-default .cm-def{color:#00f}.cm-s-default .cm-variable-2{color:#05a}.cm-s-default .cm-variable-3{color:#085}.cm-s-default .cm-comment{color:#a50}.cm-s-default .cm-string{color:#a11}.cm-s-default .cm-string-2{color:#f50}.cm-s-default .cm-meta{color:#555}.cm-s-default .cm-qualifier{color:#555}.cm-s-default .cm-builtin{color:#30a}.cm-s-default .cm-bracket{color:#997}.cm-s-default .cm-tag{color:#170}.cm-s-default .cm-attribute{color:#00c}.cm-s-default .cm-header{color:blue}.cm-s-default .cm-quote{color:#090}.cm-s-default .cm-hr{color:#999}.cm-s-default .cm-link{color:#00c}.cm-negative{color:#d44}.cm-positive{color:#292}.cm-header,.cm-strong{font-weight:bold}.cm-em{font-style:italic}.cm-link{text-decoration:underline}.cm-strikethrough{text-decoration:line-through}.cm-s-default .cm-error{color:#f00}.cm-invalidchar{color:#f00}div.CodeMirror span.CodeMirror-matchingbracket{color:#0f0}div.CodeMirror span.CodeMirror-nonmatchingbracket{color:#f22}.CodeMirror-matchingtag{background:rgba(255,150,0,.3)}.CodeMirror-activeline-background{background:#e8f2ff}.CodeMirror{line-height:1;position:relative;overflow:hidden;background:white;color:black}.CodeMirror-scroll{margin-bottom:-30px;margin-right:-30px;padding-bottom:30px;height:100%;outline:0;position:relative;-moz-box-sizing:content-box;box-sizing:content-box}.CodeMirror-sizer{position:relative;border-right:30px solid transparent;-moz-box-sizing:content-box;box-sizing:content-box}.CodeMirror-vscrollbar,.CodeMirror-hscrollbar,.CodeMirror-scrollbar-filler,.CodeMirror-gutter-filler{position:absolute;z-index:6;display:none}.CodeMirror-vscrollbar{right:0;top:0;overflow-x:hidden;overflow-y:scroll}.CodeMirror-hscrollbar{bottom:0;left:0;overflow-y:hidden;overflow-x:scroll}.CodeMirror-scrollbar-filler{right:0;bottom:0}.CodeMirror-gutter-filler{left:0;bottom:0}.CodeMirror-gutters{position:absolute;left:0;top:0;padding-bottom:30px;z-index:3}.CodeMirror-gutter{white-space:normal;height:100%;-moz-box-sizing:content-box;box-sizing:content-box;padding-bottom:30px;margin-bottom:-32px;display:inline-block;*zoom:1;*display:inline}.CodeMirror-gutter-wrapper{position:absolute;z-index:4;height:100%}.CodeMirror-gutter-elt{position:absolute;cursor:default;z-index:4}.CodeMirror-lines{cursor:text;min-height:1px}.CodeMirror pre{-moz-border-radius:0;-webkit-border-radius:0;border-radius:0;border-width:0;background:transparent;font-family:inherit;font-size:inherit;margin:0;white-space:pre;word-wrap:normal;line-height:inherit;color:inherit;z-index:2;position:relative;overflow:visible}.CodeMirror-wrap pre{word-wrap:break-word;white-space:pre-wrap;word-break:normal}.CodeMirror-linebackground{position:absolute;left:0;right:0;top:0;bottom:0;z-index:0}.CodeMirror-linewidget{position:relative;z-index:2;overflow:auto}.CodeMirror-wrap .CodeMirror-scroll{overflow-x:hidden}.CodeMirror-measure{position:absolute;width:100%;height:0;overflow:hidden;visibility:hidden}.CodeMirror-measure pre{position:static}.CodeMirror div.CodeMirror-cursor{position:absolute;border-right:0;width:0}div.CodeMirror-cursors{visibility:hidden;position:relative;z-index:3}.CodeMirror-focused div.CodeMirror-cursors{visibility:visible}.CodeMirror-selected{background:#d9d9d9}.CodeMirror-focused .CodeMirror-selected{background:#d7d4f0}.CodeMirror-crosshair{cursor:crosshair}.cm-searching{background:#ffa;background:rgba(255,255,0,.4)}.CodeMirror span{*vertical-align:text-bottom}.cm-force-border{padding-right:.1px}@media print{.CodeMirror div.CodeMirror-cursors{visibility:hidden}}.cm-tab-wrap-hack:after{content:''}span.CodeMirror-selectedtext{background:0} \ No newline at end of file diff --git a/media/editors/codemirror/lib/codemirror.js b/media/editors/codemirror/lib/codemirror.js index 22a1e9f27f1dd..0f2830b3041ec 100644 --- a/media/editors/codemirror/lib/codemirror.js +++ b/media/editors/codemirror/lib/codemirror.js @@ -1 +1 @@ -(function(a){if(typeof exports=="object"&&typeof module=="object"){module.exports=a()}else{if(typeof define=="function"&&define.amd){return define([],a)}else{this.CodeMirror=a()}}})(function(){var cn=/gecko\/\d/i.test(navigator.userAgent);var ey=/MSIE \d/.test(navigator.userAgent);var bH=/Trident\/(?:[7-9]|\d{2,})\..*rv:(\d+)/.exec(navigator.userAgent);var dz=ey||bH;var l=dz&&(ey?document.documentMode||6:bH[1]);var cU=/WebKit\//.test(navigator.userAgent);var dB=cU&&/Qt\/\d+\.\d+/.test(navigator.userAgent);var c6=/Chrome\//.test(navigator.userAgent);var dQ=/Opera\//.test(navigator.userAgent);var aB=/Apple Computer/.test(navigator.vendor);var a7=/KHTML\//.test(navigator.userAgent);var c1=/Mac OS X 1\d\D([8-9]|\d\d)\D/.test(navigator.userAgent);var fi=/PhantomJS/.test(navigator.userAgent);var eP=/AppleWebKit/.test(navigator.userAgent)&&/Mobile\/\w+/.test(navigator.userAgent);var d3=eP||/Android|webOS|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(navigator.userAgent);var b5=eP||/Mac/.test(navigator.platform);var aM=/win/i.test(navigator.platform);var aU=dQ&&navigator.userAgent.match(/Version\/(\d*\.\d*)/);if(aU){aU=Number(aU[1])}if(aU&&aU>=15){dQ=false;cU=true}var bO=b5&&(dB||dQ&&(aU==null||aU<12.11));var fS=cn||(dz&&l>=9);var fV=false,a3=false;function J(f2,f3){if(!(this instanceof J)){return new J(f2,f3)}this.options=f3=f3||{};aK(eR,f3,false);cc(f3);var f5=f3.value;if(typeof f5=="string"){f5=new at(f5,f3.mode)}this.doc=f5;var f4=this.display=new ew(f2,f5);f4.wrapper.CodeMirror=this;dZ(this);cK(this);if(f3.lineWrapping){this.display.wrapper.className+=" CodeMirror-wrap"}if(f3.autofocus&&!d3){en(this)}this.state={keyMaps:[],overlays:[],modeGen:0,overwrite:false,focused:false,suppressEdits:false,pasteIncoming:false,cutIncoming:false,draggingText:false,highlight:new f0()};if(dz&&l<11){setTimeout(ct(fc,this,true),20)}fD(this);be();var f1=this;cI(this,function(){f1.curOp.forceUpdate=true;dY(f1,f5);if((f3.autofocus&&!d3)||dC()==f4.input){setTimeout(ct(cy,f1),20)}else{aR(f1)}for(var f7 in ba){if(ba.hasOwnProperty(f7)){ba[f7](f1,f3[f7],ca)}}dT(f1);for(var f6=0;f6f3.maxLineLength){f3.maxLineLength=f4;f3.maxLine=f5}})}function cc(f1){var f2=db(f1.gutters,"CodeMirror-linenumbers");if(f2==-1&&f1.lineNumbers){f1.gutters=f1.gutters.concat(["CodeMirror-linenumbers"])}else{if(f2>-1&&!f1.lineNumbers){f1.gutters=f1.gutters.slice(0);f1.gutters.splice(f2,1)}}}function cM(f1){return f1.display.scroller.clientHeight-f1.display.wrapper.clientHeightf1.clientWidth;if(f3&&f1.scrollWidth<=f1.clientWidth+1&&f2>0&&!f1.hScrollbarTakesSpace){f3=false}var f4=f9>f1.clientHeight;if(f4){f5.scrollbarV.style.display="block";f5.scrollbarV.style.bottom=f3?f2+"px":"0";f5.scrollbarV.firstChild.style.height=Math.max(0,f9-f1.clientHeight+(f1.barHeight||f5.scrollbarV.clientHeight))+"px"}else{f5.scrollbarV.style.display="";f5.scrollbarV.firstChild.style.height="0"}if(f3){f5.scrollbarH.style.display="block";f5.scrollbarH.style.right=f4?f2+"px":"0";f5.scrollbarH.firstChild.style.width=(f1.scrollWidth-f1.clientWidth+(f1.barWidth||f5.scrollbarH.clientWidth))+"px"}else{f5.scrollbarH.style.display="";f5.scrollbarH.firstChild.style.width="0"}if(f3&&f4){f5.scrollbarFiller.style.display="block";f5.scrollbarFiller.style.height=f5.scrollbarFiller.style.width=f2+"px"}else{f5.scrollbarFiller.style.display=""}if(f3&&f8.options.coverGutterNextToScrollbar&&f8.options.fixedGutter){f5.gutterFiller.style.display="block";f5.gutterFiller.style.height=f2+"px";f5.gutterFiller.style.width=f5.gutters.offsetWidth+"px"}else{f5.gutterFiller.style.display=""}if(!f8.state.checkedOverlayScrollbar&&f1.clientHeight>0){if(f2===0){var f7=b5&&!c1?"12px":"18px";f5.scrollbarV.style.minWidth=f5.scrollbarH.style.minHeight=f7;var f6=function(ga){if(M(ga)!=f5.scrollbarV&&M(ga)!=f5.scrollbarH){cW(f8,eg)(ga)}};bV(f5.scrollbarV,"mousedown",f6);bV(f5.scrollbarH,"mousedown",f6)}f8.state.checkedOverlayScrollbar=true}}function b4(f4,f8,f3){var f5=f3&&f3.top!=null?Math.max(0,f3.top):f4.scroller.scrollTop;f5=Math.floor(f5-eV(f4));var f1=f3&&f3.bottom!=null?f3.bottom:f5+f4.wrapper.clientHeight;var f6=bE(f8,f5),f7=bE(f8,f1);if(f3&&f3.ensure){var f2=f3.ensure.from.line,f9=f3.ensure.to.line;if(f2=f7){return{from:bE(f8,bK(e2(f8,f9))-f4.wrapper.clientHeight),to:f9}}}return{from:f6,to:Math.max(f7,f6+1)}}function es(f9){var f7=f9.display,f8=f7.view;if(!f7.alignWidgets&&(!f7.gutters.firstChild||!f9.options.fixedGutter)){return}var f5=dL(f7)-f7.scroller.scrollLeft+f9.doc.scrollLeft;var f1=f7.gutters.offsetWidth,f2=f5+"px";for(var f4=0;f4=f5.viewFrom&&f4.visible.to<=f5.viewTo&&(f5.updateLineNumbers==null||f5.updateLineNumbers>=f5.viewTo)&&c5(ga)==0){return false}if(dT(ga)){ek(ga);f4.dims=e0(ga)}var f3=f9.first+f9.size;var f7=Math.max(f4.visible.from-ga.options.viewportMargin,f9.first);var f8=Math.min(f3,f4.visible.to+ga.options.viewportMargin);if(f5.viewFromf8&&f5.viewTo-f8<20){f8=Math.min(f3,f5.viewTo)}if(a3){f7=aS(ga.doc,f7);f8=dR(ga.doc,f8)}var f2=f7!=f5.viewFrom||f8!=f5.viewTo||f5.lastSizeC!=f4.wrapperHeight;cN(ga,f7,f8);f5.viewOffset=bK(e2(ga.doc,f5.viewFrom));ga.display.mover.style.top=f5.viewOffset+"px";var f1=c5(ga);if(!f2&&f1==0&&!f4.force&&(f5.updateLineNumbers==null||f5.updateLineNumbers>=f5.viewTo)){return false}var f6=dC();if(f1>4){f5.lineDiv.style.display="none"}cl(ga,f5.updateLineNumbers,f4.dims);if(f1>4){f5.lineDiv.style.display=""}if(f6&&dC()!=f6&&f6.offsetHeight){f6.focus()}dP(f5.cursorDiv);dP(f5.selectionDiv);if(f2){f5.lastSizeC=f4.wrapperHeight;d2(ga,400)}f5.updateLineNumbers=null;return true}function ci(f2,f6){var f4=f6.force,f1=f6.viewport;for(var f5=true;;f5=false){if(f5&&f2.options.lineWrapping&&f6.oldScrollerWidth!=f2.display.scroller.clientWidth){f4=true}else{f4=false;if(f1&&f1.top!=null){f1={top:Math.min(f2.doc.height+bG(f2.display)-bg-f2.display.scroller.clientHeight,f1.top)}}f6.visible=b4(f2.display,f2.doc,f1);if(f6.visible.from>=f2.display.viewFrom&&f6.visible.to<=f2.display.viewTo){break}}if(!D(f2,f6)){break}a5(f2);var f3=dq(f2);bA(f2);dp(f2,f3);eM(f2,f3)}ad(f2,"update",f2);if(f2.display.viewFrom!=f6.oldViewFrom||f2.display.viewTo!=f6.oldViewTo){ad(f2,"viewportChange",f2,f2.display.viewFrom,f2.display.viewTo)}}function dH(f2,f1){var f4=new aG(f2,f1);if(D(f2,f4)){a5(f2);ci(f2,f4);var f3=dq(f2);bA(f2);dp(f2,f3);eM(f2,f3)}}function dp(f1,f2){f1.display.sizer.style.minHeight=f1.display.heightForcer.style.top=f2.docHeight+"px";f1.display.gutters.style.height=Math.max(f2.docHeight,f2.clientHeight-bg)+"px"}function fN(f1,f2){if(f1.display.sizer.offsetWidth+f1.display.gutters.offsetWidth0.001||f7<-0.001){fO(f9.line,ga);b9(f9.line);if(f9.rest){for(var f1=0;f1-1){ga=false}aa(gc,f5,f6,gb)}if(ga){dP(f5.lineNumber);f5.lineNumber.appendChild(document.createTextNode(ef(gc.options,f6)))}gd=f5.node.nextSibling}}f6+=f5.size}while(gd){gd=f7(gd)}}function aa(f1,f3,f5,f6){for(var f2=0;f2=0&&cd(f4,f2.to())<=0){return f3}}return -1}};function dM(f1,f2){this.anchor=f1;this.head=f2}dM.prototype={from:function(){return aq(this.anchor,this.head)},to:function(){return bv(this.anchor,this.head)},empty:function(){return this.head.line==this.anchor.line&&this.head.ch==this.anchor.ch}};function cu(f1,f8){var f3=f1[f8];f1.sort(function(gb,ga){return cd(gb.from(),ga.from())});f8=db(f1,f3);for(var f5=1;f5=0){var f6=aq(f2.from(),f9.from()),f7=bv(f2.to(),f9.to());var f4=f2.empty()?f9.from()==f9.head:f2.from()==f2.head;if(f5<=f8){--f8}f1.splice(--f5,2,new dM(f4?f7:f6,f4?f6:f7))}}return new fL(f1,f8)}function eG(f1,f2){return new fL([new dM(f1,f2||f1)],0)}function cZ(f1,f2){return Math.max(f1.first,Math.min(f2,f1.first+f1.size-1))}function fx(f2,f3){if(f3.linef1){return X(f1,e2(f2,f1).text.length)}return fg(f3,e2(f2,f3.line).text.length)}function fg(f3,f2){var f1=f3.ch;if(f1==null||f1>f2){return X(f3.line,f2)}else{if(f1<0){return X(f3.line,0)}else{return f3}}}function b7(f2,f1){return f1>=f2.first&&f1=f3.ch:f1.to>f3.ch))){if(f7){aC(f2,"beforeCursorEnter");if(f2.explicitlyCleared){if(!gc.markedSpans){break}else{--f5;continue}}}if(!f2.atomic){continue}var f8=f2.find(f4<0?-1:1);if(cd(f8,f3)==0){f8.ch+=f4;if(f8.ch<0){if(f8.line>ga.first){f8=fx(ga,X(f8.line-1))}else{f8=null}}else{if(f8.ch>gc.text.length){if(f8.line3){gc(gw,gu.top,null,gu.bottom);gw=f4;if(gu.bottomgj.bottom||gv.bottom==gj.bottom&&gv.right>gj.right){gj=gv}if(gw0){f3.blinker=setInterval(function(){f3.cursorDiv.style.visibility=(f2=!f2)?"":"hidden"},f1.options.cursorBlinkRate)}else{if(f1.options.cursorBlinkRate<0){f3.cursorDiv.style.visibility="hidden"}}}function d2(f1,f2){if(f1.doc.mode.startState&&f1.doc.frontier=f1.display.viewTo){return}var f3=+new Date+f1.options.workTime;var f4=b1(f5.mode,dr(f1,f5.frontier));var f2=[];f5.iter(f5.frontier,Math.min(f5.first+f5.size,f1.display.viewTo+500),function(f6){if(f5.frontier>=f1.display.viewFrom){var f9=f6.styles;var gb=fn(f1,f6,f4,true);f6.styles=gb.styles;var f8=f6.styleClasses,ga=gb.classes;if(ga){f6.styleClasses=ga}else{if(f8){f6.styleClasses=null}}var gc=!f9||f9.length!=f6.styles.length||f8!=ga&&(!f8||!ga||f8.bgClass!=ga.bgClass||f8.textClass!=ga.textClass);for(var f7=0;!gc&&f7f3){d2(f1,f1.options.workDelay);return true}});if(f2.length){cI(f1,function(){for(var f6=0;f6f3;--ga){if(ga<=f6.first){return f6.first}var f9=e2(f6,ga-1);if(f9.stateAfter&&(!f4||ga<=f6.frontier)){return ga}var f8=bR(f9.text,null,f7.options.tabSize);if(f5==null||f2>f8){f5=ga-1;f2=f8}}return f5}function dr(f1,f7,f2){var f5=f1.doc,f4=f1.display;if(!f5.mode.startState){return true}var f6=cw(f1,f7,f2),f3=f6>f5.first&&e2(f5,f6-1).stateAfter;if(!f3){f3=bY(f5.mode)}else{f3=b1(f5.mode,f3)}f5.iter(f6,f7,function(f8){dm(f1,f8.text,f3);var f9=f6==f7-1||f6%5==0||f6>=f4.viewFrom&&f62){f6.push((f9.bottom+f2.top)/2-f7.top)}}}f6.push(f7.bottom-f7.top)}}function cr(f3,f1,f4){if(f3.line==f1){return{map:f3.measure.map,cache:f3.measure.cache}}for(var f2=0;f2f4){return{map:f3.measure.maps[f2],cache:f3.measure.caches[f2],before:true}}}}function cV(f1,f3){f3=z(f3);var f5=bL(f3);var f2=f1.display.externalMeasured=new bt(f1.doc,f3,f5);f2.lineN=f5;var f4=f2.built=eF(f1,f2);f2.text=f4.pre;bP(f1.display.lineMeasure,f4.pre);return f2}function d4(f1,f2,f4,f3){return E(f1,a0(f1,f2),f4,f3)}function eY(f1,f3){if(f3>=f1.display.viewFrom&&f3=f2.lineN&&f3ga){f4=gg-gk;f5=f4-1;if(ga>=gg){f1="right"}}}}if(f5!=null){gf=gm[gh+2];if(gk==gg&&f6==(gf.insertLeft?"left":"right")){f1=f6}if(f6=="left"&&f5==0){while(gh&&gm[gh-2]==gm[gh-3]&&gm[gh-1].insertLeft){gf=gm[(gh-=3)+2];f1="left"}}if(f6=="right"&&f5==gg-gk){while(gh0){f1=f6="right"}var f3;if(f8.options.lineWrapping&&(f3=gf.getClientRects()).length>1){f2=f3[f6=="right"?f3.length-1:0]}else{f2=gf.getBoundingClientRect()}}if(dz&&l<9&&!f5&&(!f2||!f2.left&&!f2.right)){var f7=gf.parentNode.getClientRects()[0];if(f7){f2={left:f7.left,right:f7.left+dt(f8.display),top:f7.top,bottom:f7.bottom}}else{f2=eo}}var gd=f2.top-gi.rect.top,gb=f2.bottom-gi.rect.top;var gl=(gd+gb)/2;var gj=gi.view.measure.heights;for(var gh=0;ghge.from){return f5(gg-1)}return f5(gg,gf)}var f6=a(f7),f1=f9.ch;if(!f6){return f5(f1)}var f2=aE(f6,f1);var f4=gb(f1,f2);if(eQ!=null){f4.other=gb(f1,eQ)}return f4}function dx(f1,f5){var f4=0,f5=fx(f1.doc,f5);if(!f1.options.lineWrapping){f4=dt(f1.display)*f5.ch}var f2=e2(f1.doc,f5.line);var f3=bK(f2)+eV(f1.display);return{left:f4,right:f4,top:f3,bottom:f3+f2.height}}function fJ(f1,f2,f3,f5){var f4=X(f1,f2);f4.xRel=f5;if(f3){f4.outside=true}return f4}function fC(f8,f5,f4){var f7=f8.doc;f4+=f8.display.viewOffset;if(f4<0){return fJ(f7.first,0,true,-1)}var f3=bE(f7,f4),f9=f7.first+f7.size-1;if(f3>f9){return fJ(f7.first+f7.size-1,e2(f7,f9).text.length,true,1)}if(f5<0){f5=0}var f2=e2(f7,f3);for(;;){var ga=cT(f8,f2,f3,f5,f4);var f6=ei(f2);var f1=f6&&f6.find(0,true);if(f6&&(ga.ch>f1.from.ch||ga.ch==f1.from.ch&&ga.xRel>0)){f3=bL(f2=f1.to.line)}else{return ga}}}function cT(gb,f3,ge,gd,gc){var ga=gc-bK(f3);var f7=false,gk=2*gb.display.wrapper.clientWidth;var gh=a0(gb,f3);function go(gq){var gr=dI(gb,X(ge,gq),"line",f3,gh);f7=true;if(ga>gr.bottom){return gr.left-gk}else{if(gaf2){return fJ(ge,f4,f6,1)}for(;;){if(gg?f4==gl||f4==v(f3,gl,1):f4-gl<=1){var gf=gd1?1:0);return f9}var f8=Math.ceil(gj/2),gp=gl+f8;if(gg){gp=gl;for(var gm=0;gmgd){f4=gp;f2=f5;if(f6=f7){f2+=1000}gj=f8}else{gl=gp;gi=f5;f1=f7;gj-=f8}}}var aF;function aT(f3){if(f3.cachedTextHeight!=null){return f3.cachedTextHeight}if(aF==null){aF=fK("pre");for(var f2=0;f2<49;++f2){aF.appendChild(document.createTextNode("x"));aF.appendChild(fK("br"))}aF.appendChild(document.createTextNode("x"))}bP(f3.measure,aF);var f1=aF.offsetHeight/50;if(f1>3){f3.cachedTextHeight=f1}dP(f3.measure);return f1||1}function dt(f5){if(f5.cachedCharWidth!=null){return f5.cachedCharWidth}var f1=fK("span","xxxxxxxxxx");var f4=fK("pre",[f1]);bP(f5.measure,f4);var f3=f1.getBoundingClientRect(),f2=(f3.right-f3.left)/10;if(f2>2){f5.cachedCharWidth=f2}return f2||10}var bn=null;var dW=0;function cE(f1){f1.curOp={cm:f1,viewChanged:false,startHeight:f1.doc.height,forceUpdate:false,updateInput:null,typing:false,changeObjs:null,cursorActivityHandlers:null,cursorActivityCalled:0,selectionChanged:false,updateMaxLine:false,scrollLeft:null,scrollTop:null,scrollToPos:null,id:++dW};if(bn){bn.ops.push(f1.curOp)}else{f1.curOp.ownsGroup=bn={ops:[f1.curOp],delayedCallbacks:[]}}}function cP(f4){var f3=f4.delayedCallbacks,f2=0;do{for(;f2=f2.viewTo)||f2.maxLineChanged&&f1.options.lineWrapping;f3.update=f3.mustUpdate&&new aG(f1,f3.mustUpdate&&{top:f3.scrollTop,ensure:f3.scrollToPos},f3.forceUpdate)}function ap(f1){f1.updatedDisplay=f1.mustUpdate&&D(f1.cm,f1.update)}function b0(f3){var f1=f3.cm,f2=f1.display;if(f3.updatedDisplay){a5(f1)}f3.barMeasure=dq(f1);if(f2.maxLineChanged&&!f1.options.lineWrapping){f3.adjustWidthTo=d4(f1,f2.maxLine,f2.maxLine.text.length).left+3;f3.maxScrollLeft=Math.max(0,f2.sizer.offsetLeft+f3.adjustWidthTo+bg-f2.scroller.clientWidth)}if(f3.updatedDisplay||f3.selectionChanged){f3.newSelectionNodes=bj(f1)}}function ao(f2){var f1=f2.cm;if(f2.adjustWidthTo!=null){f1.display.sizer.style.minWidth=f2.adjustWidthTo+"px";if(f2.maxScrollLeft1){eM(ga)}if(f4.updatedDisplay){ci(ga,f4.update)}if(f6.wheelStartX!=null&&(f4.scrollTop!=null||f4.scrollLeft!=null||f4.scrollToPos)){f6.wheelStartX=f6.wheelStartY=null}if(f4.scrollTop!=null&&(f6.scroller.scrollTop!=f4.scrollTop||f4.forceScroll)){var f7=Math.max(0,Math.min(f6.scroller.scrollHeight-f6.scroller.clientHeight,f4.scrollTop));f6.scroller.scrollTop=f6.scrollbarV.scrollTop=f9.scrollTop=f7}if(f4.scrollLeft!=null&&(f6.scroller.scrollLeft!=f4.scrollLeft||f4.forceScroll)){var f2=Math.max(0,Math.min(f6.scroller.scrollWidth-f6.scroller.clientWidth,f4.scrollLeft));f6.scroller.scrollLeft=f6.scrollbarH.scrollLeft=f9.scrollLeft=f2;es(ga)}if(f4.scrollToPos){var f8=F(ga,fx(f9,f4.scrollToPos.from),fx(f9,f4.scrollToPos.to),f4.scrollToPos.margin);if(f4.scrollToPos.isCursor&&ga.state.focused){dU(ga,f8)}}var f5=f4.maybeHiddenMarkers,f1=f4.maybeUnhiddenMarkers;if(f5){for(var f3=0;f3f4.barMeasure.clientWidth&&f4.barMeasure.scrollWidthf6)){f3.updateLineNumbers=f6}f8.curOp.viewChanged=true;if(f6>=f3.viewTo){if(a3&&aS(f8.doc,f6)f3.viewFrom){ek(f8)}else{f3.viewFrom+=f9;f3.viewTo+=f9}}else{if(f6<=f3.viewFrom&&f7>=f3.viewTo){ek(f8)}else{if(f6<=f3.viewFrom){var f5=c8(f8,f7,f7+f9,1);if(f5){f3.view=f3.view.slice(f5.index);f3.viewFrom=f5.lineN;f3.viewTo+=f9}else{ek(f8)}}else{if(f7>=f3.viewTo){var f5=c8(f8,f6,f6,-1);if(f5){f3.view=f3.view.slice(0,f5.index);f3.viewTo=f5.lineN}else{ek(f8)}}else{var f4=c8(f8,f6,f6,-1);var f2=c8(f8,f7,f7+f9,1);if(f4&&f2){f3.view=f3.view.slice(0,f4.index).concat(eJ(f8,f4.lineN,f2.lineN)).concat(f3.view.slice(f2.index));f3.viewTo+=f9}else{ek(f8)}}}}}}var f1=f3.externalMeasured;if(f1){if(f7=f5.lineN&&f3=f7.viewTo){return}var f4=f7.view[dh(f2,f3)];if(f4.node==null){return}var f1=f4.changes||(f4.changes=[]);if(db(f1,f6)==-1){f1.push(f6)}}function ek(f1){f1.display.viewFrom=f1.display.viewTo=f1.doc.first;f1.display.view=[];f1.display.viewOffset=0}function dh(f1,f4){if(f4>=f1.display.viewTo){return null}f4-=f1.display.viewFrom;if(f4<0){return null}var f2=f1.display.view;for(var f3=0;f30){if(f6==f7.length-1){return null}f8=(f1+f7[f6].size)-f3;f6++}else{f8=f1-f3}f3+=f8;f5+=f8}while(aS(f9.doc,f5)!=f5){if(f6==(f2<0?0:f7.length-1)){return null}f5+=f2*f7[f6-(f2<0?1:0)].size;f6+=f2}return{index:f6,lineN:f5}}function cN(f1,f5,f4){var f3=f1.display,f2=f3.view;if(f2.length==0||f5>=f3.viewTo||f4<=f3.viewFrom){f3.view=eJ(f1,f5,f4);f3.viewFrom=f5}else{if(f3.viewFrom>f5){f3.view=eJ(f1,f5,f3.viewFrom).concat(f3.view)}else{if(f3.viewFromf4){f3.view=f3.view.slice(0,dh(f1,f4))}}}f3.viewTo=f4}function c5(f1){var f2=f1.display.view,f5=0;for(var f4=0;f4=9&&f5.display.inputHasSelection===f8||b5&&/[\uf700-\uf7ff]/.test(f8)){fc(f5);return false}var gg=!f5.curOp;if(gg){cE(f5)}f5.display.shift=false;if(f8.charCodeAt(0)==8203&&gk.sel==f5.display.selForContextMenu&&!f9){f9="\u200b"}var gf=0,gc=Math.min(f9.length,f8.length);while(gf1){if(bi&&bi.join("\n")==f2){gj=gk.sel.ranges.length%bi.length==0&&bQ(bi,aW)}else{if(ga.length==gk.sel.ranges.length){gj=bQ(ga,function(gl){return[gl]})}}}for(var gh=gk.sel.ranges.length-1;gh>=0;gh--){var gb=gk.sel.ranges[gh];var gd=gb.from(),f1=gb.to();if(gf-1){ac(f5,f3.line,"smart");break}}}else{if(f7.electricInput){if(f7.electricInput.test(e2(gk,f3.line).text.slice(0,f3.ch))){ac(f5,f3.line,"smart")}}}}}fu(f5);f5.curOp.updateInput=f4;f5.curOp.typing=true;if(f8.length>1000||f8.indexOf("\n")>-1){f6.value=f5.display.prevInput=""}else{f5.display.prevInput=f8}if(gg){al(f5)}f5.state.pasteIncoming=f5.state.cutIncoming=false;return true}function fc(f1,f5){var f2,f4,f7=f1.doc;if(f1.somethingSelected()){f1.display.prevInput="";var f3=f7.sel.primary();f2=c4&&(f3.to().line-f3.from().line>100||(f4=f1.getSelection()).length>1000);var f6=f2?"-":f4||f1.getSelection();f1.display.input.value=f6;if(f1.state.focused){dA(f1.display.input)}if(dz&&l>=9){f1.display.inputHasSelection=f6}}else{if(!f5){f1.display.prevInput=f1.display.input.value="";if(dz&&l>=9){f1.display.inputHasSelection=null}}}f1.display.inaccurateSelection=f2}function en(f1){if(f1.options.readOnly!="nocursor"&&(!d3||dC()!=f1.display.input)){f1.display.input.focus()}}function s(f1){if(!f1.state.focused){en(f1);cy(f1)}}function ai(f1){return f1.options.readOnly||f1.doc.cantEdit}function fD(f1){var f3=f1.display;bV(f3.scroller,"mousedown",cW(f1,eg));if(dz&&l<11){bV(f3.scroller,"dblclick",cW(f1,function(f7){if(aO(f1,f7)){return}var f8=cm(f1,f7);if(!f8||m(f1,f7)||a6(f1.display,f7)){return}cC(f7);var f6=f1.findWordAt(f8);fH(f1.doc,f6.anchor,f6.head)}))}else{bV(f3.scroller,"dblclick",function(f6){aO(f1,f6)||cC(f6)})}bV(f3.lineSpace,"selectstart",function(f6){if(!a6(f3,f6)){cC(f6)}});if(!fS){bV(f3.scroller,"contextmenu",function(f6){ay(f1,f6)})}bV(f3.scroller,"scroll",function(){if(f3.scroller.clientHeight){O(f1,f3.scroller.scrollTop);bC(f1,f3.scroller.scrollLeft,true);aC(f1,"scroll",f1)}});bV(f3.scrollbarV,"scroll",function(){if(f3.scroller.clientHeight){O(f1,f3.scrollbarV.scrollTop)}});bV(f3.scrollbarH,"scroll",function(){if(f3.scroller.clientHeight){bC(f1,f3.scrollbarH.scrollLeft)}});bV(f3.scroller,"mousewheel",function(f6){b(f1,f6)});bV(f3.scroller,"DOMMouseScroll",function(f6){b(f1,f6)});function f5(){if(f1.state.focused){setTimeout(ct(en,f1),0)}}bV(f3.scrollbarH,"mousedown",f5);bV(f3.scrollbarV,"mousedown",f5);bV(f3.wrapper,"scroll",function(){f3.wrapper.scrollTop=f3.wrapper.scrollLeft=0});bV(f3.input,"keyup",function(f6){bd.call(f1,f6)});bV(f3.input,"input",function(){if(dz&&l>=9&&f1.display.inputHasSelection){f1.display.inputHasSelection=null}C(f1)});bV(f3.input,"keydown",cW(f1,q));bV(f3.input,"keypress",cW(f1,cv));bV(f3.input,"focus",ct(cy,f1));bV(f3.input,"blur",ct(aR,f1));function f2(f6){if(!aO(f1,f6)){ee(f6)}}if(f1.options.dragDrop){bV(f3.scroller,"dragstart",function(f6){R(f1,f6)});bV(f3.scroller,"dragenter",f2);bV(f3.scroller,"dragover",f2);bV(f3.scroller,"drop",cW(f1,bf))}bV(f3.scroller,"paste",function(f6){if(a6(f3,f6)){return}f1.state.pasteIncoming=true;en(f1);C(f1)});bV(f3.input,"paste",function(){if(cU&&!f1.state.fakedLastChar&&!(new Date-f1.state.lastMiddleDown<200)){var f7=f3.input.selectionStart,f6=f3.input.selectionEnd;f3.input.value+="$";f3.input.selectionEnd=f6;f3.input.selectionStart=f7;f1.state.fakedLastChar=true}f1.state.pasteIncoming=true;C(f1)});function f4(ga){if(f1.somethingSelected()){bi=f1.getSelections();if(f3.inaccurateSelection){f3.prevInput="";f3.inaccurateSelection=false;f3.input.value=bi.join("\n");dA(f3.input)}}else{var gb=[],f7=[];for(var f8=0;f8f3-400&&cd(c7.pos,f7)==0){f4="triple"}else{if(de&&de.time>f3-400&&cd(de.pos,f7)==0){f4="double";c7={time:f3,pos:f7}}else{f4="single";de={time:f3,pos:f7}}}var f5=f2.doc.sel,f1=b5?f6.metaKey:f6.ctrlKey;if(f2.options.dragDrop&&ez&&!ai(f2)&&f4=="single"&&f5.contains(f7)>-1&&f5.somethingSelected()){aZ(f2,f6,f7,f1)}else{n(f2,f6,f7,f4,f1)}}function aZ(f3,f5,f6,f2){var f4=f3.display;var f1=cW(f3,function(f7){if(cU){f4.scroller.draggable=false}f3.state.draggingText=false;d0(document,"mouseup",f1);d0(f4.scroller,"drop",f1);if(Math.abs(f5.clientX-f7.clientX)+Math.abs(f5.clientY-f7.clientY)<10){cC(f7);if(!f2){fH(f3.doc,f6)}en(f3);if(dz&&l==9){setTimeout(function(){document.body.focus();en(f3)},20)}}});if(cU){f4.scroller.draggable=true}f3.state.draggingText=f1;if(f4.scroller.dragDrop){f4.scroller.dragDrop()}bV(document,"mouseup",f1);bV(f4.scroller,"drop",f1)}function n(f4,gi,f3,f1,f6){var gf=f4.display,gk=f4.doc;cC(gi);var f2,gj,f5=gk.sel;if(f6&&!gi.shiftKey){gj=gk.sel.contains(f3);if(gj>-1){f2=gk.sel.ranges[gj]}else{f2=new dM(f3,f3)}}else{f2=gk.sel.primary()}if(gi.altKey){f1="rect";if(!f6){f2=new dM(f3,f3)}f3=cm(f4,gi,true,true);gj=-1}else{if(f1=="double"){var gg=f4.findWordAt(f3);if(f4.display.shift||gk.extend){f2=fj(gk,f2,gg.anchor,gg.head)}else{f2=gg}}else{if(f1=="triple"){var f9=new dM(X(f3.line,0),fx(gk,X(f3.line+1,0)));if(f4.display.shift||gk.extend){f2=fj(gk,f2,f9.anchor,f9.head)}else{f2=f9}}else{f2=fj(gk,f2,f3)}}}if(!f6){gj=0;bS(gk,new fL([f2],0),N);f5=gk.sel}else{if(gj>-1){e(gk,gj,f2,N)}else{gj=gk.sel.ranges.length;bS(gk,cu(gk.sel.ranges.concat([f2]),gj),{scroll:false,origin:"*mouse"})}}var ge=f3;function gd(gv){if(cd(ge,gv)==0){return}ge=gv;if(f1=="rect"){var gm=[],gs=f4.options.tabSize;var gl=bR(e2(gk,f3.line).text,f3.ch,gs);var gy=bR(e2(gk,gv.line).text,gv.ch,gs);var gn=Math.min(gl,gy),gw=Math.max(gl,gy);for(var gz=Math.min(f3.line,gv.line),gp=Math.min(f4.lastLine(),Math.max(f3.line,gv.line));gz<=gp;gz++){var gx=e2(gk,gz).text,go=ed(gx,gn,gs);if(gn==gw){gm.push(new dM(X(gz,go),X(gz,go)))}else{if(gx.length>go){gm.push(new dM(X(gz,go),X(gz,ed(gx,gw,gs))))}}}if(!gm.length){gm.push(new dM(f3,f3))}bS(gk,cu(f5.ranges.slice(0,gj).concat(gm),gj),{origin:"*mouse",scroll:false});f4.scrollIntoView(gv)}else{var gt=f2;var gq=gt.anchor,gu=gv;if(f1!="single"){if(f1=="double"){var gr=f4.findWordAt(gv)}else{var gr=new dM(X(gv.line,0),fx(gk,X(gv.line+1,0)))}if(cd(gr.anchor,gq)>0){gu=gr.head;gq=aq(gt.from(),gr.anchor)}else{gu=gr.anchor;gq=bv(gt.to(),gr.head)}}var gm=f5.ranges.slice(0);gm[gj]=new dM(fx(gk,gq),gu);bS(gk,cu(gm,gj),N)}}var gb=gf.wrapper.getBoundingClientRect();var f7=0;function gh(gn){var gl=++f7;var gp=cm(f4,gn,true,f1=="rect");if(!gp){return}if(cd(gp,ge)!=0){s(f4);gd(gp);var go=b4(gf,gk);if(gp.line>=go.to||gp.linegb.bottom?20:0;if(gm){setTimeout(cW(f4,function(){if(f7!=gl){return}gf.scroller.scrollTop+=gm;gh(gn)}),50)}}}function ga(gl){f7=Infinity;cC(gl);en(f4);d0(document,"mousemove",gc);d0(document,"mouseup",f8);gk.history.lastSelOrigin=null}var gc=cW(f4,function(gl){if(!fB(gl)){ga(gl)}else{gh(gl)}});var f8=cW(f4,ga);bV(document,"mousemove",gc);bV(document,"mouseup",f8)}function fZ(gc,f8,ga,gb,f4){try{var f2=f8.clientX,f1=f8.clientY}catch(f8){return false}if(f2>=Math.floor(gc.display.gutters.getBoundingClientRect().right)){return false}if(gb){cC(f8)}var f9=gc.display;var f7=f9.lineDiv.getBoundingClientRect();if(f1>f7.bottom||!e5(gc,ga)){return bJ(f8)}f1-=f7.top-f9.viewOffset;for(var f5=0;f5=f2){var gd=bE(gc.doc,f1);var f3=gc.options.gutters[f5];f4(gc,ga,gc,gd,f3,f8);return bJ(f8)}}}function m(f1,f2){return fZ(f1,f2,"gutterClick",true,ad)}var af=0;function bf(f7){var f9=this;if(aO(f9,f7)||a6(f9.display,f7)){return}cC(f7);if(dz){af=+new Date}var f8=cm(f9,f7,true),f1=f7.dataTransfer.files;if(!f8||ai(f9)){return}if(f1&&f1.length&&window.FileReader&&window.File){var f3=f1.length,ga=Array(f3),f2=0;var f5=function(gd,gc){var gb=new FileReader;gb.onload=cW(f9,function(){ga[gc]=gb.result;if(++f2==f3){f8=fx(f9.doc,f8);var ge={from:f8,to:f8,text:aW(ga.join("\n")),origin:"paste"};bb(f9.doc,ge);eU(f9.doc,eG(f8,cR(ge)))}});gb.readAsText(gd)};for(var f6=0;f6-1){f9.state.draggingText(f7);setTimeout(ct(en,f9),20);return}try{var ga=f7.dataTransfer.getData("Text");if(ga){if(f9.state.draggingText&&!(b5?f7.metaKey:f7.ctrlKey)){var f4=f9.listSelections()}ec(f9.doc,eG(f8,f8));if(f4){for(var f6=0;f6f8.clientWidth||gb&&f8.scrollHeight>f8.clientHeight)){return}if(gb&&b5&&cU){outer:for(var ga=f3.target,f7=f5.view;ga!=f8;ga=ga.parentNode){for(var f2=0;f2=9){f1.display.inputHasSelection=null}C(f1)}function cy(f1){if(f1.options.readOnly=="nocursor"){return}if(!f1.state.focused){aC(f1,"focus",f1);f1.state.focused=true;fo(f1.display.wrapper,"CodeMirror-focused");if(!f1.curOp&&f1.display.selForContextMenu!=f1.doc.sel){fc(f1);if(cU){setTimeout(ct(fc,f1,true),0)}}}bk(f1);p(f1)}function aR(f1){if(f1.state.focused){aC(f1,"blur",f1);f1.state.focused=false;f(f1.display.wrapper,"CodeMirror-focused")}clearInterval(f1.display.blinker);setTimeout(function(){if(!f1.state.focused){f1.display.shift=false}},150)}function ay(ga,f5){if(aO(ga,f5,"contextmenu")){return}var f7=ga.display;if(a6(f7,f5)||da(ga,f5)){return}var f9=cm(ga,f5),f1=f7.scroller.scrollTop;if(!f9||dQ){return}var f4=ga.options.resetSelectionOnContextMenu;if(f4&&ga.doc.sel.contains(f9)==-1){cW(ga,bS)(ga.doc,eG(f9),Z)}var f6=f7.input.style.cssText;f7.inputDiv.style.position="absolute";f7.input.style.cssText="position: fixed; width: 30px; height: 30px; top: "+(f5.clientY-5)+"px; left: "+(f5.clientX-5)+"px; z-index: 1000; background: "+(dz?"rgba(255, 255, 255, .05)":"transparent")+"; outline: none; border-width: 0; outline: none; overflow: hidden; opacity: .05; filter: alpha(opacity=5);";if(cU){var gb=window.scrollY}en(ga);if(cU){window.scrollTo(null,gb)}fc(ga);if(!ga.somethingSelected()){f7.input.value=f7.prevInput=" "}f7.selForContextMenu=ga.doc.sel;clearTimeout(f7.detectingSelectAll);function f3(){if(f7.input.selectionStart!=null){var gc=ga.somethingSelected();var gd=f7.input.value="\u200b"+(gc?f7.input.value:"");f7.prevInput=gc?"":"\u200b";f7.input.selectionStart=1;f7.input.selectionEnd=gd.length;f7.selForContextMenu=ga.doc.sel}}function f8(){f7.inputDiv.style.position="relative";f7.input.style.cssText=f6;if(dz&&l<9){f7.scrollbarV.scrollTop=f7.scroller.scrollTop=f1}bk(ga);if(f7.input.selectionStart!=null){if(!dz||(dz&&l<9)){f3()}var gc=0,gd=function(){if(f7.selForContextMenu==ga.doc.sel&&f7.input.selectionStart==0){cW(ga,er.selectAll)(ga)}else{if(gc++<10){f7.detectingSelectAll=setTimeout(gd,500)}else{fc(ga)}}};f7.detectingSelectAll=setTimeout(gd,200)}}if(dz&&l>=9){f3()}if(fS){ee(f5);var f2=function(){d0(window,"mouseup",f2);setTimeout(f8,20)};bV(window,"mouseup",f2)}else{setTimeout(f8,50)}}function da(f1,f2){if(!e5(f1,"gutterContextMenu")){return false}return fZ(f1,f2,"gutterContextMenu",false,aC)}var cR=J.changeEnd=function(f1){if(!f1.text){return f1.to}return X(f1.from.line+f1.text.length-1,fv(f1.text).length+(f1.text.length==1?f1.from.ch:0))};function bX(f4,f3){if(cd(f4,f3.from)<0){return f4}if(cd(f4,f3.to)<=0){return cR(f3)}var f1=f4.line+f3.text.length-(f3.to.line-f3.from.line)-1,f2=f4.ch;if(f4.line==f3.to.line){f2+=cR(f3).ch-f3.to.ch}return X(f1,f2)}function e7(f4,f5){var f2=[];for(var f3=0;f3=0;--f1){L(f4,{from:f2[f1].from,to:f2[f1].to,text:f1?[""]:f5.text})}}else{L(f4,f5)}}function L(f3,f4){if(f4.text.length==1&&f4.text[0]==""&&cd(f4.from,f4.to)==0){return}var f2=e7(f3,f4);fA(f3,f4,f2,f3.cm?f3.cm.curOp.id:NaN);d1(f3,f4,f2,d7(f3,f4));var f1=[];dV(f3,function(f6,f5){if(!f5&&db(f1,f6.history)==-1){du(f6.history,f4);f1.push(f6.history)}d1(f6,f4,null,d7(f6,f4))})}function b6(gc,ga,ge){if(gc.cm&&gc.cm.state.suppressEdits){return}var f9=gc.history,f3,f5=gc.sel;var f1=ga=="undo"?f9.done:f9.undone,gd=ga=="undo"?f9.undone:f9.done;for(var f6=0;f6=0;--f6){var gb=f3.changes[f6];gb.origin=ga;if(f4&&!dF(gc,gb,false)){f1.length=0;return}f8.push(dk(gc,gb));var f2=f6?e7(gc,gb):fv(f1);d1(gc,gb,f2,dX(gc,gb));if(!f6&&gc.cm){gc.cm.scrollIntoView({from:gb.from,to:cR(gb)})}var f7=[];dV(gc,function(gg,gf){if(!gf&&db(f7,gg.history)==-1){du(gg.history,gb);f7.push(gg.history)}d1(gg,gb,null,dX(gg,gb))})}}function fa(f2,f4){if(f4==0){return}f2.first+=f4;f2.sel=new fL(bQ(f2.sel.ranges,function(f5){return new dM(X(f5.anchor.line+f4,f5.anchor.ch),X(f5.head.line+f4,f5.head.ch))}),f2.sel.primIndex);if(f2.cm){ag(f2.cm,f2.first,f2.first-f4,f4);for(var f3=f2.cm.display,f1=f3.viewFrom;f1f5.lastLine()){return}if(f6.from.linef3){f6={from:f6.from,to:X(f3,e2(f5,f3).text.length),text:[f6.text[0]],origin:f6.origin}}f6.removed=fM(f5,f6.from,f6.to);if(!f4){f4=e7(f5,f6)}if(f5.cm){aH(f5.cm,f6,f2)}else{fm(f5,f6,f2)}ec(f5,f4,Z)}function aH(gc,f8,f6){var gb=gc.doc,f7=gc.display,f9=f8.from,ga=f8.to;var f1=false,f5=f9.line;if(!gc.options.lineWrapping){f5=bL(z(e2(gb,f9.line)));gb.iter(f5,ga.line+1,function(ge){if(ge==f7.maxLine){f1=true;return true}})}if(gb.sel.contains(f8.from,f8.to)>-1){W(gc)}fm(gb,f8,f6,a9(gc));if(!gc.options.lineWrapping){gb.iter(f5,f9.line+f8.text.length,function(gf){var ge=d9(gf);if(ge>f7.maxLineLength){f7.maxLine=gf;f7.maxLineLength=ge;f7.maxLineChanged=true;f1=false}});if(f1){gc.curOp.updateMaxLine=true}}gb.frontier=Math.min(gb.frontier,f9.line);d2(gc,400);var gd=f8.text.length-(ga.line-f9.line)-1;if(f9.line==ga.line&&f8.text.length==1&&!dG(gc.doc,f8)){S(gc,f9.line,"text")}else{ag(gc,f9.line,ga.line+1,gd)}var f3=e5(gc,"changes"),f4=e5(gc,"change");if(f4||f3){var f2={from:f9,to:ga,text:f8.text,removed:f8.removed,origin:f8.origin};if(f4){ad(gc,"change",gc,f2)}if(f3){(gc.curOp.changeObjs||(gc.curOp.changeObjs=[])).push(f2)}}gc.display.selForContextMenu=null}function aX(f4,f3,f6,f5,f1){if(!f5){f5=f6}if(cd(f5,f6)<0){var f2=f5;f5=f6;f6=f2}if(typeof f3=="string"){f3=aW(f3)}bb(f4,{from:f6,to:f5,text:f3,origin:f1})}function dU(f2,f5){var f6=f2.display,f3=f6.sizer.getBoundingClientRect(),f1=null;if(f5.top+f3.top<0){f1=true}else{if(f5.bottom+f3.top>(window.innerHeight||document.documentElement.clientHeight)){f1=false}}if(f1!=null&&!fi){var f4=fK("div","\u200b",null,"position: absolute; top: "+(f5.top-f6.viewOffset-eV(f2.display))+"px; height: "+(f5.bottom-f5.top+bg)+"px; left: "+f5.left+"px; width: 2px;");f2.display.lineSpace.appendChild(f4);f4.scrollIntoView(f1);f2.display.lineSpace.removeChild(f4)}}function F(ga,f8,f5,f4){if(f4==null){f4=0}for(;;){var f6=false,f9=dI(ga,f8);var f1=!f5||f5==f8?f9:dI(ga,f5);var f3=I(ga,Math.min(f9.left,f1.left),Math.min(f9.top,f1.top)-f4,Math.max(f9.left,f1.left),Math.max(f9.bottom,f1.bottom)+f4);var f7=ga.doc.scrollTop,f2=ga.doc.scrollLeft;if(f3.scrollTop!=null){O(ga,f3.scrollTop);if(Math.abs(ga.doc.scrollTop-f7)>1){f6=true}}if(f3.scrollLeft!=null){bC(ga,f3.scrollLeft);if(Math.abs(ga.doc.scrollLeft-f2)>1){f6=true}}if(!f6){return f9}}}function G(f1,f3,f5,f2,f4){var f6=I(f1,f3,f5,f2,f4);if(f6.scrollTop!=null){O(f1,f6.scrollTop)}if(f6.scrollLeft!=null){bC(f1,f6.scrollLeft)}}function I(gd,f4,gc,f2,gb){var f9=gd.display,f7=aT(gd.display);if(gc<0){gc=0}var f5=gd.curOp&&gd.curOp.scrollTop!=null?gd.curOp.scrollTop:f9.scroller.scrollTop;var gf=f9.scroller.clientHeight-bg,gh={};if(gb-gc>gf){gb=gc+gf}var f3=gd.doc.height+bG(f9);var f1=gcf3-f7;if(gcf5+gf){var ga=Math.min(gc,(f8?f3:gb)-gf);if(ga!=f5){gh.scrollTop=ga}}}var gg=gd.curOp&&gd.curOp.scrollLeft!=null?gd.curOp.scrollLeft:f9.scroller.scrollLeft;var ge=f9.scroller.clientWidth-bg-f9.gutters.offsetWidth;var f6=f2-f4>ge;if(f6){f2=gc+gf}if(f4<10){gh.scrollLeft=0}else{if(f4ge+gg-3){gh.scrollLeft=f2+(f6?0:10)-ge}}}return gh}function cH(f1,f3,f2){if(f3!=null||f2!=null){fq(f1)}if(f3!=null){f1.curOp.scrollLeft=(f1.curOp.scrollLeft==null?f1.doc.scrollLeft:f1.curOp.scrollLeft)+f3}if(f2!=null){f1.curOp.scrollTop=(f1.curOp.scrollTop==null?f1.doc.scrollTop:f1.curOp.scrollTop)+f2}}function fu(f1){fq(f1);var f2=f1.getCursor(),f4=f2,f3=f2;if(!f1.options.lineWrapping){f4=f2.ch?X(f2.line,f2.ch-1):f2;f3=X(f2.line,f2.ch+1)}f1.curOp.scrollToPos={from:f4,to:f3,margin:f1.options.cursorScrollMargin,isCursor:true}}function fq(f1){var f3=f1.curOp.scrollToPos;if(f3){f1.curOp.scrollToPos=null;var f5=dx(f1,f3.from),f4=dx(f1,f3.to);var f2=I(f1,Math.min(f5.left,f4.left),Math.min(f5.top,f4.top)-f3.margin,Math.max(f5.right,f4.right),Math.max(f5.bottom,f4.bottom)+f3.margin);f1.scrollTo(f2.scrollLeft,f2.scrollTop)}}function ac(ge,f4,gd,f3){var gc=ge.doc,f2;if(gd==null){gd="add"}if(gd=="smart"){if(!gc.mode.indent){gd="prev"}else{f2=dr(ge,f4)}}var f8=ge.options.tabSize;var gf=e2(gc,f4),f7=bR(gf.text,null,f8);if(gf.stateAfter){gf.stateAfter=null}var f1=gf.text.match(/^\s*/)[0],ga;if(!f3&&!/\S/.test(gf.text)){ga=0;gd="not"}else{if(gd=="smart"){ga=gc.mode.indent(f2,gf.text.slice(f1.length),gf.text);if(ga==b8||ga>150){if(!f3){return}gd="prev"}}}if(gd=="prev"){if(f4>gc.first){ga=bR(e2(gc,f4-1).text,null,f8)}else{ga=0}}else{if(gd=="add"){ga=f7+ge.options.indentUnit}else{if(gd=="subtract"){ga=f7-ge.options.indentUnit}else{if(typeof gd=="number"){ga=f7+gd}}}}ga=Math.max(0,ga);var gb="",f9=0;if(ge.options.indentWithTabs){for(var f5=Math.floor(ga/f8);f5;--f5){f9+=f8;gb+="\t"}}if(f9=0;f8--){aX(f1.doc,"",f5[f8].from,f5[f8].to,"+delete")}fu(f1)})}function bu(gj,f5,gd,gc,f7){var ga=f5.line,gb=f5.ch,gi=gd;var f2=e2(gj,ga);var gg=true;function gh(){var gk=ga+gd;if(gk=gj.first+gj.size){return(gg=false)}ga=gk;return f2=e2(gj,gk)}function gf(gl){var gk=(f7?v:ah)(f2,gb,gd,true);if(gk==null){if(!gl&&gh()){if(f7){gb=(gd<0?cO:cB)(f2)}else{gb=gd<0?f2.text.length:0}}else{return(gg=false)}}else{gb=gk}return true}if(gc=="char"){gf()}else{if(gc=="column"){gf(true)}else{if(gc=="word"||gc=="group"){var ge=null,f8=gc=="group";var f1=gj.cm&&gj.cm.getHelper(f5,"wordChars");for(var f6=true;;f6=false){if(gd<0&&!gf(!f6)){break}var f3=f2.text.charAt(gb)||"\n";var f4=cx(f3,f1)?"w":f8&&f3=="\n"?"n":!f8||/\s/.test(f3)?null:"p";if(f8&&!f6&&!f4){f4="s"}if(ge&&ge!=f4){if(gd<0){gd=1;gf()}break}if(f4){ge=f4}if(gd>0&&!gf(!f6)){break}}}}}var f9=bT(gj,X(ga,gb),gi,true);if(!gg){f9.hitSide=true}return f9}function bo(f9,f4,f1,f8){var f7=f9.doc,f6=f4.left,f5;if(f8=="page"){var f3=Math.min(f9.display.wrapper.clientHeight,window.innerHeight||document.documentElement.clientHeight);f5=f4.top+f1*(f3-(f1<0?1.5:0.5)*aT(f9.display))}else{if(f8=="line"){f5=f1>0?f4.bottom+3:f4.top-3}}for(;;){var f2=fC(f9,f6,f5);if(!f2.outside){break}if(f1<0?f5<=0:f5>=f7.height){f2.hitSide=true;break}f5+=f1*5}return f2}J.prototype={constructor:J,focus:function(){window.focus();en(this);C(this)},setOption:function(f3,f4){var f2=this.options,f1=f2[f3];if(f2[f3]==f4&&f3!="mode"){return}f2[f3]=f4;if(ba.hasOwnProperty(f3)){cW(this,ba[f3])(this,f4,f1)}},getOption:function(f1){return this.options[f1]},getDoc:function(){return this.doc},addKeyMap:function(f2,f1){this.state.keyMaps[f1?"push":"unshift"](f2)},removeKeyMap:function(f2){var f3=this.state.keyMaps;for(var f1=0;f10){e(this.doc,f6,new dM(f8,f3[f6].to()),Z)}}else{if(f7.head.line>f4){ac(this,f7.head.line,ga,true);f4=f7.head.line;if(f6==this.doc.sel.primIndex){fu(this)}}}}}),getTokenAt:function(f8,f2){var f5=this.doc;f8=fx(f5,f8);var f4=dr(this,f8.line,f2),f7=this.doc.mode;var f1=e2(f5,f8.line);var f6=new eH(f1.text,this.options.tabSize);while(f6.pos>1;if((f1?f4[f1*2-1]:0)>=f3){f7=f1}else{if(f4[f1*2+1]f4){f2=f4;f1=true}}var f3=e2(this.doc,f2);return eE(this,f3,{top:0,left:0},f5||"page").top+(f1?this.doc.height-bK(f3):0)},defaultTextHeight:function(){return aT(this.display)},defaultCharWidth:function(){return dt(this.display)},setGutterMarker:c2(function(f1,f2,f3){return em(this.doc,f1,"gutter",function(f4){var f5=f4.gutterMarkers||(f4.gutterMarkers={});f5[f2]=f3;if(!f3&&eI(f5)){f4.gutterMarkers=null}return true})}),clearGutter:c2(function(f3){var f1=this,f4=f1.doc,f2=f4.first;f4.iter(function(f5){if(f5.gutterMarkers&&f5.gutterMarkers[f3]){f5.gutterMarkers[f3]=null;S(f1,f2,"gutter");if(eI(f5.gutterMarkers)){f5.gutterMarkers=null}}++f2})}),addLineWidget:c2(function(f3,f2,f1){return bF(this,f3,f2,f1)}),removeLineWidget:function(f1){f1.clear()},lineInfo:function(f1){if(typeof f1=="number"){if(!b7(this.doc,f1)){return null}var f2=f1;f1=e2(this.doc,f1);if(!f1){return null}}else{var f2=bL(f1);if(f2==null){return null}}return{line:f2,handle:f1,text:f1.text,gutterMarkers:f1.gutterMarkers,textClass:f1.textClass,bgClass:f1.bgClass,wrapClass:f1.wrapClass,widgets:f1.widgets}},getViewport:function(){return{from:this.display.viewFrom,to:this.display.viewTo}},addWidget:function(f6,f3,f8,f4,ga){var f5=this.display;f6=dI(this,fx(this.doc,f6));var f7=f6.bottom,f2=f6.left;f3.style.position="absolute";f5.sizer.appendChild(f3);if(f4=="over"){f7=f6.top}else{if(f4=="above"||f4=="near"){var f1=Math.max(f5.wrapper.clientHeight,this.doc.height),f9=Math.max(f5.sizer.clientWidth,f5.lineSpace.clientWidth);if((f4=="above"||f6.bottom+f3.offsetHeight>f1)&&f6.top>f3.offsetHeight){f7=f6.top-f3.offsetHeight}else{if(f6.bottom+f3.offsetHeight<=f1){f7=f6.bottom}}if(f2+f3.offsetWidth>f9){f2=f9-f3.offsetWidth}}}f3.style.top=f7+"px";f3.style.left=f3.style.right="";if(ga=="right"){f2=f5.sizer.clientWidth-f3.offsetWidth;f3.style.right="0px"}else{if(ga=="left"){f2=0}else{if(ga=="middle"){f2=(f5.sizer.clientWidth-f3.offsetWidth)/2}}f3.style.left=f2+"px"}if(f8){G(this,f2,f7,f2+f3.offsetWidth,f7+f3.offsetHeight)}},triggerOnKeyDown:c2(q),triggerOnKeyPress:c2(cv),triggerOnKeyUp:bd,execCommand:function(f1){if(er.hasOwnProperty(f1)){return er[f1](this)}},findPosH:function(f7,f4,f5,f2){var f1=1;if(f4<0){f1=-1;f4=-f4}for(var f3=0,f6=fx(this.doc,f7);f30&&f1(f4.charAt(f7-1))){--f7}while(f30.5){Y(this)}aC(this,"refresh",this)}),swapDoc:c2(function(f2){var f1=this.doc;f1.cm=null;dY(this,f2);aj(this);fc(this);this.scrollTo(f2.scrollLeft,f2.scrollTop);this.curOp.forceScroll=true;ad(this,"swapDoc",this,f1);return f1}),getInputField:function(){return this.display.input},getWrapperElement:function(){return this.display.wrapper},getScrollerElement:function(){return this.display.scroller},getGutterElement:function(){return this.display.gutters}};bw(J);var eR=J.defaults={};var ba=J.optionHandlers={};function t(f1,f4,f3,f2){J.defaults[f1]=f4;if(f3){ba[f1]=f2?function(f5,f7,f6){if(f6!=ca){f3(f5,f7,f6)}}:f3}}var ca=J.Init={toString:function(){return"CodeMirror.Init"}};t("value","",function(f1,f2){f1.setValue(f2)},true);t("mode",null,function(f1,f2){f1.doc.modeOption=f2;bp(f1)},true);t("indentUnit",2,bp,true);t("indentWithTabs",false);t("smartIndent",true);t("tabSize",4,function(f1){d8(f1);aj(f1);ag(f1)},true);t("specialChars",/[\t\u0000-\u0019\u00ad\u200b-\u200f\u2028\u2029\ufeff]/g,function(f1,f2){f1.options.specialChars=new RegExp(f2.source+(f2.test("\t")?"":"|\t"),"g");f1.refresh()},true);t("specialCharPlaceholder",eZ,function(f1){f1.refresh()},true);t("electricChars",true);t("rtlMoveVisually",!aM);t("wholeLineUpdateBefore",true);t("theme","default",function(f1){cK(f1);dl(f1)},true);t("keyMap","default",fY);t("extraKeys",null);t("lineWrapping",false,eu,true);t("gutters",[],function(f1){cc(f1.options);dl(f1)},true);t("fixedGutter",true,function(f1,f2){f1.display.gutters.style.left=f2?dL(f1.display)+"px":"0";f1.refresh()},true);t("coverGutterNextToScrollbar",false,eM,true);t("lineNumbers",false,function(f1){cc(f1.options);dl(f1)},true);t("firstLineNumber",1,dl,true);t("lineNumberFormatter",function(f1){return f1},dl,true);t("showCursorWhenSelecting",false,bA,true);t("resetSelectionOnContextMenu",true);t("readOnly",false,function(f1,f2){if(f2=="nocursor"){aR(f1);f1.display.input.blur();f1.display.disabled=true}else{f1.display.disabled=false;if(!f2){fc(f1)}}});t("disableInput",false,function(f1,f2){if(!f2){fc(f1)}},true);t("dragDrop",true);t("cursorBlinkRate",530);t("cursorScrollMargin",0);t("cursorHeight",1,bA,true);t("singleCursorHeightPerLine",true,bA,true);t("workTime",100);t("workDelay",100);t("flattenSpans",true,d8,true);t("addModeClass",false,d8,true);t("pollInterval",100);t("undoDepth",200,function(f1,f2){f1.doc.history.undoDepth=f2});t("historyEventDelay",1250);t("viewportMargin",10,function(f1){f1.refresh()},true);t("maxHighlightLength",10000,d8,true);t("moveInputWithCursor",true,function(f1,f2){if(!f2){f1.display.inputDiv.style.top=f1.display.inputDiv.style.left=0}});t("tabindex",null,function(f1,f2){f1.display.input.tabIndex=f2||""});t("autofocus",null);var di=J.modes={},aP=J.mimeModes={};J.defineMode=function(f1,f3){if(!J.defaults.mode&&f1!="null"){J.defaults.mode=f1}if(arguments.length>2){f3.dependencies=[];for(var f2=2;f20){f7=new X(f7.line,f7.ch+1);f1.replaceRange(f2.charAt(f7.ch-1)+f2.charAt(f7.ch-2),X(f7.line,f7.ch-2),f7,"+transpose")}else{if(f7.line>f1.doc.first){var f6=e2(f1.doc,f7.line-1).text;if(f6){f1.replaceRange(f2.charAt(0)+"\n"+f6.charAt(f6.length-1),X(f7.line-1,f6.length-1),X(f7.line,1),"+transpose")}}}}f3.push(new dM(f7,f7))}f1.setSelections(f3)})},newlineAndIndent:function(f1){cI(f1,function(){var f2=f1.listSelections().length;for(var f4=0;f4=this.string.length},sol:function(){return this.pos==this.lineStart},peek:function(){return this.string.charAt(this.pos)||undefined},next:function(){if(this.posf2},eatSpace:function(){var f1=this.pos;while(/[\s\u00a0]/.test(this.string.charAt(this.pos))){++this.pos}return this.pos>f1},skipToEnd:function(){this.pos=this.string.length},skipTo:function(f1){var f2=this.string.indexOf(f1,this.pos);if(f2>-1){this.pos=f2;return true}},backUp:function(f1){this.pos-=f1},column:function(){if(this.lastColumnPos0){return null}if(f3&&f2!==false){this.pos+=f3[0].length}return f3}},current:function(){return this.string.slice(this.start,this.pos)},hideFirstChars:function(f2,f1){this.lineStart+=f2;try{return f1()}finally{this.lineStart-=f2}}};var Q=J.TextMarker=function(f2,f1){this.lines=[];this.type=f1;this.doc=f2};bw(Q);Q.prototype.clear=function(){if(this.explicitlyCleared){return}var f8=this.doc.cm,f2=f8&&!f8.curOp;if(f2){cE(f8)}if(e5(this,"clear")){var f9=this.find();if(f9){ad(this,"clear",f9.from,f9.to)}}var f3=null,f6=null;for(var f4=0;f4f8.display.maxLineLength){f8.display.maxLine=f1;f8.display.maxLineLength=f5;f8.display.maxLineChanged=true}}}if(f3!=null&&f8&&this.collapsed){ag(f8,f3,f6+1)}this.lines.length=0;this.explicitlyCleared=true;if(this.atomic&&this.doc.cantEdit){this.doc.cantEdit=false;if(f8){el(f8.doc)}}if(f8){ad(f8,"markerCleared",f8,this)}if(f2){al(f8)}if(this.parent){this.parent.clear()}};Q.prototype.find=function(f4,f2){if(f4==null&&this.type=="bookmark"){f4=1}var f7,f6;for(var f3=0;f30||ga==0&&f4.clearWhenEmpty!==false){return f4}if(f4.replacedWith){f4.collapsed=true;f4.widgetNode=fK("span",[f4.replacedWith],"CodeMirror-widget");if(!gb.handleMouseEvents){f4.widgetNode.ignoreEvents=true}if(gb.insertLeft){f4.widgetNode.insertLeft=true}}if(f4.collapsed){if(A(f9,f7.line,f7,f8,f4)||f7.line!=f8.line&&A(f9,f8.line,f7,f8,f4)){throw new Error("Inserting collapsed marker partially overlapping an existing one")}a3=true}if(f4.addToHistory){fA(f9,{from:f7,to:f8,origin:"markText"},f9.sel,NaN)}var f2=f7.line,f6=f9.cm,f1;f9.iter(f2,f8.line+1,function(gc){if(f6&&f4.collapsed&&!f6.options.lineWrapping&&z(gc)==f6.display.maxLine){f1=true}if(f4.collapsed&&f2!=f7.line){fO(gc,0)}cb(gc,new d5(f4,f2==f7.line?f7.ch:null,f2==f8.line?f8.ch:null));++f2});if(f4.collapsed){f9.iter(f7.line,f8.line+1,function(gc){if(fk(f9,gc)){fO(gc,0)}})}if(f4.clearOnEnter){bV(f4,"beforeCursorEnter",function(){f4.clear()})}if(f4.readOnly){fV=true;if(f9.history.done.length||f9.history.undone.length){f9.clearHistory()}}if(f4.collapsed){f4.id=++a1;f4.atomic=true}if(f6){if(f1){f6.curOp.updateMaxLine=true}if(f4.collapsed){ag(f6,f7.line,f8.line+1)}else{if(f4.className||f4.title||f4.startStyle||f4.endStyle){for(var f3=f7.line;f3<=f8.line;f3++){S(f6,f3,"text")}}}if(f4.atomic){el(f6.doc)}ad(f6,"markerAdded",f6,f4)}return f4}var y=J.SharedTextMarker=function(f3,f2){this.markers=f3;this.primary=f2;for(var f1=0;f1=f3:f9.to>f3);(f8||(f8=[])).push(new d5(f6,f9.from,f4?null:f9.to))}}}return f8}function aA(f2,f4,f7){if(f2){for(var f5=0,f8;f5=f4:f9.to>f4);if(f3||f9.from==f4&&f6.type=="bookmark"&&(!f7||f9.marker.insertLeft)){var f1=f9.from==null||(f6.inclusiveLeft?f9.from<=f4:f9.from0&&f7){for(var f4=0;f40){continue}var ga=[f4,1],f1=cd(f2.from,f3.from),f9=cd(f2.to,f3.to);if(f1<0||!f8.inclusiveLeft&&!f1){ga.push({from:f2.from,to:f3.from})}if(f9>0||!f8.inclusiveRight&&!f9){ga.push({from:f3.to,to:f2.to})}f6.splice.apply(f6,ga);f4+=ga.length-1}}return f6}function fR(f1){var f3=f1.markedSpans;if(!f3){return}for(var f2=0;f2=0&&f6<=0||ga<=0&&f6>=0){continue}if(ga<=0&&(cd(gb.to,f7)>0||(f2.marker.inclusiveRight&&f5.inclusiveLeft))||ga>=0&&(cd(gb.from,f8)<0||(f2.marker.inclusiveLeft&&f5.inclusiveRight))){return true}}}}function z(f2){var f1;while(f1=eC(f2)){f2=f1.find(-1,true).line}return f2}function h(f3){var f1,f2;while(f1=ei(f3)){f3=f1.find(1,true).line;(f2||(f2=[])).push(f3)}return f2}function aS(f4,f2){var f1=e2(f4,f2),f3=z(f1);if(f1==f3){return f2}return bL(f3)}function dR(f4,f3){if(f3>f4.lastLine()){return f3}var f2=e2(f4,f3),f1;if(!fk(f4,f2)){return f3}while(f1=ei(f2)){f2=f1.find(1,true).line}return bL(f2)+1}function fk(f5,f2){var f1=a3&&f2.markedSpans;if(f1){for(var f4,f3=0;f3f4.start){return f2}}throw new Error("Mode "+f5.name+" failed to advance stream.")}function x(gb,gd,f6,f2,f7,f4,f5){var f3=f6.flattenSpans;if(f3==null){f3=gb.options.flattenSpans}var f9=0,f8=null;var gc=new eH(gd,gb.options.tabSize),f1;if(gd==""){dc(fe(f6,f2),f4)}while(!gc.eol()){if(gc.pos>gb.options.maxHighlightLength){f3=false;if(f5){dm(gb,gd,f2,gc.pos)}gc.pos=gd.length;f1=null}else{f1=dc(ep(f6,gc,f2),f4)}if(gb.options.addModeClass){var ge=J.innerMode(f6,f2).mode.name;if(ge){f1="m-"+(f1?ge+" "+f1:ge)}}if(!f3||f8!=f1){if(f9gb){f9.splice(f7,1,gb,f9[f7+1],gc)}f7+=2;f3=Math.min(gb,gc)}if(!gd){return}if(f6.opaque){f9.splice(gf,f7-gf,gb,"cm-overlay "+gd);f7=gf+2}else{for(;gff4&&f5.from<=f4){break}}if(f5.to>=f6){return f2(f9,gb,f3,f7,gc,ga)}f2(f9,gb.slice(0,f5.to-f4),f3,f7,null,ga);f7=null;gb=gb.slice(f5.to-f4);f4=f5.to}}}function ab(f2,f4,f1,f3){var f5=!f3&&f1.widgetNode;if(f5){f2.map.push(f2.pos,f2.pos+f4,f5);f2.content.appendChild(f5)}f2.pos+=f4}function bm(ga,gg,f9){var f6=ga.markedSpans,f8=ga.text,ge=0;if(!f6){for(var gj=1;gjf5)){if(gi.to!=null&&gn>gi.to){gn=gi.to;gm=""}if(gf.className){f1+=" "+gf.className}if(gf.startStyle&&gi.from==f5){gd+=" "+gf.startStyle}if(gf.endStyle&&gi.to==gn){gm+=" "+gf.endStyle}if(gf.title&&!go){go=gf.title}if(gf.collapsed&&(!f3||dE(f3.marker,gf)<0)){f3=gi}}else{if(gi.from>f5&&gn>gi.from){gn=gi.from}}if(gf.type=="bookmark"&&gi.from==f5&&gf.widgetNode){f7.push(gf)}}if(f3&&(f3.from||0)==f5){ab(gg,(f3.to==null?gk+1:f3.to)-f5,f3.marker,f3.from==null);if(f3.to==null){return}}if(!f3&&f7.length){for(var gh=0;gh=gk){break}var gb=Math.min(gk,gn);while(true){if(gc){var f2=f5+gc.length;if(!f3){var f4=f2>gb?gc.slice(0,gb-f5):gc;gg.addToken(gg,f4,gl?gl+f1:f1,gd,f5+f4.length==gn?gm:"",go)}if(f2>=gb){gc=gc.slice(gb-f5);f5=gb;break}f5=f2;gd=""}gc=f8.slice(ge,ge=f9[gj++]);gl=eK(f9[gj++],gg.cm.options)}}}function dG(f1,f2){return f2.from.ch==0&&f2.to.ch==0&&fv(f2.text)==""&&(!f1.cm||f1.cm.options.wholeLineUpdateBefore)}function fm(ge,f9,f1,f5){function gf(gh){return f1?f1[gh]:null}function f2(gh,gj,gi){ea(gh,gj,gi,f5);ad(gh,"change",gh,f9)}var gc=f9.from,gd=f9.to,gg=f9.text;var ga=e2(ge,gc.line),gb=e2(ge,gd.line);var f8=fv(gg),f4=gf(gg.length-1),f7=gd.line-gc.line;if(dG(ge,f9)){for(var f3=0,f6=[];f31){ge.remove(gc.line+1,f7-1)}ge.insert(gc.line+1,f6)}}}ad(ge,"change",ge,f9)}function eN(f2){this.lines=f2;this.parent=null;for(var f3=0,f1=0;f31||!(this.children[0] instanceof eN))){var f2=[];this.collapse(f2);this.children=[new eN(f2)];this.children[0].parent=this}},collapse:function(f1){for(var f2=0;f250){while(f8.lines.length>50){var f5=f8.lines.splice(f8.lines.length-25,25);var f4=new eN(f5);f8.height-=f4.height;this.children.splice(f6+1,0,f4);f4.parent=this}this.maybeSpill()}break}f2-=f7}},maybeSpill:function(){if(this.children.length<=10){return}var f4=this;do{var f2=f4.children.splice(f4.children.length-5,5);var f3=new fl(f2);if(!f4.parent){var f5=new fl(f4.children);f5.parent=f4;f4.children=[f5,f3];f4=f5}else{f4.size-=f3.size;f4.height-=f3.height;var f1=db(f4.parent.children,f4);f4.parent.children.splice(f1+1,0,f3)}f3.parent=f4.parent}while(f4.children.length>10);f4.parent.maybeSpill()},iterN:function(f1,f7,f6){for(var f2=0;f2=0;f4--){bb(this,f5[f4])}if(f1){eU(this,f1)}else{if(this.cm){fu(this.cm)}}}),undo:cA(function(){b6(this,"undo")}),redo:cA(function(){b6(this,"redo")}),undoSelection:cA(function(){b6(this,"undo",true)}),redoSelection:cA(function(){b6(this,"redo",true)}),setExtending:function(f1){this.extend=f1},getExtending:function(){return this.extend},historySize:function(){var f4=this.history,f1=0,f3=0;for(var f2=0;f2=f5.ch)){f4.push(f3.marker.parent||f3.marker)}}}return f4},findMarks:function(f5,f4,f1){f5=fx(this,f5);f4=fx(this,f4);var f2=[],f3=f5.line;this.iter(f5.line,f4.line+1,function(f6){var f8=f6.markedSpans;if(f8){for(var f7=0;f7f9.to||f9.from==null&&f3!=f5.line||f3==f4.line&&f9.from>f4.ch)&&(!f1||f1(f9.marker))){f2.push(f9.marker.parent||f9.marker)}}}++f3});return f2},getAllMarks:function(){var f1=[];this.iter(function(f3){var f2=f3.markedSpans;if(f2){for(var f4=0;f4f2){f1=f2;return true}f2-=f5;++f3});return fx(this,X(f3,f1))},indexFromPos:function(f2){f2=fx(this,f2);var f1=f2.ch;if(f2.linef4){f4=f1.from}if(f1.to!=null&&f1.to=f4.size){throw new Error("There is no line "+(f6+f4.first)+" in the document.")}for(var f1=f4;!f1.lines;){for(var f2=0;;++f2){var f5=f1.children[f2],f3=f5.chunkSize();if(f61&&!f2.done[f2.done.length-2].ranges){f2.done.pop();return fv(f2.done)}}}}function fA(f7,f5,f1,f4){var f3=f7.history;f3.undone.length=0;var f2=+new Date,f8;if((f3.lastOp==f4||f3.lastOrigin==f5.origin&&f5.origin&&((f5.origin.charAt(0)=="+"&&f7.cm&&f3.lastModTime>f2-f7.cm.options.historyEventDelay)||f5.origin.charAt(0)=="*"))&&(f8=eA(f3,f3.lastOp==f4))){var f9=fv(f8.changes);if(cd(f5.from,f5.to)==0&&cd(f5.from,f9.to)==0){f9.to=cR(f5)}else{f8.changes.push(dk(f7,f5))}}else{var f6=fv(f3.done);if(!f6||!f6.ranges){cJ(f7.sel,f3.done)}f8={changes:[dk(f7,f5)],generation:f3.generation};f3.done.push(f8);while(f3.done.length>f3.undoDepth){f3.done.shift();if(!f3.done[0].ranges){f3.done.shift()}}}f3.done.push(f1);f3.generation=++f3.maxGeneration;f3.lastModTime=f3.lastSelTime=f2;f3.lastOp=f3.lastSelOp=f4;f3.lastOrigin=f3.lastSelOrigin=f5.origin;if(!f9){aC(f7,"historyAdded")}}function by(f5,f1,f3,f4){var f2=f1.charAt(0);return f2=="*"||f2=="+"&&f3.ranges.length==f4.ranges.length&&f3.somethingSelected()==f4.somethingSelected()&&new Date-f5.history.lastSelTime<=(f5.cm?f5.cm.options.historyEventDelay:500)}function fU(f6,f4,f1,f3){var f5=f6.history,f2=f3&&f3.origin;if(f1==f5.lastSelOp||(f2&&f5.lastSelOrigin==f2&&(f5.lastModTime==f5.lastSelTime&&f5.lastOrigin==f2||by(f6,f2,fv(f5.done),f4)))){f5.done[f5.done.length-1]=f4}else{cJ(f4,f5.done)}f5.lastSelTime=+new Date;f5.lastSelOrigin=f2;f5.lastSelOp=f1;if(f3&&f3.clearRedo!==false){fp(f5.undone)}}function cJ(f2,f1){var f3=fv(f1);if(!(f3&&f3.ranges&&f3.equals(f2))){f1.push(f2)}}function bW(f2,f6,f5,f4){var f1=f6["spans_"+f2.id],f3=0;f2.iter(Math.max(f2.first,f5),Math.min(f2.first+f2.size,f4),function(f7){if(f7.markedSpans){(f1||(f1=f6["spans_"+f2.id]={}))[f3]=f7.markedSpans}++f3})}function bh(f3){if(!f3){return null}for(var f2=0,f1;f2-1){fv(ga)[f1]=f8[f1];delete f8[f1]}}}}}}return f2}function K(f4,f3,f2,f1){if(f20}function bw(f1){f1.prototype.on=function(f2,f3){bV(this,f2,f3)};f1.prototype.off=function(f2,f3){d0(this,f2,f3)}}var bg=30;var b8=J.Pass={toString:function(){return"CodeMirror.Pass"}};var Z={scroll:false},N={origin:"*mouse"},cQ={origin:"+move"};function f0(){this.id=null}f0.prototype.set=function(f1,f2){clearTimeout(this.id);this.id=setTimeout(f2,f1)};var bR=J.countColumn=function(f4,f2,f6,f7,f3){if(f2==null){f2=f4.search(/[^\s\u00a0]/);if(f2==-1){f2=f4.length}}for(var f5=f7||0,f8=f3||0;;){var f1=f4.indexOf("\t",f5);if(f1<0||f1>=f2){return f8+(f2-f5)}f8+=f1-f5;f8+=f6-(f8%f6);f5=f1+1}};function ed(f5,f4,f6){for(var f7=0,f3=0;;){var f2=f5.indexOf("\t",f7);if(f2==-1){f2=f5.length}var f1=f2-f7;if(f2==f5.length||f3+f1>=f4){return f7+Math.min(f1,f4-f3)}f3+=f2-f7;f3+=f6-(f3%f6);f7=f2+1;if(f3>=f4){return f7}}}var aV=[""];function co(f1){while(aV.length<=f1){aV.push(fv(aV)+" ")}return aV[f1]}function fv(f1){return f1[f1.length-1]}var dA=function(f1){f1.select()};if(eP){dA=function(f1){f1.selectionStart=0;f1.selectionEnd=f1.value.length}}else{if(dz){dA=function(f2){try{f2.select()}catch(f1){}}}}function db(f3,f1){for(var f2=0;f2"\x80"&&(f1.toUpperCase()!=f1.toLowerCase()||a8.test(f1))};function cx(f1,f2){if(!f2){return fr(f1)}if(f2.source.indexOf("\\w")>-1&&fr(f1)){return true}return f2.test(f1)}function eI(f1){for(var f2 in f1){if(f1.hasOwnProperty(f2)&&f1[f2]){return false}}return true}var ex=/[\u0300-\u036f\u0483-\u0489\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u065e\u0670\u06d6-\u06dc\u06de-\u06e4\u06e7\u06e8\u06ea-\u06ed\u0711\u0730-\u074a\u07a6-\u07b0\u07eb-\u07f3\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0900-\u0902\u093c\u0941-\u0948\u094d\u0951-\u0955\u0962\u0963\u0981\u09bc\u09be\u09c1-\u09c4\u09cd\u09d7\u09e2\u09e3\u0a01\u0a02\u0a3c\u0a41\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a70\u0a71\u0a75\u0a81\u0a82\u0abc\u0ac1-\u0ac5\u0ac7\u0ac8\u0acd\u0ae2\u0ae3\u0b01\u0b3c\u0b3e\u0b3f\u0b41-\u0b44\u0b4d\u0b56\u0b57\u0b62\u0b63\u0b82\u0bbe\u0bc0\u0bcd\u0bd7\u0c3e-\u0c40\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0cbc\u0cbf\u0cc2\u0cc6\u0ccc\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0d3e\u0d41-\u0d44\u0d4d\u0d57\u0d62\u0d63\u0dca\u0dcf\u0dd2-\u0dd4\u0dd6\u0ddf\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0eb1\u0eb4-\u0eb9\u0ebb\u0ebc\u0ec8-\u0ecd\u0f18\u0f19\u0f35\u0f37\u0f39\u0f71-\u0f7e\u0f80-\u0f84\u0f86\u0f87\u0f90-\u0f97\u0f99-\u0fbc\u0fc6\u102d-\u1030\u1032-\u1037\u1039\u103a\u103d\u103e\u1058\u1059\u105e-\u1060\u1071-\u1074\u1082\u1085\u1086\u108d\u109d\u135f\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b7-\u17bd\u17c6\u17c9-\u17d3\u17dd\u180b-\u180d\u18a9\u1920-\u1922\u1927\u1928\u1932\u1939-\u193b\u1a17\u1a18\u1a56\u1a58-\u1a5e\u1a60\u1a62\u1a65-\u1a6c\u1a73-\u1a7c\u1a7f\u1b00-\u1b03\u1b34\u1b36-\u1b3a\u1b3c\u1b42\u1b6b-\u1b73\u1b80\u1b81\u1ba2-\u1ba5\u1ba8\u1ba9\u1c2c-\u1c33\u1c36\u1c37\u1cd0-\u1cd2\u1cd4-\u1ce0\u1ce2-\u1ce8\u1ced\u1dc0-\u1de6\u1dfd-\u1dff\u200c\u200d\u20d0-\u20f0\u2cef-\u2cf1\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua66f-\ua672\ua67c\ua67d\ua6f0\ua6f1\ua802\ua806\ua80b\ua825\ua826\ua8c4\ua8e0-\ua8f1\ua926-\ua92d\ua947-\ua951\ua980-\ua982\ua9b3\ua9b6-\ua9b9\ua9bc\uaa29-\uaa2e\uaa31\uaa32\uaa35\uaa36\uaa43\uaa4c\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uabe5\uabe8\uabed\udc00-\udfff\ufb1e\ufe00-\ufe0f\ufe20-\ufe26\uff9e\uff9f]/;function fd(f1){return f1.charCodeAt(0)>=768&&ex.test(f1)}function fK(f1,f5,f4,f3){var f6=document.createElement(f1);if(f4){f6.className=f4}if(f3){f6.style.cssText=f3}if(typeof f5=="string"){f6.appendChild(document.createTextNode(f5))}else{if(f5){for(var f2=0;f20;--f1){f2.removeChild(f2.firstChild)}return f2}function bP(f1,f2){return dP(f1).appendChild(f2)}function fT(f1,f2){if(f1.contains){return f1.contains(f2)}while(f2=f2.parentNode){if(f2==f1){return true}}}function dC(){return document.activeElement}if(dz&&l<11){dC=function(){try{return document.activeElement}catch(f1){return document.body}}}function T(f1){return new RegExp("\\b"+f1+"\\b\\s*")}function f(f2,f1){var f3=T(f1);if(f3.test(f2.className)){f2.className=f2.className.replace(f3,"")}}function fo(f2,f1){if(!T(f1).test(f2.className)){f2.className+=" "+f1}}function fF(f3,f1){var f2=f3.split(" ");for(var f4=0;f42&&!(dz&&l<8)}}if(fz){return fK("span","\u200b")}else{return fK("span","\u00a0",null,"display: inline-block; width: 1px; margin-right: -1px")}}var fy;function bM(f4){if(fy!=null){return fy}var f1=bP(f4,document.createTextNode("A\u062eA"));var f3=ck(f1,0,1).getBoundingClientRect();if(!f3||f3.left==f3.right){return false}var f2=ck(f1,1,2).getBoundingClientRect();return fy=(f2.right-f3.right<3)}var aW=J.splitLines="\n\nb".split(/\n/).length!=3?function(f6){var f7=0,f1=[],f5=f6.length;while(f7<=f5){var f4=f6.indexOf("\n",f7);if(f4==-1){f4=f6.length}var f3=f6.slice(f7,f6.charAt(f4-1)=="\r"?f4-1:f4);var f2=f3.indexOf("\r");if(f2!=-1){f1.push(f3.slice(0,f2));f7+=f2+1}else{f1.push(f3);f7=f4+1}}return f1}:function(f1){return f1.split(/\r\n?|\n/)};var bq=window.getSelection?function(f2){try{return f2.selectionStart!=f2.selectionEnd}catch(f1){return false}}:function(f3){try{var f1=f3.ownerDocument.selection.createRange()}catch(f2){}if(!f1||f1.parentElement()!=f3){return false}return f1.compareEndPoints("StartToEnd",f1)!=0};var c4=(function(){var f1=fK("div");if("oncopy" in f1){return true}f1.setAttribute("oncopy","return;");return typeof f1.oncopy=="function"})();var eT=null;function aI(f2){if(eT!=null){return eT}var f3=bP(f2,fK("span","x"));var f4=f3.getBoundingClientRect();var f1=ck(f3,0,1).getBoundingClientRect();return eT=Math.abs(f4.left-f1.left)>1}var e3={3:"Enter",8:"Backspace",9:"Tab",13:"Enter",16:"Shift",17:"Ctrl",18:"Alt",19:"Pause",20:"CapsLock",27:"Esc",32:"Space",33:"PageUp",34:"PageDown",35:"End",36:"Home",37:"Left",38:"Up",39:"Right",40:"Down",44:"PrintScrn",45:"Insert",46:"Delete",59:";",61:"=",91:"Mod",92:"Mod",93:"Mod",107:"=",109:"-",127:"Delete",173:"-",186:";",187:"=",188:",",189:"-",190:".",191:"/",192:"`",219:"[",220:"\\",221:"]",222:"'",63232:"Up",63233:"Down",63234:"Left",63235:"Right",63272:"Delete",63273:"Home",63275:"End",63276:"PageUp",63277:"PageDown",63302:"Insert"};J.keyNames=e3;(function(){for(var f1=0;f1<10;f1++){e3[f1+48]=e3[f1+96]=String(f1)}for(var f1=65;f1<=90;f1++){e3[f1]=String.fromCharCode(f1)}for(var f1=1;f1<=12;f1++){e3[f1+111]=e3[f1+63235]="F"+f1}})();function dS(f1,f7,f6,f5){if(!f1){return f5(f7,f6,"ltr")}var f4=false;for(var f3=0;f3f7||f7==f6&&f2.to==f7){f5(Math.max(f2.from,f7),Math.min(f2.to,f6),f2.level==1?"rtl":"ltr");f4=true}}if(!f4){f5(f7,f6,"ltr")}}function dn(f1){return f1.level%2?f1.to:f1.from}function fW(f1){return f1.level%2?f1.from:f1.to}function cB(f2){var f1=a(f2);return f1?dn(f1[0]):0}function cO(f2){var f1=a(f2);if(!f1){return f2.text.length}return fW(fv(f1))}function br(f2,f5){var f3=e2(f2.doc,f5);var f6=z(f3);if(f6!=f3){f5=bL(f6)}var f1=a(f6);var f4=!f1?0:f1[0].level%2?cO(f6):cB(f6);return X(f5,f4)}function dD(f3,f6){var f2,f4=e2(f3.doc,f6);while(f2=ei(f4)){f4=f2.find(1,true).line;f6=null}var f1=a(f4);var f5=!f1?f4.text.length:f1[0].level%2?cB(f4):cO(f4);return X(f6==null?bL(f4):f6,f5)}function dy(f2,f7){var f6=br(f2,f7.line);var f3=e2(f2.doc,f6.line);var f1=a(f3);if(!f1||f1[0].level==0){var f5=Math.max(0,f3.text.search(/\S/));var f4=f7.line==f6.line&&f7.ch<=f5&&f7.ch;return X(f6.line,f4?0:f5)}return f6}function am(f2,f3,f1){var f4=f2[0].level;if(f3==f4){return true}if(f1==f4){return false}return f3f5){return f2}if((f4.from==f5||f4.to==f5)){if(f3==null){f3=f2}else{if(am(f1,f4.level,f1[f3].level)){if(f4.from!=f4.to){eQ=f3}return f2}else{if(f4.from!=f4.to){eQ=f2}return f3}}}}return f3}function e1(f1,f4,f2,f3){if(!f3){return f4+f2}do{f4+=f2}while(f4>0&&fd(f1.text.charAt(f4)));return f4}function v(f1,f8,f3,f4){var f5=a(f1);if(!f5){return ah(f1,f8,f3,f4)}var f7=aE(f5,f8),f2=f5[f7];var f6=e1(f1,f8,f2.level%2?-f3:f3,f4);for(;;){if(f6>f2.from&&f60)==f2.level%2?f2.to:f2.from}else{f2=f5[f7+=f3];if(!f2){return null}if((f3>0)==f2.level%2){f6=e1(f1,f2.to,-1,f4)}else{f6=e1(f1,f2.from,1,f4)}}}}function ah(f1,f5,f2,f3){var f4=f5+f2;if(f3){while(f4>0&&fd(f1.text.charAt(f4))){f4+=f2}}return f4<0||f4>f1.text.length?null:f4}var bc=(function(){var f7="bbbbbbbbbtstwsbbbbbbbbbbbbbbssstwNN%%%NNNNNN,N,N1111111111NNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNbbbbbbsbbbbbbbbbbbbbbbbbbbbbbbbbb,N%%%%NNNNLNNNNN%%11NLNNN1LNNNNNLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLN";var f5="rrrrrrrrrrrr,rNNmmmmmmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmrrrrrrrnnnnnnnnnn%nnrrrmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmmmmmmNmmmm";function f4(gb){if(gb<=247){return f7.charAt(gb)}else{if(1424<=gb&&gb<=1524){return"R"}else{if(1536<=gb&&gb<=1773){return f5.charAt(gb-1536)}else{if(1774<=gb&&gb<=2220){return"r"}else{if(8192<=gb&&gb<=8203){return"w"}else{if(gb==8204){return"b"}else{return"L"}}}}}}}var f1=/[\u0590-\u05f4\u0600-\u06ff\u0700-\u08ac]/;var ga=/[stwN]/,f3=/[LRr]/,f2=/[Lb1n]/,f6=/[1n]/;var f9="L";function f8(gd,gc,gb){this.level=gd;this.from=gc;this.to=gb}return function(gl){if(!f1.test(gl)){return false}var gr=gl.length,gh=[];for(var gq=0,gd;gq=15){dS=false;cV=true}var bO=b5&&(dD||dS&&(aT==null||aT<12.11));var fV=cn||(dA&&l>=9);var fY=false,a2=false;function J(f3,f4){if(!(this instanceof J)){return new J(f3,f4)}this.options=f4=f4?aJ(f4):{};aJ(eU,f4,false);cc(f4);var f8=f4.value;if(typeof f8=="string"){f8=new ar(f8,f4.mode)}this.doc=f8;var f7=this.display=new ez(f3,f8);f7.wrapper.CodeMirror=this;d2(this);cL(this);if(f4.lineWrapping){this.display.wrapper.className+=" CodeMirror-wrap"}if(f4.autofocus&&!d6){eq(this)}this.state={keyMaps:[],overlays:[],modeGen:0,overwrite:false,focused:false,suppressEdits:false,pasteIncoming:false,cutIncoming:false,draggingText:false,highlight:new f2(),keySeq:null};if(dA&&l<11){setTimeout(cu(ff,this,true),20)}fG(this);be();cF(this);this.curOp.forceUpdate=true;d1(this,f8);if((f4.autofocus&&!d6)||dE()==f7.input){setTimeout(cu(cz,this),20)}else{aQ(this)}for(var f6 in ba){if(ba.hasOwnProperty(f6)){ba[f6](this,f4[f6],ca)}}dV(this);for(var f5=0;f5f5.maxLineLength){f5.maxLineLength=f6;f5.maxLine=f7}})}function cc(f3){var f4=dc(f3.gutters,"CodeMirror-linenumbers");if(f4==-1&&f3.lineNumbers){f3.gutters=f3.gutters.concat(["CodeMirror-linenumbers"])}else{if(f4>-1&&!f3.lineNumbers){f3.gutters=f3.gutters.slice(0);f3.gutters.splice(f4,1)}}}function cN(f3){return f3.display.scroller.clientHeight-f3.display.wrapper.clientHeightf3.clientWidth;if(f5&&f3.scrollWidth<=f3.clientWidth+1&&f4>0&&!f3.hScrollbarTakesSpace){f5=false}var f6=gb>f3.clientHeight;if(f6){f7.scrollbarV.style.display="block";f7.scrollbarV.style.bottom=f5?f4+"px":"0";f7.scrollbarV.firstChild.style.height=Math.max(0,gb-f3.clientHeight+(f3.barHeight||f7.scrollbarV.clientHeight))+"px"}else{f7.scrollbarV.style.display="";f7.scrollbarV.firstChild.style.height="0"}if(f5){f7.scrollbarH.style.display="block";f7.scrollbarH.style.right=f6?f4+"px":"0";f7.scrollbarH.firstChild.style.width=(f3.scrollWidth-f3.clientWidth+(f3.barWidth||f7.scrollbarH.clientWidth))+"px"}else{f7.scrollbarH.style.display="";f7.scrollbarH.firstChild.style.width="0"}if(f5&&f6){f7.scrollbarFiller.style.display="block";f7.scrollbarFiller.style.height=f7.scrollbarFiller.style.width=f4+"px"}else{f7.scrollbarFiller.style.display=""}if(f5&&ga.options.coverGutterNextToScrollbar&&ga.options.fixedGutter){f7.gutterFiller.style.display="block";f7.gutterFiller.style.height=f4+"px";f7.gutterFiller.style.width=f7.gutters.offsetWidth+"px"}else{f7.gutterFiller.style.display=""}if(!ga.state.checkedOverlayScrollbar&&f3.clientHeight>0){if(f4===0){var f9=b5&&!c2?"12px":"18px";f7.scrollbarV.style.minWidth=f7.scrollbarH.style.minHeight=f9;var f8=function(gc){if(M(gc)!=f7.scrollbarV&&M(gc)!=f7.scrollbarH){cX(ga,ej)(gc)}};bV(f7.scrollbarV,"mousedown",f8);bV(f7.scrollbarH,"mousedown",f8)}ga.state.checkedOverlayScrollbar=true}}function b4(f6,ga,f5){var f7=f5&&f5.top!=null?Math.max(0,f5.top):f6.scroller.scrollTop;f7=Math.floor(f7-eY(f6));var f3=f5&&f5.bottom!=null?f5.bottom:f7+f6.wrapper.clientHeight;var f8=bE(ga,f7),f9=bE(ga,f3);if(f5&&f5.ensure){var f4=f5.ensure.from.line,gb=f5.ensure.to.line;if(f4=f9){return{from:bE(ga,bK(e5(ga,gb))-f6.wrapper.clientHeight),to:gb}}}return{from:f8,to:Math.max(f9,f8+1)}}function ev(gb){var f9=gb.display,ga=f9.view;if(!f9.alignWidgets&&(!f9.gutters.firstChild||!gb.options.fixedGutter)){return}var f7=dN(f9)-f9.scroller.scrollLeft+gb.doc.scrollLeft;var f3=f9.gutters.offsetWidth,f4=f7+"px";for(var f6=0;f6=f7.viewFrom&&f6.visible.to<=f7.viewTo&&(f7.updateLineNumbers==null||f7.updateLineNumbers>=f7.viewTo)&&c6(gc)==0){return false}if(dV(gc)){en(gc);f6.dims=e3(gc)}var f5=gb.first+gb.size;var f9=Math.max(f6.visible.from-gc.options.viewportMargin,gb.first);var ga=Math.min(f5,f6.visible.to+gc.options.viewportMargin);if(f7.viewFromga&&f7.viewTo-ga<20){ga=Math.min(f5,f7.viewTo)}if(a2){f9=aR(gc.doc,f9);ga=dT(gc.doc,ga)}var f4=f9!=f7.viewFrom||ga!=f7.viewTo||f7.lastWrapHeight!=f6.wrapperHeight||f7.lastWrapWidth!=f6.wrapperWidth;cO(gc,f9,ga);f7.viewOffset=bK(e5(gc.doc,f7.viewFrom));gc.display.mover.style.top=f7.viewOffset+"px";var f3=c6(gc);if(!f4&&f3==0&&!f6.force&&(f7.updateLineNumbers==null||f7.updateLineNumbers>=f7.viewTo)){return false}var f8=dE();if(f3>4){f7.lineDiv.style.display="none"}cl(gc,f7.updateLineNumbers,f6.dims);if(f3>4){f7.lineDiv.style.display=""}if(f8&&dE()!=f8&&f8.offsetHeight){f8.focus()}dR(f7.cursorDiv);dR(f7.selectionDiv);if(f4){f7.lastWrapHeight=f6.wrapperHeight;f7.lastWrapWidth=f6.wrapperWidth;d5(gc,400)}f7.updateLineNumbers=null;return true}function ci(f4,f8){var f6=f8.force,f3=f8.viewport;for(var f7=true;;f7=false){if(f7&&f4.options.lineWrapping&&f8.oldScrollerWidth!=f4.display.scroller.clientWidth){f6=true}else{f6=false;if(f3&&f3.top!=null){f3={top:Math.min(f4.doc.height+bG(f4.display)-bg-f4.display.scroller.clientHeight,f3.top)}}f8.visible=b4(f4.display,f4.doc,f3);if(f8.visible.from>=f4.display.viewFrom&&f8.visible.to<=f4.display.viewTo){break}}if(!D(f4,f8)){break}a4(f4);var f5=dr(f4);bA(f4);dq(f4,f5);eP(f4,f5)}ad(f4,"update",f4);if(f4.display.viewFrom!=f8.oldViewFrom||f4.display.viewTo!=f8.oldViewTo){ad(f4,"viewportChange",f4,f4.display.viewFrom,f4.display.viewTo)}}function dJ(f4,f3){var f6=new aF(f4,f3);if(D(f4,f6)){a4(f4);ci(f4,f6);var f5=dr(f4);bA(f4);dq(f4,f5);eP(f4,f5)}}function dq(f3,f4){f3.display.sizer.style.minHeight=f3.display.heightForcer.style.top=f4.docHeight+"px";f3.display.gutters.style.height=Math.max(f4.docHeight,f4.clientHeight-bg)+"px"}function fQ(f3,f4){if(f3.display.sizer.offsetWidth+f3.display.gutters.offsetWidth0.001||f9<-0.001){fR(gb.line,gc);b9(gb.line);if(gb.rest){for(var f3=0;f3-1){gc=false}aa(ge,f7,f8,gd)}if(gc){dR(f7.lineNumber);f7.lineNumber.appendChild(document.createTextNode(ei(ge.options,f8)))}gf=f7.node.nextSibling}}f8+=f7.size}while(gf){gf=f9(gf)}}function aa(f3,f5,f7,f8){for(var f4=0;f4=0&&cd(f6,f4.to())<=0){return f5}}return -1}};function dO(f3,f4){this.anchor=f3;this.head=f4}dO.prototype={from:function(){return aq(this.anchor,this.head)},to:function(){return bv(this.anchor,this.head)},empty:function(){return this.head.line==this.anchor.line&&this.head.ch==this.anchor.ch}};function cv(f3,ga){var f5=f3[ga];f3.sort(function(gd,gc){return cd(gd.from(),gc.from())});ga=dc(f3,f5);for(var f7=1;f7=0){var f8=aq(f4.from(),gb.from()),f9=bv(f4.to(),gb.to());var f6=f4.empty()?gb.from()==gb.head:f4.from()==f4.head;if(f7<=ga){--ga}f3.splice(--f7,2,new dO(f6?f9:f8,f6?f8:f9))}}return new fO(f3,ga)}function eJ(f3,f4){return new fO([new dO(f3,f4||f3)],0)}function c0(f3,f4){return Math.max(f3.first,Math.min(f4,f3.first+f3.size-1))}function fA(f4,f5){if(f5.linef3){return X(f3,e5(f4,f3).text.length)}return fj(f5,e5(f4,f5.line).text.length)}function fj(f5,f4){var f3=f5.ch;if(f3==null||f3>f4){return X(f5.line,f4)}else{if(f3<0){return X(f5.line,0)}else{return f5}}}function b7(f4,f3){return f3>=f4.first&&f3=f5.ch:f3.to>f5.ch))){if(f9){aB(f4,"beforeCursorEnter");if(f4.explicitlyCleared){if(!ge.markedSpans){break}else{--f7;continue}}}if(!f4.atomic){continue}var ga=f4.find(f6<0?-1:1);if(cd(ga,f5)==0){ga.ch+=f6;if(ga.ch<0){if(ga.line>gc.first){ga=fA(gc,X(ga.line-1))}else{ga=null}}else{if(ga.ch>ge.text.length){if(ga.line3){ge(gy,gw.top,null,gw.bottom);gy=f6;if(gw.bottomgl.bottom||gx.bottom==gl.bottom&&gx.right>gl.right){gl=gx}if(gy0){f5.blinker=setInterval(function(){f5.cursorDiv.style.visibility=(f4=!f4)?"":"hidden"},f3.options.cursorBlinkRate)}else{if(f3.options.cursorBlinkRate<0){f5.cursorDiv.style.visibility="hidden"}}}function d5(f3,f4){if(f3.doc.mode.startState&&f3.doc.frontier=f3.display.viewTo){return}var f5=+new Date+f3.options.workTime;var f6=b1(f7.mode,ds(f3,f7.frontier));var f4=[];f7.iter(f7.frontier,Math.min(f7.first+f7.size,f3.display.viewTo+500),function(f8){if(f7.frontier>=f3.display.viewFrom){var gb=f8.styles;var gd=fq(f3,f8,f6,true);f8.styles=gd.styles;var ga=f8.styleClasses,gc=gd.classes;if(gc){f8.styleClasses=gc}else{if(ga){f8.styleClasses=null}}var ge=!gb||gb.length!=f8.styles.length||ga!=gc&&(!ga||!gc||ga.bgClass!=gc.bgClass||ga.textClass!=gc.textClass);for(var f9=0;!ge&&f9f5){d5(f3,f3.options.workDelay);return true}});if(f4.length){cJ(f3,function(){for(var f8=0;f8f5;--gc){if(gc<=f8.first){return f8.first}var gb=e5(f8,gc-1);if(gb.stateAfter&&(!f6||gc<=f8.frontier)){return gc}var ga=bR(gb.text,null,f9.options.tabSize);if(f7==null||f4>ga){f7=gc-1;f4=ga}}return f7}function ds(f3,f9,f4){var f7=f3.doc,f6=f3.display;if(!f7.mode.startState){return true}var f8=cx(f3,f9,f4),f5=f8>f7.first&&e5(f7,f8-1).stateAfter;if(!f5){f5=bY(f7.mode)}else{f5=b1(f7.mode,f5)}f7.iter(f8,f9,function(ga){dn(f3,ga.text,f5);var gb=f8==f9-1||f8%5==0||f8>=f6.viewFrom&&f82){f8.push((gb.bottom+f4.top)/2-f9.top)}}}f8.push(f9.bottom-f9.top)}}function cs(f5,f3,f6){if(f5.line==f3){return{map:f5.measure.map,cache:f5.measure.cache}}for(var f4=0;f4f6){return{map:f5.measure.maps[f4],cache:f5.measure.caches[f4],before:true}}}}function cW(f3,f5){f5=z(f5);var f7=bL(f5);var f4=f3.display.externalMeasured=new bt(f3.doc,f5,f7);f4.lineN=f7;var f6=f4.built=eI(f3,f4);f4.text=f6.pre;bP(f3.display.lineMeasure,f6.pre);return f4}function d7(f3,f4,f6,f5){return E(f3,aZ(f3,f4),f6,f5)}function e1(f3,f5){if(f5>=f3.display.viewFrom&&f5=f4.lineN&&f5gc){f6=gi-gm;f7=f6-1;if(gc>=gi){f3="right"}}}}if(f7!=null){gh=go[gj+2];if(gm==gi&&f8==(gh.insertLeft?"left":"right")){f3=f8}if(f8=="left"&&f7==0){while(gj&&go[gj-2]==go[gj-3]&&go[gj-1].insertLeft){gh=go[(gj-=3)+2];f3="left"}}if(f8=="right"&&f7==gi-gm){while(gj0){f3=f8="right"}var f5;if(ga.options.lineWrapping&&(f5=gh.getClientRects()).length>1){f4=f5[f8=="right"?f5.length-1:0]}else{f4=gh.getBoundingClientRect()}}if(dA&&l<9&&!f7&&(!f4||!f4.left&&!f4.right)){var f9=gh.parentNode.getClientRects()[0];if(f9){f4={left:f9.left,right:f9.left+du(ga.display),top:f9.top,bottom:f9.bottom}}else{f4=er}}var gf=f4.top-gk.rect.top,gd=f4.bottom-gk.rect.top;var gn=(gf+gd)/2;var gl=gk.view.measure.heights;for(var gj=0;gjgg.from){return f7(gi-1)}return f7(gi,gh)}var f8=a(f9),f3=gb.ch;if(!f8){return f7(f3)}var f4=aD(f8,f3);var f6=gd(f3,f4);if(eT!=null){f6.other=gd(f3,eT)}return f6}function dy(f3,f7){var f6=0,f7=fA(f3.doc,f7);if(!f3.options.lineWrapping){f6=du(f3.display)*f7.ch}var f4=e5(f3.doc,f7.line);var f5=bK(f4)+eY(f3.display);return{left:f6,right:f6,top:f5,bottom:f5+f4.height}}function fM(f3,f4,f5,f7){var f6=X(f3,f4);f6.xRel=f7;if(f5){f6.outside=true}return f6}function fF(ga,f7,f6){var f9=ga.doc;f6+=ga.display.viewOffset;if(f6<0){return fM(f9.first,0,true,-1)}var f5=bE(f9,f6),gb=f9.first+f9.size-1;if(f5>gb){return fM(f9.first+f9.size-1,e5(f9,gb).text.length,true,1)}if(f7<0){f7=0}var f4=e5(f9,f5);for(;;){var gc=cU(ga,f4,f5,f7,f6);var f8=el(f4);var f3=f8&&f8.find(0,true);if(f8&&(gc.ch>f3.from.ch||gc.ch==f3.from.ch&&gc.xRel>0)){f5=bL(f4=f3.to.line)}else{return gc}}}function cU(gd,f5,gg,gf,ge){var gc=ge-bK(f5);var f9=false,gm=2*gd.display.wrapper.clientWidth;var gj=aZ(gd,f5);function gq(gs){var gt=dK(gd,X(gg,gs),"line",f5,gj);f9=true;if(gc>gt.bottom){return gt.left-gm}else{if(gcf4){return fM(gg,f6,f8,1)}for(;;){if(gi?f6==gn||f6==v(f5,gn,1):f6-gn<=1){var gh=gf1?1:0);return gb}var ga=Math.ceil(gl/2),gr=gn+ga;if(gi){gr=gn;for(var go=0;gogf){f6=gr;f4=f7;if(f8=f9){f4+=1000}gl=ga}else{gn=gr;gk=f7;f3=f9;gl-=ga}}}var aE;function aS(f5){if(f5.cachedTextHeight!=null){return f5.cachedTextHeight}if(aE==null){aE=fN("pre");for(var f4=0;f4<49;++f4){aE.appendChild(document.createTextNode("x"));aE.appendChild(fN("br"))}aE.appendChild(document.createTextNode("x"))}bP(f5.measure,aE);var f3=aE.offsetHeight/50;if(f3>3){f5.cachedTextHeight=f3}dR(f5.measure);return f3||1}function du(f7){if(f7.cachedCharWidth!=null){return f7.cachedCharWidth}var f3=fN("span","xxxxxxxxxx");var f6=fN("pre",[f3]);bP(f7.measure,f6);var f5=f3.getBoundingClientRect(),f4=(f5.right-f5.left)/10;if(f4>2){f7.cachedCharWidth=f4}return f4||10}var bn=null;var dY=0;function cF(f3){f3.curOp={cm:f3,viewChanged:false,startHeight:f3.doc.height,forceUpdate:false,updateInput:null,typing:false,changeObjs:null,cursorActivityHandlers:null,cursorActivityCalled:0,selectionChanged:false,updateMaxLine:false,scrollLeft:null,scrollTop:null,scrollToPos:null,id:++dY};if(bn){bn.ops.push(f3.curOp)}else{f3.curOp.ownsGroup=bn={ops:[f3.curOp],delayedCallbacks:[]}}}function cQ(f6){var f5=f6.delayedCallbacks,f4=0;do{for(;f4=f4.viewTo)||f4.maxLineChanged&&f3.options.lineWrapping;f5.update=f5.mustUpdate&&new aF(f3,f5.mustUpdate&&{top:f5.scrollTop,ensure:f5.scrollToPos},f5.forceUpdate)}function ap(f3){f3.updatedDisplay=f3.mustUpdate&&D(f3.cm,f3.update)}function b0(f5){var f3=f5.cm,f4=f3.display;if(f5.updatedDisplay){a4(f3)}f5.barMeasure=dr(f3);if(f4.maxLineChanged&&!f3.options.lineWrapping){f5.adjustWidthTo=d7(f3,f4.maxLine,f4.maxLine.text.length).left+3;f5.maxScrollLeft=Math.max(0,f4.sizer.offsetLeft+f5.adjustWidthTo+bg-f4.scroller.clientWidth)}if(f5.updatedDisplay||f5.selectionChanged){f5.newSelectionNodes=bj(f3)}}function ao(f4){var f3=f4.cm;if(f4.adjustWidthTo!=null){f3.display.sizer.style.minWidth=f4.adjustWidthTo+"px";if(f4.maxScrollLeft1){eP(gc)}if(f6.updatedDisplay){ci(gc,f6.update)}if(f8.wheelStartX!=null&&(f6.scrollTop!=null||f6.scrollLeft!=null||f6.scrollToPos)){f8.wheelStartX=f8.wheelStartY=null}if(f6.scrollTop!=null&&(f8.scroller.scrollTop!=f6.scrollTop||f6.forceScroll)){var f9=Math.max(0,Math.min(f8.scroller.scrollHeight-f8.scroller.clientHeight,f6.scrollTop));f8.scroller.scrollTop=f8.scrollbarV.scrollTop=gb.scrollTop=f9}if(f6.scrollLeft!=null&&(f8.scroller.scrollLeft!=f6.scrollLeft||f6.forceScroll)){var f4=Math.max(0,Math.min(f8.scroller.scrollWidth-f8.scroller.clientWidth,f6.scrollLeft));f8.scroller.scrollLeft=f8.scrollbarH.scrollLeft=gb.scrollLeft=f4;ev(gc)}if(f6.scrollToPos){var ga=F(gc,fA(gb,f6.scrollToPos.from),fA(gb,f6.scrollToPos.to),f6.scrollToPos.margin);if(f6.scrollToPos.isCursor&&gc.state.focused){dW(gc,ga)}}var f7=f6.maybeHiddenMarkers,f3=f6.maybeUnhiddenMarkers;if(f7){for(var f5=0;f5f6.barMeasure.clientWidth&&f6.barMeasure.scrollWidthf8)){f5.updateLineNumbers=f8}ga.curOp.viewChanged=true;if(f8>=f5.viewTo){if(a2&&aR(ga.doc,f8)f5.viewFrom){en(ga)}else{f5.viewFrom+=gb;f5.viewTo+=gb}}else{if(f8<=f5.viewFrom&&f9>=f5.viewTo){en(ga)}else{if(f8<=f5.viewFrom){var f7=c9(ga,f9,f9+gb,1);if(f7){f5.view=f5.view.slice(f7.index);f5.viewFrom=f7.lineN;f5.viewTo+=gb}else{en(ga)}}else{if(f9>=f5.viewTo){var f7=c9(ga,f8,f8,-1);if(f7){f5.view=f5.view.slice(0,f7.index);f5.viewTo=f7.lineN}else{en(ga)}}else{var f6=c9(ga,f8,f8,-1);var f4=c9(ga,f9,f9+gb,1);if(f6&&f4){f5.view=f5.view.slice(0,f6.index).concat(eM(ga,f6.lineN,f4.lineN)).concat(f5.view.slice(f4.index));f5.viewTo+=gb}else{en(ga)}}}}}}var f3=f5.externalMeasured;if(f3){if(f9=f7.lineN&&f5=f9.viewTo){return}var f6=f9.view[di(f4,f5)];if(f6.node==null){return}var f3=f6.changes||(f6.changes=[]);if(dc(f3,f8)==-1){f3.push(f8)}}function en(f3){f3.display.viewFrom=f3.display.viewTo=f3.doc.first;f3.display.view=[];f3.display.viewOffset=0}function di(f3,f6){if(f6>=f3.display.viewTo){return null}f6-=f3.display.viewFrom;if(f6<0){return null}var f4=f3.display.view;for(var f5=0;f50){if(f8==f9.length-1){return null}ga=(f3+f9[f8].size)-f5;f8++}else{ga=f3-f5}f5+=ga;f7+=ga}while(aR(gb.doc,f7)!=f7){if(f8==(f4<0?0:f9.length-1)){return null}f7+=f4*f9[f8-(f4<0?1:0)].size;f8+=f4}return{index:f8,lineN:f7}}function cO(f3,f7,f6){var f5=f3.display,f4=f5.view;if(f4.length==0||f7>=f5.viewTo||f6<=f5.viewFrom){f5.view=eM(f3,f7,f6);f5.viewFrom=f7}else{if(f5.viewFrom>f7){f5.view=eM(f3,f7,f5.viewFrom).concat(f5.view)}else{if(f5.viewFromf6){f5.view=f5.view.slice(0,di(f3,f6))}}}f5.viewTo=f6}function c6(f3){var f4=f3.display.view,f7=0;for(var f6=0;f6=9&&f7.display.inputHasSelection===ga||b5&&/[\uf700-\uf7ff]/.test(ga)){ff(f7);return false}var gi=!f7.curOp;if(gi){cF(f7)}f7.display.shift=false;if(ga.charCodeAt(0)==8203&&gm.sel==f7.display.selForContextMenu&&!gb){gb="\u200b"}var gh=0,ge=Math.min(gb.length,ga.length);while(gh1){if(bi&&bi.join("\n")==f4){gl=gm.sel.ranges.length%bi.length==0&&bQ(bi,aV)}else{if(gc.length==gm.sel.ranges.length){gl=bQ(gc,function(gn){return[gn]})}}}for(var gj=gm.sel.ranges.length-1;gj>=0;gj--){var gd=gm.sel.ranges[gj];var gf=gd.from(),f3=gd.to();if(gh-1){ac(f7,f5.line,"smart");break}}}else{if(f9.electricInput){if(f9.electricInput.test(e5(gm,f5.line).text.slice(0,f5.ch))){ac(f7,f5.line,"smart")}}}}}fx(f7);f7.curOp.updateInput=f6;f7.curOp.typing=true;if(ga.length>1000||ga.indexOf("\n")>-1){f8.value=f7.display.prevInput=""}else{f7.display.prevInput=ga}if(gi){al(f7)}f7.state.pasteIncoming=f7.state.cutIncoming=false;return true}function ff(f3,f7){var f4,f6,f9=f3.doc;if(f3.somethingSelected()){f3.display.prevInput="";var f5=f9.sel.primary();f4=c5&&(f5.to().line-f5.from().line>100||(f6=f3.getSelection()).length>1000);var f8=f4?"-":f6||f3.getSelection();f3.display.input.value=f8;if(f3.state.focused){dB(f3.display.input)}if(dA&&l>=9){f3.display.inputHasSelection=f8}}else{if(!f7){f3.display.prevInput=f3.display.input.value="";if(dA&&l>=9){f3.display.inputHasSelection=null}}}f3.display.inaccurateSelection=f4}function eq(f3){if(f3.options.readOnly!="nocursor"&&(!d6||dE()!=f3.display.input)){f3.display.input.focus()}}function s(f3){if(!f3.state.focused){eq(f3);cz(f3)}}function ai(f3){return f3.options.readOnly||f3.doc.cantEdit}function fG(f3){var f5=f3.display;bV(f5.scroller,"mousedown",cX(f3,ej));if(dA&&l<11){bV(f5.scroller,"dblclick",cX(f3,function(f9){if(aN(f3,f9)){return}var ga=cm(f3,f9);if(!ga||m(f3,f9)||a5(f3.display,f9)){return}cD(f9);var f8=f3.findWordAt(ga);fK(f3.doc,f8.anchor,f8.head)}))}else{bV(f5.scroller,"dblclick",function(f8){aN(f3,f8)||cD(f8)})}bV(f5.lineSpace,"selectstart",function(f8){if(!a5(f5,f8)){cD(f8)}});if(!fV){bV(f5.scroller,"contextmenu",function(f8){ax(f3,f8)})}bV(f5.scroller,"scroll",function(){if(f5.scroller.clientHeight){O(f3,f5.scroller.scrollTop);bC(f3,f5.scroller.scrollLeft,true);aB(f3,"scroll",f3)}});bV(f5.scrollbarV,"scroll",function(){if(f5.scroller.clientHeight){O(f3,f5.scrollbarV.scrollTop)}});bV(f5.scrollbarH,"scroll",function(){if(f5.scroller.clientHeight){bC(f3,f5.scrollbarH.scrollLeft)}});bV(f5.scroller,"mousewheel",function(f8){b(f3,f8)});bV(f5.scroller,"DOMMouseScroll",function(f8){b(f3,f8)});function f7(){if(f3.state.focused){setTimeout(cu(eq,f3),0)}}bV(f5.scrollbarH,"mousedown",f7);bV(f5.scrollbarV,"mousedown",f7);bV(f5.wrapper,"scroll",function(){f5.wrapper.scrollTop=f5.wrapper.scrollLeft=0});bV(f5.input,"keyup",function(f8){bd.call(f3,f8)});bV(f5.input,"input",function(){if(dA&&l>=9&&f3.display.inputHasSelection){f3.display.inputHasSelection=null}C(f3)});bV(f5.input,"keydown",cX(f3,q));bV(f5.input,"keypress",cX(f3,cw));bV(f5.input,"focus",cu(cz,f3));bV(f5.input,"blur",cu(aQ,f3));function f4(f8){if(!aN(f3,f8)){eh(f8)}}if(f3.options.dragDrop){bV(f5.scroller,"dragstart",function(f8){R(f3,f8)});bV(f5.scroller,"dragenter",f4);bV(f5.scroller,"dragover",f4);bV(f5.scroller,"drop",cX(f3,bf))}bV(f5.scroller,"paste",function(f8){if(a5(f5,f8)){return}f3.state.pasteIncoming=true;eq(f3);C(f3)});bV(f5.input,"paste",function(){if(cV&&!f3.state.fakedLastChar&&!(new Date-f3.state.lastMiddleDown<200)){var f9=f5.input.selectionStart,f8=f5.input.selectionEnd;f5.input.value+="$";f5.input.selectionEnd=f8;f5.input.selectionStart=f9;f3.state.fakedLastChar=true}f3.state.pasteIncoming=true;C(f3)});function f6(gc){if(f3.somethingSelected()){bi=f3.getSelections();if(f5.inaccurateSelection){f5.prevInput="";f5.inaccurateSelection=false;f5.input.value=bi.join("\n");dB(f5.input)}}else{var gd=[],f9=[];for(var ga=0;gaf5-400&&cd(c8.pos,f9)==0){f6="triple"}else{if(df&&df.time>f5-400&&cd(df.pos,f9)==0){f6="double";c8={time:f5,pos:f9}}else{f6="single";df={time:f5,pos:f9}}}var f7=f4.doc.sel,f3=b5?f8.metaKey:f8.ctrlKey;if(f4.options.dragDrop&&eC&&!ai(f4)&&f6=="single"&&f7.contains(f9)>-1&&f7.somethingSelected()){aY(f4,f8,f9,f3)}else{n(f4,f8,f9,f6,f3)}}function aY(f5,f7,f8,f4){var f6=f5.display;var f3=cX(f5,function(f9){if(cV){f6.scroller.draggable=false}f5.state.draggingText=false;d3(document,"mouseup",f3);d3(f6.scroller,"drop",f3);if(Math.abs(f7.clientX-f9.clientX)+Math.abs(f7.clientY-f9.clientY)<10){cD(f9);if(!f4){fK(f5.doc,f8)}eq(f5);if(dA&&l==9){setTimeout(function(){document.body.focus();eq(f5)},20)}}});if(cV){f6.scroller.draggable=true}f5.state.draggingText=f3;if(f6.scroller.dragDrop){f6.scroller.dragDrop()}bV(document,"mouseup",f3);bV(f6.scroller,"drop",f3)}function n(f6,gk,f5,f3,f8){var gh=f6.display,gm=f6.doc;cD(gk);var f4,gl,f7=gm.sel;if(f8&&!gk.shiftKey){gl=gm.sel.contains(f5);if(gl>-1){f4=gm.sel.ranges[gl]}else{f4=new dO(f5,f5)}}else{f4=gm.sel.primary()}if(gk.altKey){f3="rect";if(!f8){f4=new dO(f5,f5)}f5=cm(f6,gk,true,true);gl=-1}else{if(f3=="double"){var gi=f6.findWordAt(f5);if(f6.display.shift||gm.extend){f4=fm(gm,f4,gi.anchor,gi.head)}else{f4=gi}}else{if(f3=="triple"){var gb=new dO(X(f5.line,0),fA(gm,X(f5.line+1,0)));if(f6.display.shift||gm.extend){f4=fm(gm,f4,gb.anchor,gb.head)}else{f4=gb}}else{f4=fm(gm,f4,f5)}}}if(!f8){gl=0;bS(gm,new fO([f4],0),N);f7=gm.sel}else{if(gl>-1){e(gm,gl,f4,N)}else{gl=gm.sel.ranges.length;bS(gm,cv(gm.sel.ranges.concat([f4]),gl),{scroll:false,origin:"*mouse"})}}var gg=f5;function gf(gx){if(cd(gg,gx)==0){return}gg=gx;if(f3=="rect"){var go=[],gu=f6.options.tabSize;var gn=bR(e5(gm,f5.line).text,f5.ch,gu);var gA=bR(e5(gm,gx.line).text,gx.ch,gu);var gp=Math.min(gn,gA),gy=Math.max(gn,gA);for(var gB=Math.min(f5.line,gx.line),gr=Math.min(f6.lastLine(),Math.max(f5.line,gx.line));gB<=gr;gB++){var gz=e5(gm,gB).text,gq=eg(gz,gp,gu);if(gp==gy){go.push(new dO(X(gB,gq),X(gB,gq)))}else{if(gz.length>gq){go.push(new dO(X(gB,gq),X(gB,eg(gz,gy,gu))))}}}if(!go.length){go.push(new dO(f5,f5))}bS(gm,cv(f7.ranges.slice(0,gl).concat(go),gl),{origin:"*mouse",scroll:false});f6.scrollIntoView(gx)}else{var gv=f4;var gs=gv.anchor,gw=gx;if(f3!="single"){if(f3=="double"){var gt=f6.findWordAt(gx)}else{var gt=new dO(X(gx.line,0),fA(gm,X(gx.line+1,0)))}if(cd(gt.anchor,gs)>0){gw=gt.head;gs=aq(gv.from(),gt.anchor)}else{gw=gt.anchor;gs=bv(gv.to(),gt.head)}}var go=f7.ranges.slice(0);go[gl]=new dO(fA(gm,gs),gw);bS(gm,cv(go,gl),N)}}var gd=gh.wrapper.getBoundingClientRect();var f9=0;function gj(gp){var gn=++f9;var gr=cm(f6,gp,true,f3=="rect");if(!gr){return}if(cd(gr,gg)!=0){s(f6);gf(gr);var gq=b4(gh,gm);if(gr.line>=gq.to||gr.linegd.bottom?20:0;if(go){setTimeout(cX(f6,function(){if(f9!=gn){return}gh.scroller.scrollTop+=go;gj(gp)}),50)}}}function gc(gn){f9=Infinity;cD(gn);eq(f6);d3(document,"mousemove",ge);d3(document,"mouseup",ga);gm.history.lastSelOrigin=null}var ge=cX(f6,function(gn){if(!fE(gn)){gc(gn)}else{gj(gn)}});var ga=cX(f6,gc);bV(document,"mousemove",ge);bV(document,"mouseup",ga)}function f1(ge,ga,gc,gd,f6){try{var f4=ga.clientX,f3=ga.clientY}catch(ga){return false}if(f4>=Math.floor(ge.display.gutters.getBoundingClientRect().right)){return false}if(gd){cD(ga)}var gb=ge.display;var f9=gb.lineDiv.getBoundingClientRect();if(f3>f9.bottom||!e8(ge,gc)){return bJ(ga)}f3-=f9.top-gb.viewOffset;for(var f7=0;f7=f4){var gf=bE(ge.doc,f3);var f5=ge.options.gutters[f7];f6(ge,gc,ge,gf,f5,ga);return bJ(ga)}}}function m(f3,f4){return f1(f3,f4,"gutterClick",true,ad)}var af=0;function bf(f9){var gb=this;if(aN(gb,f9)||a5(gb.display,f9)){return}cD(f9);if(dA){af=+new Date}var ga=cm(gb,f9,true),f3=f9.dataTransfer.files;if(!ga||ai(gb)){return}if(f3&&f3.length&&window.FileReader&&window.File){var f5=f3.length,gc=Array(f5),f4=0;var f7=function(gf,ge){var gd=new FileReader;gd.onload=cX(gb,function(){gc[ge]=gd.result;if(++f4==f5){ga=fA(gb.doc,ga);var gg={from:ga,to:ga,text:aV(gc.join("\n")),origin:"paste"};bb(gb.doc,gg);eX(gb.doc,eJ(ga,cS(gg)))}});gd.readAsText(gf)};for(var f8=0;f8-1){gb.state.draggingText(f9);setTimeout(cu(eq,gb),20);return}try{var gc=f9.dataTransfer.getData("Text");if(gc){if(gb.state.draggingText&&!(b5?f9.metaKey:f9.ctrlKey)){var f6=gb.listSelections()}ef(gb.doc,eJ(ga,ga));if(f6){for(var f8=0;f8ga.clientWidth||gd&&ga.scrollHeight>ga.clientHeight)){return}if(gd&&b5&&cV){outer:for(var gc=f5.target,f9=f7.view;gc!=ga;gc=gc.parentNode){for(var f4=0;f4=9){f3.display.inputHasSelection=null}C(f3)}function cz(f3){if(f3.options.readOnly=="nocursor"){return}if(!f3.state.focused){aB(f3,"focus",f3);f3.state.focused=true;fr(f3.display.wrapper,"CodeMirror-focused");if(!f3.curOp&&f3.display.selForContextMenu!=f3.doc.sel){ff(f3);if(cV){setTimeout(cu(ff,f3,true),0)}}}bk(f3);p(f3)}function aQ(f3){if(f3.state.focused){aB(f3,"blur",f3);f3.state.focused=false;f(f3.display.wrapper,"CodeMirror-focused")}clearInterval(f3.display.blinker);setTimeout(function(){if(!f3.state.focused){f3.display.shift=false}},150)}function ax(gc,f7){if(aN(gc,f7,"contextmenu")){return}var f9=gc.display;if(a5(f9,f7)||db(gc,f7)){return}var gb=cm(gc,f7),f3=f9.scroller.scrollTop;if(!gb||dS){return}var f6=gc.options.resetSelectionOnContextMenu;if(f6&&gc.doc.sel.contains(gb)==-1){cX(gc,bS)(gc.doc,eJ(gb),Z)}var f8=f9.input.style.cssText;f9.inputDiv.style.position="absolute";f9.input.style.cssText="position: fixed; width: 30px; height: 30px; top: "+(f7.clientY-5)+"px; left: "+(f7.clientX-5)+"px; z-index: 1000; background: "+(dA?"rgba(255, 255, 255, .05)":"transparent")+"; outline: none; border-width: 0; outline: none; overflow: hidden; opacity: .05; filter: alpha(opacity=5);";if(cV){var gd=window.scrollY}eq(gc);if(cV){window.scrollTo(null,gd)}ff(gc);if(!gc.somethingSelected()){f9.input.value=f9.prevInput=" "}f9.selForContextMenu=gc.doc.sel;clearTimeout(f9.detectingSelectAll);function f5(){if(f9.input.selectionStart!=null){var ge=gc.somethingSelected();var gf=f9.input.value="\u200b"+(ge?f9.input.value:"");f9.prevInput=ge?"":"\u200b";f9.input.selectionStart=1;f9.input.selectionEnd=gf.length;f9.selForContextMenu=gc.doc.sel}}function ga(){f9.inputDiv.style.position="relative";f9.input.style.cssText=f8;if(dA&&l<9){f9.scrollbarV.scrollTop=f9.scroller.scrollTop=f3}bk(gc);if(f9.input.selectionStart!=null){if(!dA||(dA&&l<9)){f5()}var ge=0,gf=function(){if(f9.selForContextMenu==gc.doc.sel&&f9.input.selectionStart==0){cX(gc,eu.selectAll)(gc)}else{if(ge++<10){f9.detectingSelectAll=setTimeout(gf,500)}else{ff(gc)}}};f9.detectingSelectAll=setTimeout(gf,200)}}if(dA&&l>=9){f5()}if(fV){eh(f7);var f4=function(){d3(window,"mouseup",f4);setTimeout(ga,20)};bV(window,"mouseup",f4)}else{setTimeout(ga,50)}}function db(f3,f4){if(!e8(f3,"gutterContextMenu")){return false}return f1(f3,f4,"gutterContextMenu",false,aB)}var cS=J.changeEnd=function(f3){if(!f3.text){return f3.to}return X(f3.from.line+f3.text.length-1,fy(f3.text).length+(f3.text.length==1?f3.from.ch:0))};function bX(f6,f5){if(cd(f6,f5.from)<0){return f6}if(cd(f6,f5.to)<=0){return cS(f5)}var f3=f6.line+f5.text.length-(f5.to.line-f5.from.line)-1,f4=f6.ch;if(f6.line==f5.to.line){f4+=cS(f5).ch-f5.to.ch}return X(f3,f4)}function fa(f6,f7){var f4=[];for(var f5=0;f5=0;--f3){L(f6,{from:f4[f3].from,to:f4[f3].to,text:f3?[""]:f7.text})}}else{L(f6,f7)}}function L(f5,f6){if(f6.text.length==1&&f6.text[0]==""&&cd(f6.from,f6.to)==0){return}var f4=fa(f5,f6);fD(f5,f6,f4,f5.cm?f5.cm.curOp.id:NaN);d4(f5,f6,f4,ea(f5,f6));var f3=[];dX(f5,function(f8,f7){if(!f7&&dc(f3,f8.history)==-1){dv(f8.history,f6);f3.push(f8.history)}d4(f8,f6,null,ea(f8,f6))})}function b6(ge,gc,gg){if(ge.cm&&ge.cm.state.suppressEdits){return}var gb=ge.history,f5,f7=ge.sel;var f3=gc=="undo"?gb.done:gb.undone,gf=gc=="undo"?gb.undone:gb.done;for(var f8=0;f8=0;--f8){var gd=f5.changes[f8];gd.origin=gc;if(f6&&!dH(ge,gd,false)){f3.length=0;return}ga.push(dl(ge,gd));var f4=f8?fa(ge,gd):fy(f3);d4(ge,gd,f4,dZ(ge,gd));if(!f8&&ge.cm){ge.cm.scrollIntoView({from:gd.from,to:cS(gd)})}var f9=[];dX(ge,function(gi,gh){if(!gh&&dc(f9,gi.history)==-1){dv(gi.history,gd);f9.push(gi.history)}d4(gi,gd,null,dZ(gi,gd))})}}function fd(f4,f6){if(f6==0){return}f4.first+=f6;f4.sel=new fO(bQ(f4.sel.ranges,function(f7){return new dO(X(f7.anchor.line+f6,f7.anchor.ch),X(f7.head.line+f6,f7.head.ch))}),f4.sel.primIndex);if(f4.cm){ag(f4.cm,f4.first,f4.first-f6,f6);for(var f5=f4.cm.display,f3=f5.viewFrom;f3f7.lastLine()){return}if(f8.from.linef5){f8={from:f8.from,to:X(f5,e5(f7,f5).text.length),text:[f8.text[0]],origin:f8.origin}}f8.removed=fP(f7,f8.from,f8.to);if(!f6){f6=fa(f7,f8)}if(f7.cm){aG(f7.cm,f8,f4)}else{fp(f7,f8,f4)}ef(f7,f6,Z)}function aG(ge,ga,f8){var gd=ge.doc,f9=ge.display,gb=ga.from,gc=ga.to;var f3=false,f7=gb.line;if(!ge.options.lineWrapping){f7=bL(z(e5(gd,gb.line)));gd.iter(f7,gc.line+1,function(gg){if(gg==f9.maxLine){f3=true;return true}})}if(gd.sel.contains(ga.from,ga.to)>-1){W(ge)}fp(gd,ga,f8,a9(ge));if(!ge.options.lineWrapping){gd.iter(f7,gb.line+ga.text.length,function(gh){var gg=ec(gh);if(gg>f9.maxLineLength){f9.maxLine=gh;f9.maxLineLength=gg;f9.maxLineChanged=true;f3=false}});if(f3){ge.curOp.updateMaxLine=true}}gd.frontier=Math.min(gd.frontier,gb.line);d5(ge,400);var gf=ga.text.length-(gc.line-gb.line)-1;if(gb.line==gc.line&&ga.text.length==1&&!dI(ge.doc,ga)){S(ge,gb.line,"text")}else{ag(ge,gb.line,gc.line+1,gf)}var f5=e8(ge,"changes"),f6=e8(ge,"change");if(f6||f5){var f4={from:gb,to:gc,text:ga.text,removed:ga.removed,origin:ga.origin};if(f6){ad(ge,"change",ge,f4)}if(f5){(ge.curOp.changeObjs||(ge.curOp.changeObjs=[])).push(f4)}}ge.display.selForContextMenu=null}function aW(f6,f5,f8,f7,f3){if(!f7){f7=f8}if(cd(f7,f8)<0){var f4=f7;f7=f8;f8=f4}if(typeof f5=="string"){f5=aV(f5)}bb(f6,{from:f8,to:f7,text:f5,origin:f3})}function dW(f4,f7){if(aN(f4,"scrollCursorIntoView")){return}var f8=f4.display,f5=f8.sizer.getBoundingClientRect(),f3=null;if(f7.top+f5.top<0){f3=true}else{if(f7.bottom+f5.top>(window.innerHeight||document.documentElement.clientHeight)){f3=false}}if(f3!=null&&!fl){var f6=fN("div","\u200b",null,"position: absolute; top: "+(f7.top-f8.viewOffset-eY(f4.display))+"px; height: "+(f7.bottom-f7.top+bg)+"px; left: "+f7.left+"px; width: 2px;");f4.display.lineSpace.appendChild(f6);f6.scrollIntoView(f3);f4.display.lineSpace.removeChild(f6)}}function F(gd,gb,f7,f6){if(f6==null){f6=0}for(var f8=0;f8<5;f8++){var f9=false,gc=dK(gd,gb);var f3=!f7||f7==gb?gc:dK(gd,f7);var f5=I(gd,Math.min(gc.left,f3.left),Math.min(gc.top,f3.top)-f6,Math.max(gc.left,f3.left),Math.max(gc.bottom,f3.bottom)+f6);var ga=gd.doc.scrollTop,f4=gd.doc.scrollLeft;if(f5.scrollTop!=null){O(gd,f5.scrollTop);if(Math.abs(gd.doc.scrollTop-ga)>1){f9=true}}if(f5.scrollLeft!=null){bC(gd,f5.scrollLeft);if(Math.abs(gd.doc.scrollLeft-f4)>1){f9=true}}if(!f9){return gc}}}function G(f3,f5,f7,f4,f6){var f8=I(f3,f5,f7,f4,f6);if(f8.scrollTop!=null){O(f3,f8.scrollTop)}if(f8.scrollLeft!=null){bC(f3,f8.scrollLeft)}}function I(gf,f6,ge,f4,gd){var gb=gf.display,f9=aS(gf.display);if(ge<0){ge=0}var f7=gf.curOp&&gf.curOp.scrollTop!=null?gf.curOp.scrollTop:gb.scroller.scrollTop;var gh=gb.scroller.clientHeight-bg,gj={};if(gd-ge>gh){gd=ge+gh}var f5=gf.doc.height+bG(gb);var f3=gef5-f9;if(gef7+gh){var gc=Math.min(ge,(ga?f5:gd)-gh);if(gc!=f7){gj.scrollTop=gc}}}var gi=gf.curOp&&gf.curOp.scrollLeft!=null?gf.curOp.scrollLeft:gb.scroller.scrollLeft;var gg=gb.scroller.clientWidth-bg-gb.gutters.offsetWidth;var f8=f4-f6>gg;if(f8){f4=f6+gg}if(f6<10){gj.scrollLeft=0}else{if(f6gg+gi-3){gj.scrollLeft=f4+(f8?0:10)-gg}}}return gj}function cI(f3,f5,f4){if(f5!=null||f4!=null){ft(f3)}if(f5!=null){f3.curOp.scrollLeft=(f3.curOp.scrollLeft==null?f3.doc.scrollLeft:f3.curOp.scrollLeft)+f5}if(f4!=null){f3.curOp.scrollTop=(f3.curOp.scrollTop==null?f3.doc.scrollTop:f3.curOp.scrollTop)+f4}}function fx(f3){ft(f3);var f4=f3.getCursor(),f6=f4,f5=f4;if(!f3.options.lineWrapping){f6=f4.ch?X(f4.line,f4.ch-1):f4;f5=X(f4.line,f4.ch+1)}f3.curOp.scrollToPos={from:f6,to:f5,margin:f3.options.cursorScrollMargin,isCursor:true}}function ft(f3){var f5=f3.curOp.scrollToPos;if(f5){f3.curOp.scrollToPos=null;var f7=dy(f3,f5.from),f6=dy(f3,f5.to);var f4=I(f3,Math.min(f7.left,f6.left),Math.min(f7.top,f6.top)-f5.margin,Math.max(f7.right,f6.right),Math.max(f7.bottom,f6.bottom)+f5.margin);f3.scrollTo(f4.scrollLeft,f4.scrollTop)}}function ac(gg,f6,gf,f5){var ge=gg.doc,f4;if(gf==null){gf="add"}if(gf=="smart"){if(!ge.mode.indent){gf="prev"}else{f4=ds(gg,f6)}}var ga=gg.options.tabSize;var gh=e5(ge,f6),f9=bR(gh.text,null,ga);if(gh.stateAfter){gh.stateAfter=null}var f3=gh.text.match(/^\s*/)[0],gc;if(!f5&&!/\S/.test(gh.text)){gc=0;gf="not"}else{if(gf=="smart"){gc=ge.mode.indent(f4,gh.text.slice(f3.length),gh.text);if(gc==b8||gc>150){if(!f5){return}gf="prev"}}}if(gf=="prev"){if(f6>ge.first){gc=bR(e5(ge,f6-1).text,null,ga)}else{gc=0}}else{if(gf=="add"){gc=f9+gg.options.indentUnit}else{if(gf=="subtract"){gc=f9-gg.options.indentUnit}else{if(typeof gf=="number"){gc=f9+gf}}}}gc=Math.max(0,gc);var gd="",gb=0;if(gg.options.indentWithTabs){for(var f7=Math.floor(gc/ga);f7;--f7){gb+=ga;gd+="\t"}}if(gb=0;ga--){aW(f3.doc,"",f7[ga].from,f7[ga].to,"+delete")}fx(f3)})}function bu(gl,f7,gf,ge,f9){var gc=f7.line,gd=f7.ch,gk=gf;var f4=e5(gl,gc);var gi=true;function gj(){var gm=gc+gf;if(gm=gl.first+gl.size){return(gi=false)}gc=gm;return f4=e5(gl,gm)}function gh(gn){var gm=(f9?v:ah)(f4,gd,gf,true);if(gm==null){if(!gn&&gj()){if(f9){gd=(gf<0?cP:cC)(f4)}else{gd=gf<0?f4.text.length:0}}else{return(gi=false)}}else{gd=gm}return true}if(ge=="char"){gh()}else{if(ge=="column"){gh(true)}else{if(ge=="word"||ge=="group"){var gg=null,ga=ge=="group";var f3=gl.cm&&gl.cm.getHelper(f7,"wordChars");for(var f8=true;;f8=false){if(gf<0&&!gh(!f8)){break}var f5=f4.text.charAt(gd)||"\n";var f6=cy(f5,f3)?"w":ga&&f5=="\n"?"n":!ga||/\s/.test(f5)?null:"p";if(ga&&!f8&&!f6){f6="s"}if(gg&&gg!=f6){if(gf<0){gf=1;gh()}break}if(f6){gg=f6}if(gf>0&&!gh(!f8)){break}}}}}var gb=bT(gl,X(gc,gd),gk,true);if(!gi){gb.hitSide=true}return gb}function bo(gb,f6,f3,ga){var f9=gb.doc,f8=f6.left,f7;if(ga=="page"){var f5=Math.min(gb.display.wrapper.clientHeight,window.innerHeight||document.documentElement.clientHeight);f7=f6.top+f3*(f5-(f3<0?1.5:0.5)*aS(gb.display))}else{if(ga=="line"){f7=f3>0?f6.bottom+3:f6.top-3}}for(;;){var f4=fF(gb,f8,f7);if(!f4.outside){break}if(f3<0?f7<=0:f7>=f9.height){f4.hitSide=true;break}f7+=f3*5}return f4}J.prototype={constructor:J,focus:function(){window.focus();eq(this);C(this)},setOption:function(f5,f6){var f4=this.options,f3=f4[f5];if(f4[f5]==f6&&f5!="mode"){return}f4[f5]=f6;if(ba.hasOwnProperty(f5)){cX(this,ba[f5])(this,f6,f3)}},getOption:function(f3){return this.options[f3]},getDoc:function(){return this.doc},addKeyMap:function(f4,f3){this.state.keyMaps[f3?"push":"unshift"](fL(f4))},removeKeyMap:function(f4){var f5=this.state.keyMaps;for(var f3=0;f30){e(this.doc,f8,new dO(ga,f5[f8].to()),Z)}}else{if(f9.head.line>f6){ac(this,f9.head.line,gc,true);f6=f9.head.line;if(f8==this.doc.sel.primIndex){fx(this)}}}}}),getTokenAt:function(f4,f3){return cp(this,f4,f3)},getLineTokens:function(f4,f3){return cp(this,X(f4),f3,true)},getTokenTypeAt:function(ga){ga=fA(this.doc,ga);var f6=c1(this,e5(this.doc,ga.line));var f8=0,f9=(f6.length-1)/2,f5=ga.ch;var f4;if(f5==0){f4=f6[2]}else{for(;;){var f3=(f8+f9)>>1;if((f3?f6[f3*2-1]:0)>=f5){f9=f3}else{if(f6[f3*2+1]f6){f4=f6;f3=true}}var f5=e5(this.doc,f4);return eH(this,f5,{top:0,left:0},f7||"page").top+(f3?this.doc.height-bK(f5):0)},defaultTextHeight:function(){return aS(this.display)},defaultCharWidth:function(){return du(this.display)},setGutterMarker:c3(function(f3,f4,f5){return ep(this.doc,f3,"gutter",function(f6){var f7=f6.gutterMarkers||(f6.gutterMarkers={});f7[f4]=f5;if(!f5&&eL(f7)){f6.gutterMarkers=null}return true})}),clearGutter:c3(function(f5){var f3=this,f6=f3.doc,f4=f6.first;f6.iter(function(f7){if(f7.gutterMarkers&&f7.gutterMarkers[f5]){f7.gutterMarkers[f5]=null;S(f3,f4,"gutter");if(eL(f7.gutterMarkers)){f7.gutterMarkers=null}}++f4})}),addLineWidget:c3(function(f5,f4,f3){return bF(this,f5,f4,f3)}),removeLineWidget:function(f3){f3.clear()},lineInfo:function(f3){if(typeof f3=="number"){if(!b7(this.doc,f3)){return null}var f4=f3;f3=e5(this.doc,f3);if(!f3){return null}}else{var f4=bL(f3);if(f4==null){return null}}return{line:f4,handle:f3,text:f3.text,gutterMarkers:f3.gutterMarkers,textClass:f3.textClass,bgClass:f3.bgClass,wrapClass:f3.wrapClass,widgets:f3.widgets}},getViewport:function(){return{from:this.display.viewFrom,to:this.display.viewTo}},addWidget:function(f8,f5,ga,f6,gc){var f7=this.display;f8=dK(this,fA(this.doc,f8));var f9=f8.bottom,f4=f8.left;f5.style.position="absolute";f7.sizer.appendChild(f5);if(f6=="over"){f9=f8.top}else{if(f6=="above"||f6=="near"){var f3=Math.max(f7.wrapper.clientHeight,this.doc.height),gb=Math.max(f7.sizer.clientWidth,f7.lineSpace.clientWidth);if((f6=="above"||f8.bottom+f5.offsetHeight>f3)&&f8.top>f5.offsetHeight){f9=f8.top-f5.offsetHeight}else{if(f8.bottom+f5.offsetHeight<=f3){f9=f8.bottom}}if(f4+f5.offsetWidth>gb){f4=gb-f5.offsetWidth}}}f5.style.top=f9+"px";f5.style.left=f5.style.right="";if(gc=="right"){f4=f7.sizer.clientWidth-f5.offsetWidth;f5.style.right="0px"}else{if(gc=="left"){f4=0}else{if(gc=="middle"){f4=(f7.sizer.clientWidth-f5.offsetWidth)/2}}f5.style.left=f4+"px"}if(ga){G(this,f4,f9,f4+f5.offsetWidth,f9+f5.offsetHeight)}},triggerOnKeyDown:c3(q),triggerOnKeyPress:c3(cw),triggerOnKeyUp:bd,execCommand:function(f3){if(eu.hasOwnProperty(f3)){return eu[f3](this)}},findPosH:function(f9,f6,f7,f4){var f3=1;if(f6<0){f3=-1;f6=-f6}for(var f5=0,f8=fA(this.doc,f9);f50&&f3(f6.charAt(f9-1))){--f9}while(f50.5){Y(this)}aB(this,"refresh",this)}),swapDoc:c3(function(f4){var f3=this.doc;f3.cm=null;d1(this,f4);aj(this);ff(this);this.scrollTo(f4.scrollLeft,f4.scrollTop);this.curOp.forceScroll=true;ad(this,"swapDoc",this,f3);return f3}),getInputField:function(){return this.display.input},getWrapperElement:function(){return this.display.wrapper},getScrollerElement:function(){return this.display.scroller},getGutterElement:function(){return this.display.gutters}};bw(J);var eU=J.defaults={};var ba=J.optionHandlers={};function t(f3,f6,f5,f4){J.defaults[f3]=f6;if(f5){ba[f3]=f4?function(f7,f9,f8){if(f8!=ca){f5(f7,f9,f8)}}:f5}}var ca=J.Init={toString:function(){return"CodeMirror.Init"}};t("value","",function(f3,f4){f3.setValue(f4)},true);t("mode",null,function(f3,f4){f3.doc.modeOption=f4;bp(f3)},true);t("indentUnit",2,bp,true);t("indentWithTabs",false);t("smartIndent",true);t("tabSize",4,function(f3){eb(f3);aj(f3);ag(f3)},true);t("specialChars",/[\t\u0000-\u0019\u00ad\u200b-\u200f\u2028\u2029\ufeff]/g,function(f3,f4){f3.options.specialChars=new RegExp(f4.source+(f4.test("\t")?"":"|\t"),"g");f3.refresh()},true);t("specialCharPlaceholder",e2,function(f3){f3.refresh()},true);t("electricChars",true);t("rtlMoveVisually",!aL);t("wholeLineUpdateBefore",true);t("theme","default",function(f3){cL(f3);dm(f3)},true);t("keyMap","default",function(f3,f7,f4){var f5=fL(f7);var f6=f4!=J.Init&&fL(f4);if(f6&&f6.detach){f6.detach(f3,f5)}if(f5.attach){f5.attach(f3,f6||null)}});t("extraKeys",null);t("lineWrapping",false,ex,true);t("gutters",[],function(f3){cc(f3.options);dm(f3)},true);t("fixedGutter",true,function(f3,f4){f3.display.gutters.style.left=f4?dN(f3.display)+"px":"0";f3.refresh()},true);t("coverGutterNextToScrollbar",false,eP,true);t("lineNumbers",false,function(f3){cc(f3.options);dm(f3)},true);t("firstLineNumber",1,dm,true);t("lineNumberFormatter",function(f3){return f3},dm,true);t("showCursorWhenSelecting",false,bA,true);t("resetSelectionOnContextMenu",true);t("readOnly",false,function(f3,f4){if(f4=="nocursor"){aQ(f3);f3.display.input.blur();f3.display.disabled=true}else{f3.display.disabled=false;if(!f4){ff(f3)}}});t("disableInput",false,function(f3,f4){if(!f4){ff(f3)}},true);t("dragDrop",true);t("cursorBlinkRate",530);t("cursorScrollMargin",0);t("cursorHeight",1,bA,true);t("singleCursorHeightPerLine",true,bA,true);t("workTime",100);t("workDelay",100);t("flattenSpans",true,eb,true);t("addModeClass",false,eb,true);t("pollInterval",100);t("undoDepth",200,function(f3,f4){f3.doc.history.undoDepth=f4});t("historyEventDelay",1250);t("viewportMargin",10,function(f3){f3.refresh()},true);t("maxHighlightLength",10000,eb,true);t("moveInputWithCursor",true,function(f3,f4){if(!f4){f3.display.inputDiv.style.top=f3.display.inputDiv.style.left=0}});t("tabindex",null,function(f3,f4){f3.display.input.tabIndex=f4||""});t("autofocus",null);var dj=J.modes={},aO=J.mimeModes={};J.defineMode=function(f3,f4){if(!J.defaults.mode&&f3!="null"){J.defaults.mode=f3}if(arguments.length>2){f4.dependencies=Array.prototype.slice.call(arguments,2)}dj[f3]=f4};J.defineMIME=function(f4,f3){aO[f4]=f3};J.resolveMode=function(f3){if(typeof f3=="string"&&aO.hasOwnProperty(f3)){f3=aO[f3]}else{if(f3&&typeof f3.name=="string"&&aO.hasOwnProperty(f3.name)){var f4=aO[f3.name];if(typeof f4=="string"){f4={name:f4}}f3=cj(f4,f3);f3.name=f4.name}else{if(typeof f3=="string"&&/^[\w\-]+\/[\w\-]+\+xml$/.test(f3)){return J.resolveMode("application/xml")}}}if(typeof f3=="string"){return{name:f3}}else{return f3||{name:"null"}}};J.getMode=function(f4,f3){var f3=J.resolveMode(f3);var f6=dj[f3.name];if(!f6){return J.getMode(f4,"text/plain")}var f7=f6(f4,f3);if(dg.hasOwnProperty(f3.name)){var f5=dg[f3.name];for(var f8 in f5){if(!f5.hasOwnProperty(f8)){continue}if(f7.hasOwnProperty(f8)){f7["_"+f8]=f7[f8]}f7[f8]=f5[f8]}}f7.name=f3.name;if(f3.helperType){f7.helperType=f3.helperType}if(f3.modeProps){for(var f8 in f3.modeProps){f7[f8]=f3.modeProps[f8]}}return f7};J.defineMode("null",function(){return{token:function(f3){f3.skipToEnd()}}});J.defineMIME("text/plain","null");var dg=J.modeExtensions={};J.extendMode=function(f5,f4){var f3=dg.hasOwnProperty(f5)?dg[f5]:(dg[f5]={});aJ(f4,f3)};J.defineExtension=function(f3,f4){J.prototype[f3]=f4};J.defineDocExtension=function(f3,f4){ar.prototype[f3]=f4};J.defineOption=t;var a3=[];J.defineInitHook=function(f3){a3.push(f3)};var fe=J.helpers={};J.registerHelper=function(f4,f3,f5){if(!fe.hasOwnProperty(f4)){fe[f4]=J[f4]={_global:[]}}fe[f4][f3]=f5};J.registerGlobalHelper=function(f5,f4,f3,f6){J.registerHelper(f5,f4,f6);fe[f5]._global.push({pred:f3,val:f6})};var b1=J.copyState=function(f6,f3){if(f3===true){return f3}if(f6.copyState){return f6.copyState(f3)}var f5={};for(var f7 in f3){var f4=f3[f7];if(f4 instanceof Array){f4=f4.concat([])}f5[f7]=f4}return f5};var bY=J.startState=function(f5,f4,f3){return f5.startState?f5.startState(f4,f3):true};J.innerMode=function(f5,f3){while(f5.innerMode){var f4=f5.innerMode(f3);if(!f4||f4.mode==f5){break}f3=f4.state;f5=f4.mode}return f4||{mode:f5,state:f3}};var eu=J.commands={selectAll:function(f3){f3.setSelection(X(f3.firstLine(),0),X(f3.lastLine()),Z)},singleSelection:function(f3){f3.setSelection(f3.getCursor("anchor"),f3.getCursor("head"),Z)},killLine:function(f3){eO(f3,function(f5){if(f5.empty()){var f4=e5(f3.doc,f5.head.line).text.length;if(f5.head.ch==f4&&f5.head.line0){f9=new X(f9.line,f9.ch+1);f3.replaceRange(f4.charAt(f9.ch-1)+f4.charAt(f9.ch-2),X(f9.line,f9.ch-2),f9,"+transpose")}else{if(f9.line>f3.doc.first){var f8=e5(f3.doc,f9.line-1).text;if(f8){f3.replaceRange(f4.charAt(0)+"\n"+f8.charAt(f8.length-1),X(f9.line-1,f8.length-1),X(f9.line,1),"+transpose")}}}}f5.push(new dO(f9,f9))}f3.setSelections(f5)})},newlineAndIndent:function(f3){cJ(f3,function(){var f4=f3.listSelections().length;for(var f6=0;f6=this.string.length},sol:function(){return this.pos==this.lineStart},peek:function(){return this.string.charAt(this.pos)||undefined},next:function(){if(this.posf4},eatSpace:function(){var f3=this.pos;while(/[\s\u00a0]/.test(this.string.charAt(this.pos))){++this.pos}return this.pos>f3},skipToEnd:function(){this.pos=this.string.length},skipTo:function(f3){var f4=this.string.indexOf(f3,this.pos);if(f4>-1){this.pos=f4;return true}},backUp:function(f3){this.pos-=f3},column:function(){if(this.lastColumnPos0){return null}if(f5&&f4!==false){this.pos+=f5[0].length}return f5}},current:function(){return this.string.slice(this.start,this.pos)},hideFirstChars:function(f4,f3){this.lineStart+=f4;try{return f3()}finally{this.lineStart-=f4}}};var Q=J.TextMarker=function(f4,f3){this.lines=[];this.type=f3;this.doc=f4};bw(Q);Q.prototype.clear=function(){if(this.explicitlyCleared){return}var ga=this.doc.cm,f4=ga&&!ga.curOp;if(f4){cF(ga)}if(e8(this,"clear")){var gb=this.find();if(gb){ad(this,"clear",gb.from,gb.to)}}var f5=null,f8=null;for(var f6=0;f6ga.display.maxLineLength){ga.display.maxLine=f3;ga.display.maxLineLength=f7;ga.display.maxLineChanged=true}}}if(f5!=null&&ga&&this.collapsed){ag(ga,f5,f8+1)}this.lines.length=0;this.explicitlyCleared=true;if(this.atomic&&this.doc.cantEdit){this.doc.cantEdit=false;if(ga){eo(ga.doc)}}if(ga){ad(ga,"markerCleared",ga,this)}if(f4){al(ga)}if(this.parent){this.parent.clear()}};Q.prototype.find=function(f6,f4){if(f6==null&&this.type=="bookmark"){f6=1}var f9,f8;for(var f5=0;f50||gc==0&&f6.clearWhenEmpty!==false){return f6}if(f6.replacedWith){f6.collapsed=true;f6.widgetNode=fN("span",[f6.replacedWith],"CodeMirror-widget");if(!gd.handleMouseEvents){f6.widgetNode.ignoreEvents=true}if(gd.insertLeft){f6.widgetNode.insertLeft=true}}if(f6.collapsed){if(A(gb,f9.line,f9,ga,f6)||f9.line!=ga.line&&A(gb,ga.line,f9,ga,f6)){throw new Error("Inserting collapsed marker partially overlapping an existing one")}a2=true}if(f6.addToHistory){fD(gb,{from:f9,to:ga,origin:"markText"},gb.sel,NaN)}var f4=f9.line,f8=gb.cm,f3;gb.iter(f4,ga.line+1,function(ge){if(f8&&f6.collapsed&&!f8.options.lineWrapping&&z(ge)==f8.display.maxLine){f3=true}if(f6.collapsed&&f4!=f9.line){fR(ge,0)}cb(ge,new d8(f6,f4==f9.line?f9.ch:null,f4==ga.line?ga.ch:null));++f4});if(f6.collapsed){gb.iter(f9.line,ga.line+1,function(ge){if(fn(gb,ge)){fR(ge,0)}})}if(f6.clearOnEnter){bV(f6,"beforeCursorEnter",function(){f6.clear()})}if(f6.readOnly){fY=true;if(gb.history.done.length||gb.history.undone.length){gb.clearHistory()}}if(f6.collapsed){f6.id=++a0;f6.atomic=true}if(f8){if(f3){f8.curOp.updateMaxLine=true}if(f6.collapsed){ag(f8,f9.line,ga.line+1)}else{if(f6.className||f6.title||f6.startStyle||f6.endStyle){for(var f5=f9.line;f5<=ga.line;f5++){S(f8,f5,"text")}}}if(f6.atomic){eo(f8.doc)}ad(f8,"markerAdded",f8,f6)}return f6}var y=J.SharedTextMarker=function(f5,f4){this.markers=f5;this.primary=f4;for(var f3=0;f3=f5:gb.to>f5);(ga||(ga=[])).push(new d8(f8,gb.from,f6?null:gb.to))}}}return ga}function az(f4,f6,f9){if(f4){for(var f7=0,ga;f7=f6:gb.to>f6);if(f5||gb.from==f6&&f8.type=="bookmark"&&(!f9||gb.marker.insertLeft)){var f3=gb.from==null||(f8.inclusiveLeft?gb.from<=f6:gb.from0&&f9){for(var f6=0;f60){continue}var gc=[f6,1],f3=cd(f4.from,f5.from),gb=cd(f4.to,f5.to);if(f3<0||!ga.inclusiveLeft&&!f3){gc.push({from:f4.from,to:f5.from})}if(gb>0||!ga.inclusiveRight&&!gb){gc.push({from:f5.to,to:f4.to})}f8.splice.apply(f8,gc);f6+=gc.length-1}}return f8}function fU(f3){var f5=f3.markedSpans;if(!f5){return}for(var f4=0;f4=0&&f8<=0||gc<=0&&f8>=0){continue}if(gc<=0&&(cd(gd.to,f9)>0||(f4.marker.inclusiveRight&&f7.inclusiveLeft))||gc>=0&&(cd(gd.from,ga)<0||(f4.marker.inclusiveLeft&&f7.inclusiveRight))){return true}}}}function z(f4){var f3;while(f3=eF(f4)){f4=f3.find(-1,true).line}return f4}function h(f5){var f3,f4;while(f3=el(f5)){f5=f3.find(1,true).line;(f4||(f4=[])).push(f5)}return f4}function aR(f6,f4){var f3=e5(f6,f4),f5=z(f3);if(f3==f5){return f4}return bL(f5)}function dT(f6,f5){if(f5>f6.lastLine()){return f5}var f4=e5(f6,f5),f3;if(!fn(f6,f4)){return f5}while(f3=el(f4)){f4=f3.find(1,true).line}return bL(f4)+1}function fn(f7,f4){var f3=a2&&f4.markedSpans;if(f3){for(var f6,f5=0;f5f7.start){return f5}}throw new Error("Mode "+f8.name+" failed to advance stream.")}function cp(gc,ga,f7,f6){function f3(gf){return{start:gd.start,end:gd.pos,string:gd.current(),type:f5||null,state:gf?b1(gb.mode,f4):f4}}var gb=gc.doc,f8=gb.mode,f5;ga=fA(gb,ga);var ge=e5(gb,ga.line),f4=ds(gc,ga.line,f7);var gd=new eK(ge.text,gc.options.tabSize),f9;if(f6){f9=[]}while((f6||gd.posgd.options.maxHighlightLength){f5=false;if(f7){dn(gd,gf,f4,ge.pos)}ge.pos=gf.length;f3=null}else{f3=dd(es(f8,ge,f4,gh),f6)}if(gh){var gg=gh[0].name;if(gg){f3="m-"+(f3?gg+" "+f3:gg)}}if(!f5||ga!=f3){if(gbgd){gb.splice(f9,1,gd,gb[f9+1],ge)}f9+=2;f5=Math.min(gd,ge)}if(!gf){return}if(f8.opaque){gb.splice(gh,f9-gh,gd,"cm-overlay "+gf);f9=gh+2}else{for(;ghf6&&f7.from<=f6){break}}if(f7.to>=f8){return f4(gb,gd,f5,f9,ge,gc)}f4(gb,gd.slice(0,f7.to-f6),f5,f9,null,gc);f9=null;gd=gd.slice(f7.to-f6);f6=f7.to}}}function ab(f4,f6,f3,f5){var f7=!f5&&f3.widgetNode;if(f7){f4.map.push(f4.pos,f4.pos+f6,f7);f4.content.appendChild(f7)}f4.pos+=f6}function bm(gc,gi,gb){var f8=gc.markedSpans,ga=gc.text,gg=0;if(!f8){for(var gl=1;glf7)){if(gk.to!=null&&gp>gk.to){gp=gk.to;go=""}if(gh.className){f3+=" "+gh.className}if(gh.startStyle&&gk.from==f7){gf+=" "+gh.startStyle}if(gh.endStyle&&gk.to==gp){go+=" "+gh.endStyle}if(gh.title&&!gq){gq=gh.title}if(gh.collapsed&&(!f5||dG(f5.marker,gh)<0)){f5=gk}}else{if(gk.from>f7&&gp>gk.from){gp=gk.from}}if(gh.type=="bookmark"&&gk.from==f7&&gh.widgetNode){f9.push(gh)}}if(f5&&(f5.from||0)==f7){ab(gi,(f5.to==null?gm+1:f5.to)-f7,f5.marker,f5.from==null);if(f5.to==null){return}}if(!f5&&f9.length){for(var gj=0;gj=gm){break}var gd=Math.min(gm,gp);while(true){if(ge){var f4=f7+ge.length;if(!f5){var f6=f4>gd?ge.slice(0,gd-f7):ge;gi.addToken(gi,f6,gn?gn+f3:f3,gf,f7+f6.length==gp?go:"",gq)}if(f4>=gd){ge=ge.slice(gd-f7);f7=gd;break}f7=f4;gf=""}ge=ga.slice(gg,gg=gb[gl++]);gn=eN(gb[gl++],gi.cm.options)}}}function dI(f3,f4){return f4.from.ch==0&&f4.to.ch==0&&fy(f4.text)==""&&(!f3.cm||f3.cm.options.wholeLineUpdateBefore)}function fp(gg,gb,f3,f7){function gh(gj){return f3?f3[gj]:null}function f4(gj,gl,gk){ed(gj,gl,gk,f7);ad(gj,"change",gj,gb)}var ge=gb.from,gf=gb.to,gi=gb.text;var gc=e5(gg,ge.line),gd=e5(gg,gf.line);var ga=fy(gi),f6=gh(gi.length-1),f9=gf.line-ge.line;if(dI(gg,gb)){for(var f5=0,f8=[];f51){gg.remove(ge.line+1,f9-1)}gg.insert(ge.line+1,f8)}}}ad(gg,"change",gg,gb)}function eQ(f4){this.lines=f4;this.parent=null;for(var f5=0,f3=0;f51||!(this.children[0] instanceof eQ))){var f4=[];this.collapse(f4);this.children=[new eQ(f4)];this.children[0].parent=this}},collapse:function(f3){for(var f4=0;f450){while(ga.lines.length>50){var f7=ga.lines.splice(ga.lines.length-25,25);var f6=new eQ(f7);ga.height-=f6.height;this.children.splice(f8+1,0,f6);f6.parent=this}this.maybeSpill()}break}f4-=f9}},maybeSpill:function(){if(this.children.length<=10){return}var f6=this;do{var f4=f6.children.splice(f6.children.length-5,5);var f5=new fo(f4);if(!f6.parent){var f7=new fo(f6.children);f7.parent=f6;f6.children=[f7,f5];f6=f7}else{f6.size-=f5.size;f6.height-=f5.height;var f3=dc(f6.parent.children,f6);f6.parent.children.splice(f3+1,0,f5)}f5.parent=f6.parent}while(f6.children.length>10);f6.parent.maybeSpill()},iterN:function(f3,f9,f8){for(var f4=0;f4=0;f6--){bb(this,f7[f6])}if(f3){eX(this,f3)}else{if(this.cm){fx(this.cm)}}}),undo:cB(function(){b6(this,"undo")}),redo:cB(function(){b6(this,"redo")}),undoSelection:cB(function(){b6(this,"undo",true)}),redoSelection:cB(function(){b6(this,"redo",true)}),setExtending:function(f3){this.extend=f3},getExtending:function(){return this.extend},historySize:function(){var f6=this.history,f3=0,f5=0;for(var f4=0;f4=f7.ch)){f6.push(f5.marker.parent||f5.marker)}}}return f6},findMarks:function(f7,f6,f3){f7=fA(this,f7);f6=fA(this,f6);var f4=[],f5=f7.line;this.iter(f7.line,f6.line+1,function(f8){var ga=f8.markedSpans;if(ga){for(var f9=0;f9gb.to||gb.from==null&&f5!=f7.line||f5==f6.line&&gb.from>f6.ch)&&(!f3||f3(gb.marker))){f4.push(gb.marker.parent||gb.marker)}}}++f5});return f4},getAllMarks:function(){var f3=[];this.iter(function(f5){var f4=f5.markedSpans;if(f4){for(var f6=0;f6f4){f3=f4;return true}f4-=f7;++f5});return fA(this,X(f5,f3))},indexFromPos:function(f4){f4=fA(this,f4);var f3=f4.ch;if(f4.linef6){f6=f3.from}if(f3.to!=null&&f3.to=f6.size){throw new Error("There is no line "+(f8+f6.first)+" in the document.")}for(var f3=f6;!f3.lines;){for(var f4=0;;++f4){var f7=f3.children[f4],f5=f7.chunkSize();if(f81&&!f4.done[f4.done.length-2].ranges){f4.done.pop();return fy(f4.done)}}}}function fD(f9,f7,f3,f6){var f5=f9.history;f5.undone.length=0;var f4=+new Date,ga;if((f5.lastOp==f6||f5.lastOrigin==f7.origin&&f7.origin&&((f7.origin.charAt(0)=="+"&&f9.cm&&f5.lastModTime>f4-f9.cm.options.historyEventDelay)||f7.origin.charAt(0)=="*"))&&(ga=eD(f5,f5.lastOp==f6))){var gb=fy(ga.changes);if(cd(f7.from,f7.to)==0&&cd(f7.from,gb.to)==0){gb.to=cS(f7)}else{ga.changes.push(dl(f9,f7))}}else{var f8=fy(f5.done);if(!f8||!f8.ranges){cK(f9.sel,f5.done)}ga={changes:[dl(f9,f7)],generation:f5.generation};f5.done.push(ga);while(f5.done.length>f5.undoDepth){f5.done.shift();if(!f5.done[0].ranges){f5.done.shift()}}}f5.done.push(f3);f5.generation=++f5.maxGeneration;f5.lastModTime=f5.lastSelTime=f4;f5.lastOp=f5.lastSelOp=f6;f5.lastOrigin=f5.lastSelOrigin=f7.origin;if(!gb){aB(f9,"historyAdded")}}function by(f7,f3,f5,f6){var f4=f3.charAt(0);return f4=="*"||f4=="+"&&f5.ranges.length==f6.ranges.length&&f5.somethingSelected()==f6.somethingSelected()&&new Date-f7.history.lastSelTime<=(f7.cm?f7.cm.options.historyEventDelay:500)}function fX(f8,f6,f3,f5){var f7=f8.history,f4=f5&&f5.origin;if(f3==f7.lastSelOp||(f4&&f7.lastSelOrigin==f4&&(f7.lastModTime==f7.lastSelTime&&f7.lastOrigin==f4||by(f8,f4,fy(f7.done),f6)))){f7.done[f7.done.length-1]=f6}else{cK(f6,f7.done)}f7.lastSelTime=+new Date;f7.lastSelOrigin=f4;f7.lastSelOp=f3;if(f5&&f5.clearRedo!==false){fs(f7.undone)}}function cK(f4,f3){var f5=fy(f3);if(!(f5&&f5.ranges&&f5.equals(f4))){f3.push(f4)}}function bW(f4,f8,f7,f6){var f3=f8["spans_"+f4.id],f5=0;f4.iter(Math.max(f4.first,f7),Math.min(f4.first+f4.size,f6),function(f9){if(f9.markedSpans){(f3||(f3=f8["spans_"+f4.id]={}))[f5]=f9.markedSpans}++f5})}function bh(f5){if(!f5){return null}for(var f4=0,f3;f4-1){fy(gc)[f3]=ga[f3];delete ga[f3]}}}}}}return f4}function K(f6,f5,f4,f3){if(f40}function bw(f3){f3.prototype.on=function(f4,f5){bV(this,f4,f5)};f3.prototype.off=function(f4,f5){d3(this,f4,f5)}}var bg=30;var b8=J.Pass={toString:function(){return"CodeMirror.Pass"}};var Z={scroll:false},N={origin:"*mouse"},cR={origin:"+move"};function f2(){this.id=null}f2.prototype.set=function(f3,f4){clearTimeout(this.id);this.id=setTimeout(f4,f3)};var bR=J.countColumn=function(f6,f4,f8,f9,f5){if(f4==null){f4=f6.search(/[^\s\u00a0]/);if(f4==-1){f4=f6.length}}for(var f7=f9||0,ga=f5||0;;){var f3=f6.indexOf("\t",f7);if(f3<0||f3>=f4){return ga+(f4-f7)}ga+=f3-f7;ga+=f8-(ga%f8);f7=f3+1}};function eg(f7,f6,f8){for(var f9=0,f5=0;;){var f4=f7.indexOf("\t",f9);if(f4==-1){f4=f7.length}var f3=f4-f9;if(f4==f7.length||f5+f3>=f6){return f9+Math.min(f3,f6-f5)}f5+=f4-f9;f5+=f8-(f5%f8);f9=f4+1;if(f5>=f6){return f9}}}var aU=[""];function co(f3){while(aU.length<=f3){aU.push(fy(aU)+" ")}return aU[f3]}function fy(f3){return f3[f3.length-1]}var dB=function(f3){f3.select()};if(eS){dB=function(f3){f3.selectionStart=0;f3.selectionEnd=f3.value.length}}else{if(dA){dB=function(f4){try{f4.select()}catch(f3){}}}}function dc(f5,f3){for(var f4=0;f4"\x80"&&(f3.toUpperCase()!=f3.toLowerCase()||a7.test(f3))};function cy(f3,f4){if(!f4){return fu(f3)}if(f4.source.indexOf("\\w")>-1&&fu(f3)){return true}return f4.test(f3)}function eL(f3){for(var f4 in f3){if(f3.hasOwnProperty(f4)&&f3[f4]){return false}}return true}var eA=/[\u0300-\u036f\u0483-\u0489\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u065e\u0670\u06d6-\u06dc\u06de-\u06e4\u06e7\u06e8\u06ea-\u06ed\u0711\u0730-\u074a\u07a6-\u07b0\u07eb-\u07f3\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0900-\u0902\u093c\u0941-\u0948\u094d\u0951-\u0955\u0962\u0963\u0981\u09bc\u09be\u09c1-\u09c4\u09cd\u09d7\u09e2\u09e3\u0a01\u0a02\u0a3c\u0a41\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a70\u0a71\u0a75\u0a81\u0a82\u0abc\u0ac1-\u0ac5\u0ac7\u0ac8\u0acd\u0ae2\u0ae3\u0b01\u0b3c\u0b3e\u0b3f\u0b41-\u0b44\u0b4d\u0b56\u0b57\u0b62\u0b63\u0b82\u0bbe\u0bc0\u0bcd\u0bd7\u0c3e-\u0c40\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0cbc\u0cbf\u0cc2\u0cc6\u0ccc\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0d3e\u0d41-\u0d44\u0d4d\u0d57\u0d62\u0d63\u0dca\u0dcf\u0dd2-\u0dd4\u0dd6\u0ddf\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0eb1\u0eb4-\u0eb9\u0ebb\u0ebc\u0ec8-\u0ecd\u0f18\u0f19\u0f35\u0f37\u0f39\u0f71-\u0f7e\u0f80-\u0f84\u0f86\u0f87\u0f90-\u0f97\u0f99-\u0fbc\u0fc6\u102d-\u1030\u1032-\u1037\u1039\u103a\u103d\u103e\u1058\u1059\u105e-\u1060\u1071-\u1074\u1082\u1085\u1086\u108d\u109d\u135f\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b7-\u17bd\u17c6\u17c9-\u17d3\u17dd\u180b-\u180d\u18a9\u1920-\u1922\u1927\u1928\u1932\u1939-\u193b\u1a17\u1a18\u1a56\u1a58-\u1a5e\u1a60\u1a62\u1a65-\u1a6c\u1a73-\u1a7c\u1a7f\u1b00-\u1b03\u1b34\u1b36-\u1b3a\u1b3c\u1b42\u1b6b-\u1b73\u1b80\u1b81\u1ba2-\u1ba5\u1ba8\u1ba9\u1c2c-\u1c33\u1c36\u1c37\u1cd0-\u1cd2\u1cd4-\u1ce0\u1ce2-\u1ce8\u1ced\u1dc0-\u1de6\u1dfd-\u1dff\u200c\u200d\u20d0-\u20f0\u2cef-\u2cf1\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua66f-\ua672\ua67c\ua67d\ua6f0\ua6f1\ua802\ua806\ua80b\ua825\ua826\ua8c4\ua8e0-\ua8f1\ua926-\ua92d\ua947-\ua951\ua980-\ua982\ua9b3\ua9b6-\ua9b9\ua9bc\uaa29-\uaa2e\uaa31\uaa32\uaa35\uaa36\uaa43\uaa4c\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uabe5\uabe8\uabed\udc00-\udfff\ufb1e\ufe00-\ufe0f\ufe20-\ufe26\uff9e\uff9f]/;function fg(f3){return f3.charCodeAt(0)>=768&&eA.test(f3)}function fN(f3,f7,f6,f5){var f8=document.createElement(f3);if(f6){f8.className=f6}if(f5){f8.style.cssText=f5}if(typeof f7=="string"){f8.appendChild(document.createTextNode(f7))}else{if(f7){for(var f4=0;f40;--f3){f4.removeChild(f4.firstChild)}return f4}function bP(f3,f4){return dR(f3).appendChild(f4)}function fW(f3,f4){if(f3.contains){return f3.contains(f4)}while(f4=f4.parentNode){if(f4==f3){return true}}}function dE(){return document.activeElement}if(dA&&l<11){dE=function(){try{return document.activeElement}catch(f3){return document.body}}}function T(f3){return new RegExp("(^|\\s)"+f3+"(?:$|\\s)\\s*")}var f=J.rmClass=function(f5,f3){var f6=f5.className;var f4=T(f3).exec(f6);if(f4){var f7=f6.slice(f4.index+f4[0].length);f5.className=f6.slice(0,f4.index)+(f7?f4[1]+f7:"")}};var fr=J.addClass=function(f4,f3){var f5=f4.className;if(!T(f3).test(f5)){f4.className+=(f5?" ":"")+f3}};function fI(f5,f3){var f4=f5.split(" ");for(var f6=0;f62&&!(dA&&l<8)}}if(fC){return fN("span","\u200b")}else{return fN("span","\u00a0",null,"display: inline-block; width: 1px; margin-right: -1px")}}var fB;function bM(f6){if(fB!=null){return fB}var f3=bP(f6,document.createTextNode("A\u062eA"));var f5=ck(f3,0,1).getBoundingClientRect();if(!f5||f5.left==f5.right){return false}var f4=ck(f3,1,2).getBoundingClientRect();return fB=(f4.right-f5.right<3)}var aV=J.splitLines="\n\nb".split(/\n/).length!=3?function(f8){var f9=0,f3=[],f7=f8.length;while(f9<=f7){var f6=f8.indexOf("\n",f9);if(f6==-1){f6=f8.length}var f5=f8.slice(f9,f8.charAt(f6-1)=="\r"?f6-1:f6);var f4=f5.indexOf("\r");if(f4!=-1){f3.push(f5.slice(0,f4));f9+=f4+1}else{f3.push(f5);f9=f6+1}}return f3}:function(f3){return f3.split(/\r\n?|\n/)};var bq=window.getSelection?function(f4){try{return f4.selectionStart!=f4.selectionEnd}catch(f3){return false}}:function(f5){try{var f3=f5.ownerDocument.selection.createRange()}catch(f4){}if(!f3||f3.parentElement()!=f5){return false}return f3.compareEndPoints("StartToEnd",f3)!=0};var c5=(function(){var f3=fN("div");if("oncopy" in f3){return true}f3.setAttribute("oncopy","return;");return typeof f3.oncopy=="function"})();var eW=null;function aH(f4){if(eW!=null){return eW}var f5=bP(f4,fN("span","x"));var f6=f5.getBoundingClientRect();var f3=ck(f5,0,1).getBoundingClientRect();return eW=Math.abs(f6.left-f3.left)>1}var e6={3:"Enter",8:"Backspace",9:"Tab",13:"Enter",16:"Shift",17:"Ctrl",18:"Alt",19:"Pause",20:"CapsLock",27:"Esc",32:"Space",33:"PageUp",34:"PageDown",35:"End",36:"Home",37:"Left",38:"Up",39:"Right",40:"Down",44:"PrintScrn",45:"Insert",46:"Delete",59:";",61:"=",91:"Mod",92:"Mod",93:"Mod",107:"=",109:"-",127:"Delete",173:"-",186:";",187:"=",188:",",189:"-",190:".",191:"/",192:"`",219:"[",220:"\\",221:"]",222:"'",63232:"Up",63233:"Down",63234:"Left",63235:"Right",63272:"Delete",63273:"Home",63275:"End",63276:"PageUp",63277:"PageDown",63302:"Insert"};J.keyNames=e6;(function(){for(var f3=0;f3<10;f3++){e6[f3+48]=e6[f3+96]=String(f3)}for(var f3=65;f3<=90;f3++){e6[f3]=String.fromCharCode(f3)}for(var f3=1;f3<=12;f3++){e6[f3+111]=e6[f3+63235]="F"+f3}})();function dU(f3,f9,f8,f7){if(!f3){return f7(f9,f8,"ltr")}var f6=false;for(var f5=0;f5f9||f9==f8&&f4.to==f9){f7(Math.max(f4.from,f9),Math.min(f4.to,f8),f4.level==1?"rtl":"ltr");f6=true}}if(!f6){f7(f9,f8,"ltr")}}function dp(f3){return f3.level%2?f3.to:f3.from}function fZ(f3){return f3.level%2?f3.from:f3.to}function cC(f4){var f3=a(f4);return f3?dp(f3[0]):0}function cP(f4){var f3=a(f4);if(!f3){return f4.text.length}return fZ(fy(f3))}function br(f4,f7){var f5=e5(f4.doc,f7);var f8=z(f5);if(f8!=f5){f7=bL(f8)}var f3=a(f8);var f6=!f3?0:f3[0].level%2?cP(f8):cC(f8);return X(f7,f6)}function dF(f5,f8){var f4,f6=e5(f5.doc,f8);while(f4=el(f6)){f6=f4.find(1,true).line;f8=null}var f3=a(f6);var f7=!f3?f6.text.length:f3[0].level%2?cC(f6):cP(f6);return X(f8==null?bL(f6):f8,f7)}function dz(f4,f9){var f8=br(f4,f9.line);var f5=e5(f4.doc,f8.line);var f3=a(f5);if(!f3||f3[0].level==0){var f7=Math.max(0,f5.text.search(/\S/));var f6=f9.line==f8.line&&f9.ch<=f7&&f9.ch;return X(f8.line,f6?0:f7)}return f8}function am(f4,f5,f3){var f6=f4[0].level;if(f5==f6){return true}if(f3==f6){return false}return f5f7){return f4}if((f6.from==f7||f6.to==f7)){if(f5==null){f5=f4}else{if(am(f3,f6.level,f3[f5].level)){if(f6.from!=f6.to){eT=f5}return f4}else{if(f6.from!=f6.to){eT=f4}return f5}}}}return f5}function e4(f3,f6,f4,f5){if(!f5){return f6+f4}do{f6+=f4}while(f6>0&&fg(f3.text.charAt(f6)));return f6}function v(f3,ga,f5,f6){var f7=a(f3);if(!f7){return ah(f3,ga,f5,f6)}var f9=aD(f7,ga),f4=f7[f9];var f8=e4(f3,ga,f4.level%2?-f5:f5,f6);for(;;){if(f8>f4.from&&f80)==f4.level%2?f4.to:f4.from}else{f4=f7[f9+=f5];if(!f4){return null}if((f5>0)==f4.level%2){f8=e4(f3,f4.to,-1,f6)}else{f8=e4(f3,f4.from,1,f6)}}}}function ah(f3,f7,f4,f5){var f6=f7+f4;if(f5){while(f6>0&&fg(f3.text.charAt(f6))){f6+=f4}}return f6<0||f6>f3.text.length?null:f6}var bc=(function(){var f9="bbbbbbbbbtstwsbbbbbbbbbbbbbbssstwNN%%%NNNNNN,N,N1111111111NNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNbbbbbbsbbbbbbbbbbbbbbbbbbbbbbbbbb,N%%%%NNNNLNNNNN%%11NLNNN1LNNNNNLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLN";var f7="rrrrrrrrrrrr,rNNmmmmmmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmrrrrrrrnnnnnnnnnn%nnrrrmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmmmmmmNmmmm";function f6(gd){if(gd<=247){return f9.charAt(gd)}else{if(1424<=gd&&gd<=1524){return"R"}else{if(1536<=gd&&gd<=1773){return f7.charAt(gd-1536)}else{if(1774<=gd&&gd<=2220){return"r"}else{if(8192<=gd&&gd<=8203){return"w"}else{if(gd==8204){return"b"}else{return"L"}}}}}}}var f3=/[\u0590-\u05f4\u0600-\u06ff\u0700-\u08ac]/;var gc=/[stwN]/,f5=/[LRr]/,f4=/[Lb1n]/,f8=/[1n]/;var gb="L";function ga(gf,ge,gd){this.level=gf;this.from=ge;this.to=gd}return function(gn){if(!f3.test(gn)){return false}var gt=gn.length,gj=[];for(var gs=0,gf;gs diff --git a/media/editors/codemirror/mode/apl/apl.js b/media/editors/codemirror/mode/apl/apl.js index a87dd73bdeea9..4357bed475fb1 100644 Binary files a/media/editors/codemirror/mode/apl/apl.js and b/media/editors/codemirror/mode/apl/apl.js differ diff --git a/media/editors/codemirror/mode/apl/index.html b/media/editors/codemirror/mode/apl/index.html index c41ca1f2dd7b0..2efb97f319a35 100644 Binary files a/media/editors/codemirror/mode/apl/index.html and b/media/editors/codemirror/mode/apl/index.html differ diff --git a/media/editors/codemirror/mode/asterisk/index.html b/media/editors/codemirror/mode/asterisk/index.html index 6abdecb50dc6f..2efb97f319a35 100644 --- a/media/editors/codemirror/mode/asterisk/index.html +++ b/media/editors/codemirror/mode/asterisk/index.html @@ -1,154 +1 @@ - - -CodeMirror: Asterisk dialplan mode - - - - - - - - - -
-

Asterisk dialplan mode

-
- - -

MIME types defined: text/x-asterisk.

- -
+ diff --git a/media/editors/codemirror/mode/clike/clike.js b/media/editors/codemirror/mode/clike/clike.js index ee2c77a025e9e..710953b2298a4 100644 --- a/media/editors/codemirror/mode/clike/clike.js +++ b/media/editors/codemirror/mode/clike/clike.js @@ -20,7 +20,8 @@ CodeMirror.defineMode("clike", function(config, parserConfig) { blockKeywords = parserConfig.blockKeywords || {}, atoms = parserConfig.atoms || {}, hooks = parserConfig.hooks || {}, - multiLineStrings = parserConfig.multiLineStrings; + multiLineStrings = parserConfig.multiLineStrings, + indentStatements = parserConfig.indentStatements !== false; var isOperatorChar = /[+\-*&%=<>!?|\/]/; var curPunc; @@ -57,7 +58,7 @@ CodeMirror.defineMode("clike", function(config, parserConfig) { stream.eatWhile(isOperatorChar); return "operator"; } - stream.eatWhile(/[\w\$_]/); + stream.eatWhile(/[\w\$_\xa1-\uffff]/); var cur = stream.current(); if (keywords.propertyIsEnumerable(cur)) { if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement"; @@ -151,7 +152,9 @@ CodeMirror.defineMode("clike", function(config, parserConfig) { while (ctx.type == "statement") ctx = popContext(state); } else if (curPunc == ctx.type) popContext(state); - else if (((ctx.type == "}" || ctx.type == "top") && curPunc != ';') || (ctx.type == "statement" && curPunc == "newstatement")) + else if (indentStatements && + (((ctx.type == "}" || ctx.type == "top") && curPunc != ';') || + (ctx.type == "statement" && curPunc == "newstatement"))) pushContext(state, stream.column(), "statement"); state.startOfLine = false; return style; @@ -298,6 +301,7 @@ CodeMirror.defineMode("clike", function(config, parserConfig) { }, modeProps: {fold: ["brace", "include"]} }); + def("text/x-java", { name: "clike", keywords: words("abstract assert boolean break byte case catch char class const continue default " + @@ -315,6 +319,7 @@ CodeMirror.defineMode("clike", function(config, parserConfig) { }, modeProps: {fold: ["brace", "import"]} }); + def("text/x-csharp", { name: "clike", keywords: words("abstract as base break case catch checked class const continue" + @@ -341,6 +346,19 @@ CodeMirror.defineMode("clike", function(config, parserConfig) { } } }); + + function tokenTripleString(stream, state) { + var escaped = false; + while (!stream.eol()) { + if (!escaped && stream.match('"""')) { + state.tokenize = null; + break; + } + escaped = stream.next() != "\\" && !escaped; + } + return "string"; + } + def("text/x-scala", { name: "clike", keywords: words( @@ -366,19 +384,24 @@ CodeMirror.defineMode("clike", function(config, parserConfig) { "Compiler Double Exception Float Integer Long Math Number Object Package Pair Process " + "Runtime Runnable SecurityManager Short StackTraceElement StrictMath String " + "StringBuffer System Thread ThreadGroup ThreadLocal Throwable Triple Void" - - ), multiLineStrings: true, blockKeywords: words("catch class do else finally for forSome if match switch try while"), atoms: words("true false null"), + indentStatements: false, hooks: { "@": function(stream) { stream.eatWhile(/[\w\$_]/); return "meta"; + }, + '"': function(stream, state) { + if (!stream.match('""')) return false; + state.tokenize = tokenTripleString; + return state.tokenize(stream, state); } } }); + def(["x-shader/x-vertex", "x-shader/x-fragment"], { name: "clike", keywords: words("float int bool void " + @@ -448,4 +471,19 @@ CodeMirror.defineMode("clike", function(config, parserConfig) { modeProps: {fold: ["brace", "include"]} }); + def("text/x-objectivec", { + name: "clike", + keywords: words(cKeywords + "inline restrict _Bool _Complex _Imaginery BOOL Class bycopy byref id IMP in " + + "inout nil oneway out Protocol SEL self super atomic nonatomic retain copy readwrite readonly"), + atoms: words("YES NO NULL NILL ON OFF"), + hooks: { + "@": function(stream) { + stream.eatWhile(/[\w\$]/); + return "keyword"; + }, + "#": cppHook + }, + modeProps: {fold: "brace"} + }); + }); diff --git a/media/editors/codemirror/mode/clike/index.html b/media/editors/codemirror/mode/clike/index.html index d1abf9359d1c0..2efb97f319a35 100644 --- a/media/editors/codemirror/mode/clike/index.html +++ b/media/editors/codemirror/mode/clike/index.html @@ -1,204 +1 @@ - - -CodeMirror: C-like mode - - - - - - - - - - - - -
-

C-like mode

- -
- -

C++ example

- -
- -

Java example

- -
- - - -

Simple mode that tries to handle C-like languages as well as it - can. Takes two configuration parameters: keywords, an - object whose property names are the keywords in the language, - and useCPP, which determines whether C preprocessor - directives are recognized.

- -

MIME types defined: text/x-csrc - (C code), text/x-c++src (C++ - code), text/x-java (Java - code), text/x-csharp (C#).

-
+ diff --git a/media/editors/codemirror/mode/clike/scala.html b/media/editors/codemirror/mode/clike/scala.html index e9acc049b3e7f..aa04cf0f04af5 100644 --- a/media/editors/codemirror/mode/clike/scala.html +++ b/media/editors/codemirror/mode/clike/scala.html @@ -10,12 +10,12 @@