From c4caf8670061b661f204c9306c2361406620a0c7 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 14 Nov 2013 13:34:36 +0100 Subject: [PATCH 0001/4131] [javascript mode] More ES6 features (modules, destructuring, generators, class) --- mode/javascript/javascript.js | 116 ++++++++++++++++++++++++---------- mode/javascript/test.js | 42 ++++++++++++ 2 files changed, 125 insertions(+), 33 deletions(-) diff --git a/mode/javascript/javascript.js b/mode/javascript/javascript.js index 5be5f7c119..17cd1b02d6 100644 --- a/mode/javascript/javascript.js +++ b/mode/javascript/javascript.js @@ -19,9 +19,10 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { "var": kw("var"), "const": kw("var"), "let": kw("var"), "function": kw("function"), "catch": kw("catch"), "for": kw("for"), "switch": kw("switch"), "case": kw("case"), "default": kw("default"), - "in": operator, "of": operator, "typeof": operator, "instanceof": operator, + "in": operator, "typeof": operator, "instanceof": operator, "true": atom, "false": atom, "null": atom, "undefined": atom, "NaN": atom, "Infinity": atom, - "this": kw("this") + "this": kw("this"), "module": kw("module"), "class": kw("class"), "super": kw("atom"), + "yield": C, "export": kw("export"), "import": kw("import") }; // Extend the 'normal' keywords with the TypeScript language extensions @@ -30,7 +31,6 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { var tsKeywords = { // object-like things "interface": kw("interface"), - "class": kw("class"), "extends": kw("extends"), "constructor": kw("constructor"), @@ -40,8 +40,6 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { "protected": kw("protected"), "static": kw("static"), - "super": kw("super"), - // types "string": type, "number": type, "bool": type, "any": type }; @@ -84,6 +82,8 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { return chain(stream, state, jsTokenString(ch)); else if (ch == "." && stream.match(/^\d+(?:[eE][+\-]?\d+)?/)) return ret("number", "number"); + else if (ch == "." && stream.eat("..")) + return ret("spread", "meta"); else if (/[\[\]{}\(\),;\:\.]/.test(ch)) return ret(ch); else if (ch == "0" && stream.eat(/x/i)) { @@ -257,8 +257,8 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { }; } - function statement(type) { - if (type == "var") return cont(pushlex("vardef"), vardef1, expect(";"), poplex); + function statement(type, value) { + if (type == "var") return cont(pushlex("vardef", value.length), vardef, expect(";"), poplex); if (type == "keyword a") return cont(pushlex("form"), expression, statement, poplex); if (type == "keyword b") return cont(pushlex("form"), statement, poplex); if (type == "{") return cont(pushlex("}"), block, poplex); @@ -274,6 +274,10 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { if (type == "default") return cont(expect(":")); if (type == "catch") return cont(pushlex("form"), pushcontext, expect("("), funarg, expect(")"), statement, poplex, popcontext); + if (type == "module") return cont(pushlex("form"), pushcontext, afterModule, popcontext, poplex); + if (type == "class") return cont(pushlex("form"), className, objlit, poplex); + if (type == "export") return cont(pushlex("form"), afterExport, poplex); + if (type == "import") return cont(pushlex("form"), afterImport, poplex); return pass(pushlex("stat"), expression, expect(";"), poplex); } function expression(type) { @@ -288,9 +292,9 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { if (type == "function") return cont(functiondef); if (type == "keyword c") return cont(noComma ? maybeexpressionNoComma : maybeexpression); if (type == "(") return cont(pushlex(")"), maybeexpression, expect(")"), poplex, maybeop); - if (type == "operator") return cont(noComma ? expressionNoComma : expression); - if (type == "[") return cont(pushlex("]"), commasep(expressionNoComma, "]"), poplex, maybeop); - if (type == "{") return cont(pushlex("}"), commasep(objprop, "}"), poplex, maybeop); + if (type == "operator" || type == "spread") return cont(noComma ? expressionNoComma : expression); + if (type == "[") return cont(commasep(expressionNoComma, "]"), maybeop); + if (type == "{") return cont(commasep(objprop, "}"), maybeop); return cont(); } function maybeexpression(type) { @@ -315,7 +319,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { return cont(expr); } if (type == ";") return; - if (type == "(") return cont(pushlex(")", "call"), commasep(expressionNoComma, ")"), poplex, me); + if (type == "(") return cont(commasep(expressionNoComma, ")", "call"), me); if (type == ".") return cont(property, me); if (type == "[") return cont(pushlex("]"), maybeexpression, expect("]"), poplex, me); } @@ -332,16 +336,21 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { if (value == "get" || value == "set") return cont(getterSetter); } else if (type == "number" || type == "string") { cx.marked = type + " property"; + } else if (type == "[") { + return cont(expression, expect("]"), afterprop); } - if (atomicTypes.hasOwnProperty(type)) return cont(expect(":"), expressionNoComma); + if (atomicTypes.hasOwnProperty(type)) return cont(afterprop); } function getterSetter(type) { - if (type == ":") return cont(expression); - if (type != "variable") return cont(expect(":"), expression); + if (type != "variable") return pass(afterprop); cx.marked = "property"; return cont(functiondef); } - function commasep(what, end) { + function afterprop(type) { + if (type == ":") return cont(expressionNoComma); + if (type == "(") return pass(functiondef); + } + function commasep(what, end, info) { function proceed(type) { if (type == ",") { var lex = cx.state.lexical; @@ -353,7 +362,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { } return function(type) { if (type == end) return cont(); - else return pass(what, proceed); + else return pass(pushlex(end, info), what, proceed, poplex); }; } function block(type) { @@ -361,51 +370,92 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { return pass(statement, block); } function maybetype(type) { - if (type == ":") return cont(typedef); - return pass(); + if (isTS && type == ":") return cont(typedef); } function typedef(type) { if (type == "variable"){cx.marked = "variable-3"; return cont();} - return pass(); } - function vardef1(type, value) { - if (type == "variable") { + function vardef() { + return pass(pattern, maybetype, maybeAssign, vardefCont); + } + function pattern(type, value) { + if (type == "variable") { register(value); return cont(); } + if (type == "[") return cont(commasep(pattern, "]")); + if (type == "{") return cont(commasep(proppattern, "}")); + } + function proppattern(type, value) { + if (type == "variable" && !cx.stream.match(/^\s*:/, false)) { register(value); - return isTS ? cont(maybetype, vardef2) : cont(vardef2); + return cont(maybeAssign); } - return pass(); + if (type == "variable") cx.marked = "property"; + return cont(expect(":"), pattern, maybeAssign); + } + function maybeAssign(_type, value) { + if (value == "=") return cont(expressionNoComma); } - function vardef2(type, value) { - if (value == "=") return cont(expressionNoComma, vardef2); - if (type == ",") return cont(vardef1); + function vardefCont(type) { + if (type == ",") return cont(vardef); } function maybeelse(type, value) { if (type == "keyword b" && value == "else") return cont(pushlex("form"), statement, poplex); } function forspec1(type) { - if (type == "var") return cont(vardef1, expect(";"), forspec2); + if (type == "var") return cont(vardef, expect(";"), forspec2); if (type == ";") return cont(forspec2); if (type == "variable") return cont(formaybeinof); return pass(expression, expect(";"), forspec2); } function formaybeinof(_type, value) { - if (value == "in" || value == "of") return cont(expression); + if (value == "in" || value == "of") { cx.marked = "keyword"; return cont(expression); } return cont(maybeoperatorComma, forspec2); } function forspec2(type, value) { if (type == ";") return cont(forspec3); - if (value == "in" || value == "of") return cont(expression); + if (value == "in" || value == "of") { cx.marked = "keyword"; return cont(expression); } return pass(expression, expect(";"), forspec3); } function forspec3(type) { if (type != ")") cont(expression); } function functiondef(type, value) { + if (value == "*") {cx.marked = "keyword"; return cont(functiondef);} if (type == "variable") {register(value); return cont(functiondef);} - if (type == "(") return cont(pushlex(")"), pushcontext, commasep(funarg, ")"), poplex, statement, popcontext); + if (type == "(") return cont(pushcontext, commasep(funarg, ")"), statement, popcontext); + } + function funarg(type) { + if (type == "spread") return cont(funarg); + return pass(pattern, maybetype); + } + function className(type, value) { + if (type == "variable") {register(value); return cont(classNameAfter);} + } + function classNameAfter(type) { + if (type == "(") return pass(expression); + } + function objlit(type) { + if (type == "{") return cont(commasep(objprop, "}")); + } + function afterModule(type, value) { + if (type == "string") return cont(statement); + if (type == "variable") { register(value); return cont(maybeFrom); } + } + function afterExport(_type, value) { + if (value == "*") { cx.marked = "keyword"; return cont(maybeFrom, expect(";")); } + if (value == "default") { cx.marked = "keyword"; return cont(expression, expect(";")); } + return pass(statement); + } + function afterImport(type) { + if (type == "string") return cont(); + return pass(importSpec, maybeFrom); + } + function importSpec(type, value) { + if (type == "{") return cont(commasep(importSpec, "}")); + if (type == "variable") register(value); + return cont(); } - function funarg(type, value) { - if (type == "variable") {register(value); return isTS ? cont(maybetype) : cont();} + function maybeFrom(_type, value) { + if (value == "from") { cx.marked = "keyword"; return cont(expression); } } // Interface @@ -452,7 +502,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { lexical = lexical.prev; var type = lexical.type, closing = firstChar == type; - if (type == "vardef") return lexical.indented + (state.lastType == "operator" || state.lastType == "," ? 4 : 0); + if (type == "vardef") return lexical.indented + (state.lastType == "operator" || state.lastType == "," ? lexical.info + 1 : 0); else if (type == "form" && firstChar == "{") return lexical.indented; else if (type == "form") return lexical.indented + indentUnit; else if (type == "stat") diff --git a/mode/javascript/test.js b/mode/javascript/test.js index a2af527bee..90c4769d47 100644 --- a/mode/javascript/test.js +++ b/mode/javascript/test.js @@ -7,4 +7,46 @@ MT("comma-and-binop", "[keyword function](){ [keyword var] [def x] = [number 1] + [number 2], [def y]; }"); + + MT("destructuring", + "([keyword function]([def a], [[[def b], [def c] ]]) {", + " [keyword let] {[def d], [property foo]: [def c]=[number 10], [def x]} = [variable foo]([variable-2 a]);", + " [[[variable-2 c], [variable y] ]] = [variable-2 c];", + "})();"); + + MT("class", + "[keyword class] [variable Point]([variable SuperThing]) {", + " [[ [string-2 /expr/] ]]: [number 24],", + " [property constructor]([def x], [def y]) {", + " [keyword super]([string 'something']);", + " [keyword this].[property x] = [variable-2 x];", + " }", + "}"); + + MT("module", + "[keyword module] [string 'foo'] {", + " [keyword export] [keyword let] [def x] = [number 42];", + " [keyword export] [keyword *] [keyword from] [string 'somewhere'];", + "}"); + + MT("import", + "[keyword function] [variable foo]() {", + " [keyword import] [def $] [keyword from] [string 'jquery'];", + " [keyword module] [def crypto] [keyword from] [string 'crypto'];", + " [keyword import] { [def encrypt], [def decrypt] } [keyword from] [string 'crypto'];", + "}"); + + MT("const", + "[keyword function] [variable f]() {", + " [keyword const] [[ [def a], [def b] ]] = [[ [number 1], [number 2] ]];", + "}"); + + MT("for/of", + "[keyword for]([keyword let] [variable of] [keyword of] [variable something]) {}"); + + MT("generator", + "[keyword function*] [variable repeat]([def n]) {", + " [keyword for]([keyword var] [def i] = [number 0]; [variable-2 i] < [variable-2 n]; ++[variable-2 i])", + " [keyword yield] [variable-2 i];", + "}"); })(); From 83aa2b8707324046166f9aef0ef0594c06ddca52 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 14 Nov 2013 14:14:05 +0100 Subject: [PATCH 0002/4131] [javascript mode] Add ES6 fat-arrow support --- mode/javascript/javascript.js | 54 ++++++++++++++++++++++++++++++++++- mode/javascript/test.js | 11 +++++++ 2 files changed, 64 insertions(+), 1 deletion(-) diff --git a/mode/javascript/javascript.js b/mode/javascript/javascript.js index 17cd1b02d6..001a04032f 100644 --- a/mode/javascript/javascript.js +++ b/mode/javascript/javascript.js @@ -82,10 +82,12 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { return chain(stream, state, jsTokenString(ch)); else if (ch == "." && stream.match(/^\d+(?:[eE][+\-]?\d+)?/)) return ret("number", "number"); - else if (ch == "." && stream.eat("..")) + else if (ch == "." && stream.match("..")) return ret("spread", "meta"); else if (/[\[\]{}\(\),;\:\.]/.test(ch)) return ret(ch); + else if (ch == "=" && stream.eat(">")) + return ret("=>"); else if (ch == "0" && stream.eat(/x/i)) { stream.eatWhile(/[\da-f]/i); return ret("number", "number"); @@ -149,6 +151,38 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { return ret("comment", "comment"); } + var brackets = "([{}])"; + // This is a crude lookahead trick to try and notice that we're + // parsing the argument patterns for a fat-arrow function before we + // actually hit the arrow token. It only works if the arrow is on + // the same line as the arguments and there's no strange noise + // (comments) in between. Fallback is to only notice when we hit the + // arrow, and not declare the arguments as locals for the arrow + // body. + function findFatArrow(stream, state) { + if (state.fatArrowAt) state.fatArrowAt = null; + var arrow = stream.string.indexOf("=>", stream.start); + if (arrow < 0) return; + + var depth = 0, sawSomething = false; + for (var pos = arrow - 1; pos >= 0; --pos) { + var ch = stream.string.charAt(pos); + var bracket = brackets.indexOf(ch); + if (bracket >= 0 && bracket < 3) { + if (!depth) { ++pos; break; } + if (--depth == 0) break; + } else if (bracket >= 3 && bracket < 6) { + ++depth; + } else if (/[$\w]/.test(ch)) { + sawSomething = true; + } else if (sawSomething && !depth) { + ++pos; + break; + } + } + if (sawSomething && !depth) state.fatArrowAt = pos; + } + // Parser var atomicTypes = {"atom": true, "number": true, "variable": true, "string": true, "regexp": true, "this": true}; @@ -287,6 +321,12 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { return expressionInner(type, true); } function expressionInner(type, noComma) { + if (cx.state.fatArrowAt == cx.stream.start) { + var body = noComma ? arrowBodyNoComma : arrowBody; + if (type == "(") return cont(pushcontext, commasep(pattern, ")"), expect("=>"), body, popcontext); + else if (type == "variable") return pass(pushcontext, pattern, expect("=>"), body, popcontext); + } + var maybeop = noComma ? maybeoperatorNoComma : maybeoperatorComma; if (atomicTypes.hasOwnProperty(type)) return cont(maybeop); if (type == "function") return cont(functiondef); @@ -313,6 +353,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { function maybeoperatorNoComma(type, value, noComma) { var me = noComma == false ? maybeoperatorComma : maybeoperatorNoComma; var expr = noComma == false ? expression : expressionNoComma; + if (value == "=>") return cont(pushcontext, noComma ? arrowBodyNoComma : arrowBody, popcontext); if (type == "operator") { if (/\+\+|--/.test(value)) return cont(me); if (value == "?") return cont(expression, expect(":"), expr); @@ -323,6 +364,16 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { if (type == ".") return cont(property, me); if (type == "[") return cont(pushlex("]"), maybeexpression, expect("]"), poplex, me); } + function arrowBody(type) { + findFatArrow(cx.stream, cx.state); + if (type == "{") return pass(statement); + return pass(expression); + } + function arrowBodyNoComma(type) { + findFatArrow(cx.stream, cx.state); + if (type == "{") return pass(statement); + return pass(expressionNoComma); + } function maybelabel(type) { if (type == ":") return cont(poplex, statement); return pass(maybeoperatorComma, expect(";"), poplex); @@ -479,6 +530,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { if (!state.lexical.hasOwnProperty("align")) state.lexical.align = false; state.indented = stream.indentation(); + findFatArrow(stream, state); } if (state.tokenize != jsTokenComment && stream.eatSpace()) return null; var style = state.tokenize(stream, state); diff --git a/mode/javascript/test.js b/mode/javascript/test.js index 90c4769d47..d7f4fe5e6a 100644 --- a/mode/javascript/test.js +++ b/mode/javascript/test.js @@ -49,4 +49,15 @@ " [keyword for]([keyword var] [def i] = [number 0]; [variable-2 i] < [variable-2 n]; ++[variable-2 i])", " [keyword yield] [variable-2 i];", "}"); + + MT("fatArrow", + "[variable array].[property filter]([def a] => [variable-2 a] + [number 1]);", + "[variable a];", // No longer in scope + "[keyword let] [variable f] = ([[ [def a], [def b] ]], [def c]) => [variable-2 a] + [variable-2 c];", + "[variable c];"); + + MT("spread", + "[keyword function] [variable f]([def a], [meta ...][def b]) {", + " [variable something]([variable-2 a], [meta ...][variable-2 b]);", + "}"); })(); From d272101f6407359c7733316f07ac7126473aab94 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 14 Nov 2013 14:34:34 +0100 Subject: [PATCH 0003/4131] [javascript mode] Add support for ES6-style comprehension --- mode/javascript/javascript.js | 22 +++++++++++++++++----- mode/javascript/test.js | 6 ++++++ 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/mode/javascript/javascript.js b/mode/javascript/javascript.js index 001a04032f..92f58e82ac 100644 --- a/mode/javascript/javascript.js +++ b/mode/javascript/javascript.js @@ -299,8 +299,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { if (type == ";") return cont(); if (type == "if") return cont(pushlex("form"), expression, statement, poplex, maybeelse); if (type == "function") return cont(functiondef); - if (type == "for") return cont(pushlex("form"), expect("("), pushlex(")"), forspec1, expect(")"), - poplex, statement, poplex); + if (type == "for") return cont(pushlex("form"), forspec, poplex, statement, poplex); if (type == "variable") return cont(pushlex("stat"), maybelabel); if (type == "switch") return cont(pushlex("form"), expression, pushlex("}", "switch"), expect("{"), block, poplex, poplex); @@ -331,9 +330,9 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { if (atomicTypes.hasOwnProperty(type)) return cont(maybeop); if (type == "function") return cont(functiondef); if (type == "keyword c") return cont(noComma ? maybeexpressionNoComma : maybeexpression); - if (type == "(") return cont(pushlex(")"), maybeexpression, expect(")"), poplex, maybeop); + if (type == "(") return cont(pushlex(")"), maybeexpression, comprehension, expect(")"), poplex, maybeop); if (type == "operator" || type == "spread") return cont(noComma ? expressionNoComma : expression); - if (type == "[") return cont(commasep(expressionNoComma, "]"), maybeop); + if (type == "[") return cont(pushlex("]"), expressionNoComma, maybeArrayComprehension, poplex, maybeop); if (type == "{") return cont(commasep(objprop, "}"), maybeop); return cont(); } @@ -413,7 +412,8 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { } return function(type) { if (type == end) return cont(); - else return pass(pushlex(end, info), what, proceed, poplex); + if (info === false) return pass(what, proceed); + return pass(pushlex(end, info), what, proceed, poplex); }; } function block(type) { @@ -451,6 +451,9 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { function maybeelse(type, value) { if (type == "keyword b" && value == "else") return cont(pushlex("form"), statement, poplex); } + function forspec(type) { + if (type == "(") return cont(pushlex(")"), forspec1, expect(")")); + } function forspec1(type) { if (type == "var") return cont(vardef, expect(";"), forspec2); if (type == ";") return cont(forspec2); @@ -508,6 +511,15 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { function maybeFrom(_type, value) { if (value == "from") { cx.marked = "keyword"; return cont(expression); } } + function maybeArrayComprehension(type) { + if (type == "for") return pass(comprehension); + if (type == ",") return cont(commasep(expressionNoComma, "]", false)); + return pass(commasep(expressionNoComma, "]", false)); + } + function comprehension(type) { + if (type == "for") return cont(forspec, comprehension); + if (type == "if") return cont(expression, comprehension); + } // Interface diff --git a/mode/javascript/test.js b/mode/javascript/test.js index d7f4fe5e6a..125cfce373 100644 --- a/mode/javascript/test.js +++ b/mode/javascript/test.js @@ -60,4 +60,10 @@ "[keyword function] [variable f]([def a], [meta ...][def b]) {", " [variable something]([variable-2 a], [meta ...][variable-2 b]);", "}"); + + MT("comprehension", + "[keyword function] [variable f]() {", + " [[ [variable x] + [number 1] [keyword for] ([keyword var] [def x] [keyword in] [variable y]) [keyword if] [variable pred]([variable-2 x]) ]];", + " ([variable u] [keyword for] ([keyword var] [def u] [keyword of] [variable generateValues]()) [keyword if] ([variable-2 u].[property color] === [string 'blue']));", + "}"); })(); From d85b8c4c980fc54a2e52950622feb939c0013e8f Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Fri, 15 Nov 2013 11:03:19 +0100 Subject: [PATCH 0004/4131] [javascript mode] Add support for ES6 quasiquotes --- mode/javascript/javascript.js | 101 ++++++++++++++++++++-------------- mode/javascript/test.js | 3 + 2 files changed, 63 insertions(+), 41 deletions(-) diff --git a/mode/javascript/javascript.js b/mode/javascript/javascript.js index 92f58e82ac..03824739e6 100644 --- a/mode/javascript/javascript.js +++ b/mode/javascript/javascript.js @@ -54,11 +54,6 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { var isOperatorChar = /[+\-*&%=<>!?|~^]/; - function chain(stream, state, f) { - state.tokenize = f; - return f(stream, state); - } - function nextUntilUnescaped(stream, end) { var escaped = false, next; while ((next = stream.next()) != null) { @@ -76,54 +71,51 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { type = tp; content = cont; return style; } - function jsTokenBase(stream, state) { + function tokenBase(stream, state) { var ch = stream.next(); - if (ch == '"' || ch == "'") - return chain(stream, state, jsTokenString(ch)); - else if (ch == "." && stream.match(/^\d+(?:[eE][+\-]?\d+)?/)) + if (ch == '"' || ch == "'") { + state.tokenize = tokenString(ch); + return state.tokenize(stream, state); + } else if (ch == "." && stream.match(/^\d+(?:[eE][+\-]?\d+)?/)) { return ret("number", "number"); - else if (ch == "." && stream.match("..")) + } else if (ch == "." && stream.match("..")) { return ret("spread", "meta"); - else if (/[\[\]{}\(\),;\:\.]/.test(ch)) + } else if (/[\[\]{}\(\),;\:\.]/.test(ch)) { return ret(ch); - else if (ch == "=" && stream.eat(">")) + } else if (ch == "=" && stream.eat(">")) { return ret("=>"); - else if (ch == "0" && stream.eat(/x/i)) { + } else if (ch == "0" && stream.eat(/x/i)) { stream.eatWhile(/[\da-f]/i); return ret("number", "number"); - } - else if (/\d/.test(ch)) { + } else if (/\d/.test(ch)) { stream.match(/^\d*(?:\.\d*)?(?:[eE][+\-]?\d+)?/); return ret("number", "number"); - } - else if (ch == "/") { + } else if (ch == "/") { if (stream.eat("*")) { - return chain(stream, state, jsTokenComment); - } - else if (stream.eat("/")) { + state.tokenize = tokenComment; + return tokenComment(stream, state); + } else if (stream.eat("/")) { stream.skipToEnd(); return ret("comment", "comment"); - } - else if (state.lastType == "operator" || state.lastType == "keyword c" || + } else if (state.lastType == "operator" || state.lastType == "keyword c" || state.lastType == "sof" || /^[\[{}\(,;:]$/.test(state.lastType)) { nextUntilUnescaped(stream, "/"); stream.eatWhile(/[gimy]/); // 'y' is "sticky" option in Mozilla return ret("regexp", "string-2"); - } - else { + } else { stream.eatWhile(isOperatorChar); return ret("operator", null, stream.current()); } - } - else if (ch == "#") { + } else if (ch == "`") { + state.tokenize = tokenQuasi; + return tokenQuasi(stream, state); + } else if (ch == "#") { stream.skipToEnd(); return ret("error", "error"); - } - else if (isOperatorChar.test(ch)) { + } else if (isOperatorChar.test(ch)) { stream.eatWhile(isOperatorChar); return ret("operator", null, stream.current()); - } - else { + } else { stream.eatWhile(/[\w\$_]/); var word = stream.current(), known = keywords.propertyIsEnumerable(word) && keywords[word]; return (known && state.lastType != ".") ? ret(known.type, known.style, word) : @@ -131,19 +123,19 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { } } - function jsTokenString(quote) { + function tokenString(quote) { return function(stream, state) { if (!nextUntilUnescaped(stream, quote)) - state.tokenize = jsTokenBase; + state.tokenize = tokenBase; return ret("string", "string"); }; } - function jsTokenComment(stream, state) { + function tokenComment(stream, state) { var maybeEnd = false, ch; while (ch = stream.next()) { if (ch == "/" && maybeEnd) { - state.tokenize = jsTokenBase; + state.tokenize = tokenBase; break; } maybeEnd = (ch == "*"); @@ -151,6 +143,18 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { return ret("comment", "comment"); } + function tokenQuasi(stream, state) { + var escaped = false, next; + while ((next = stream.next()) != null) { + if (!escaped && (next == "`" || next == "$" && stream.eat("{"))) { + state.tokenize = tokenBase; + break; + } + escaped = !escaped && next == "\\"; + } + return ret("quasi", "string-2", stream.current()); + } + var brackets = "([{}])"; // This is a crude lookahead trick to try and notice that we're // parsing the argument patterns for a fat-arrow function before we @@ -249,7 +253,8 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { state.localVars = {name: varname, next: state.localVars}; } else { if (inList(state.globalVars)) return; - state.globalVars = {name: varname, next: state.globalVars}; + if (parserConfig.globalVars) + state.globalVars = {name: varname, next: state.globalVars}; } } @@ -358,11 +363,24 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { if (value == "?") return cont(expression, expect(":"), expr); return cont(expr); } + if (type == "quasi") { cx.cc.push(me); return quasi(value); } if (type == ";") return; if (type == "(") return cont(commasep(expressionNoComma, ")", "call"), me); if (type == ".") return cont(property, me); if (type == "[") return cont(pushlex("]"), maybeexpression, expect("]"), poplex, me); } + function quasi(value) { + if (!value) debugger; + if (value.slice(value.length - 2) != "${") return cont(); + return cont(expression, continueQuasi); + } + function continueQuasi(type) { + if (type == "}") { + cx.marked = "string-2"; + cx.state.tokenize = tokenQuasi; + return cont(); + } + } function arrowBody(type) { findFatArrow(cx.stream, cx.state); if (type == "{") return pass(statement); @@ -525,16 +543,17 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { return { startState: function(basecolumn) { - return { - tokenize: jsTokenBase, + var state = { + tokenize: tokenBase, lastType: "sof", cc: [], lexical: new JSLexical((basecolumn || 0) - indentUnit, 0, "block", false), localVars: parserConfig.localVars, - globalVars: parserConfig.globalVars, context: parserConfig.localVars && {vars: parserConfig.localVars}, indented: 0 }; + if (parserConfig.globalVars) state.globalVars = parserConfig.globalVars; + return state; }, token: function(stream, state) { @@ -544,7 +563,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { state.indented = stream.indentation(); findFatArrow(stream, state); } - if (state.tokenize != jsTokenComment && stream.eatSpace()) return null; + if (state.tokenize != tokenComment && stream.eatSpace()) return null; var style = state.tokenize(stream, state); if (type == "comment") return style; state.lastType = type == "operator" && (content == "++" || content == "--") ? "incdec" : type; @@ -552,8 +571,8 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { }, indent: function(state, textAfter) { - if (state.tokenize == jsTokenComment) return CodeMirror.Pass; - if (state.tokenize != jsTokenBase) return 0; + if (state.tokenize == tokenComment) return CodeMirror.Pass; + if (state.tokenize != tokenBase) return 0; var firstChar = textAfter && textAfter.charAt(0), lexical = state.lexical; // Kludge to prevent 'maybelse' from blocking lexical scope pops for (var i = state.cc.length - 1; i >= 0; --i) { diff --git a/mode/javascript/test.js b/mode/javascript/test.js index 125cfce373..8dcb20d455 100644 --- a/mode/javascript/test.js +++ b/mode/javascript/test.js @@ -66,4 +66,7 @@ " [[ [variable x] + [number 1] [keyword for] ([keyword var] [def x] [keyword in] [variable y]) [keyword if] [variable pred]([variable-2 x]) ]];", " ([variable u] [keyword for] ([keyword var] [def u] [keyword of] [variable generateValues]()) [keyword if] ([variable-2 u].[property color] === [string 'blue']));", "}"); + + MT("quasi", + "[variable re][string-2 `fofdlakj${][variable x] + ([variable re][string-2 `foo`]) + [number 1][string-2 }fdsa`] + [number 2]"); })(); From a31c335e03a0d89cdbed2c40197c0cab7ff08b4a Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Fri, 15 Nov 2013 11:10:12 +0100 Subject: [PATCH 0005/4131] [javascript mode] Use 'extends' instead of parenthesized syntax for inheritance --- mode/javascript/javascript.js | 6 +++--- mode/javascript/test.js | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/mode/javascript/javascript.js b/mode/javascript/javascript.js index 03824739e6..fdc41877b0 100644 --- a/mode/javascript/javascript.js +++ b/mode/javascript/javascript.js @@ -22,7 +22,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { "in": operator, "typeof": operator, "instanceof": operator, "true": atom, "false": atom, "null": atom, "undefined": atom, "NaN": atom, "Infinity": atom, "this": kw("this"), "module": kw("module"), "class": kw("class"), "super": kw("atom"), - "yield": C, "export": kw("export"), "import": kw("import") + "yield": C, "export": kw("export"), "import": kw("import"), "extends": C }; // Extend the 'normal' keywords with the TypeScript language extensions @@ -502,8 +502,8 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { function className(type, value) { if (type == "variable") {register(value); return cont(classNameAfter);} } - function classNameAfter(type) { - if (type == "(") return pass(expression); + function classNameAfter(_type, value) { + if (value == "extends") return cont(expression); } function objlit(type) { if (type == "{") return cont(commasep(objprop, "}")); diff --git a/mode/javascript/test.js b/mode/javascript/test.js index 8dcb20d455..760152499e 100644 --- a/mode/javascript/test.js +++ b/mode/javascript/test.js @@ -15,7 +15,7 @@ "})();"); MT("class", - "[keyword class] [variable Point]([variable SuperThing]) {", + "[keyword class] [variable Point] [keyword extends] [variable SuperThing] {", " [[ [string-2 /expr/] ]]: [number 24],", " [property constructor]([def x], [def y]) {", " [keyword super]([string 'something']);", From 37ee20782d8d45eeb9a536d953eb90d3a903cb5b Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 18 Nov 2013 11:01:12 +0100 Subject: [PATCH 0006/4131] [javascript mode] Fix indentation of 'else' lines Issue #1960 --- mode/javascript/javascript.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mode/javascript/javascript.js b/mode/javascript/javascript.js index fdc41877b0..f27c06346c 100644 --- a/mode/javascript/javascript.js +++ b/mode/javascript/javascript.js @@ -578,7 +578,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { for (var i = state.cc.length - 1; i >= 0; --i) { var c = state.cc[i]; if (c == poplex) lexical = lexical.prev; - else if (c != maybeelse || /^else\b/.test(textAfter)) break; + else if (c != maybeelse) break; } if (lexical.type == "stat" && firstChar == "}") lexical = lexical.prev; if (statementIndent && lexical.type == ")" && lexical.prev.type == "stat") From 8e2454ae441dc1913f2d1c88b7627d1c0d560450 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=AD=8F=E9=B9=8F=E5=88=9A?= Date: Tue, 19 Nov 2013 14:55:52 +0800 Subject: [PATCH 0007/4131] [fullscreen addon] Set with to auto rather than '' --- addon/display/fullscreen.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/addon/display/fullscreen.js b/addon/display/fullscreen.js index 3c31e97a33..a442f6a433 100644 --- a/addon/display/fullscreen.js +++ b/addon/display/fullscreen.js @@ -12,7 +12,8 @@ var wrap = cm.getWrapperElement(); cm.state.fullScreenRestore = {scrollTop: window.pageYOffset, scrollLeft: window.pageXOffset, width: wrap.style.width, height: wrap.style.height}; - wrap.style.width = wrap.style.height = ""; + wrap.style.width = ""; + wrap.style.height = "auto"; wrap.className += " CodeMirror-fullscreen"; document.documentElement.style.overflow = "hidden"; cm.refresh(); From 4426841017bfc06411dd4513c77e35900e1710f2 Mon Sep 17 00:00:00 2001 From: Anton Kovalyov Date: Mon, 18 Nov 2013 15:33:11 -0800 Subject: [PATCH 0008/4131] [dialog addon] Make dialogDiv accept a detached DOM node in addition to a template string --- addon/dialog/dialog.js | 6 +++++- doc/manual.html | 6 +++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/addon/dialog/dialog.js b/addon/dialog/dialog.js index ced394d3fc..499964fdb2 100644 --- a/addon/dialog/dialog.js +++ b/addon/dialog/dialog.js @@ -10,7 +10,11 @@ } else { dialog.className = "CodeMirror-dialog CodeMirror-dialog-top"; } - dialog.innerHTML = template; + if (typeof template == "string") { + dialog.innerHTML = template; + } else { // Assuming it's a detached DOM element. + dialog.appendChild(template); + } return dialog; } diff --git a/doc/manual.html b/doc/manual.html index 80de6d950f..8100bb82a7 100644 --- a/doc/manual.html +++ b/doc/manual.html @@ -1710,9 +1710,9 @@

Addons

Provides a very simple way to query users for text input. Adds an openDialog method to CodeMirror instances, which can be called with an HTML fragment - that provides the prompt (should include an input - tag), and a callback function that is called when text has been - entered. Also adds + or a detached DOM node that provides the prompt (should include + an input tag), and a callback function that is called + when text has been entered. Also adds an openNotification function that simply shows an HTML fragment as a notification. Depends on addon/dialog/dialog.css.
From bd374efc143ccb4515d001a647ba89d2fdd11201 Mon Sep 17 00:00:00 2001 From: Alberto Pose Date: Mon, 18 Nov 2013 18:05:13 -0300 Subject: [PATCH 0009/4131] [foldgutter addon] Add options to customize change/update time spans --- addon/fold/foldgutter.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/addon/fold/foldgutter.js b/addon/fold/foldgutter.js index e3c52bc229..57336fbff8 100644 --- a/addon/fold/foldgutter.js +++ b/addon/fold/foldgutter.js @@ -88,14 +88,14 @@ } function onChange(cm) { - var state = cm.state.foldGutter; + var state = cm.state.foldGutter, opts = cm.state.foldGutter.options; state.from = state.to = 0; clearTimeout(state.changeUpdate); - state.changeUpdate = setTimeout(function() { updateInViewport(cm); }, 600); + state.changeUpdate = setTimeout(function() { updateInViewport(cm); }, opts.foldOnChangeTimeSpan || 600); } function onViewportChange(cm) { - var state = cm.state.foldGutter; + var state = cm.state.foldGutter, opts = cm.state.foldGutter.options; clearTimeout(state.changeUpdate); state.changeUpdate = setTimeout(function() { var vp = cm.getViewport(); @@ -113,7 +113,7 @@ } }); } - }, 400); + }, opts.updateViewportTimeSpan || 400); } function onFold(cm, from) { From f0610e60c3b220814d80c133326adebc7339a35f Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Tue, 19 Nov 2013 18:33:06 +0100 Subject: [PATCH 0010/4131] Add specialChars and specialCharPlaceholder options Issue #649 --- doc/manual.html | 13 +++++++++++++ lib/codemirror.js | 22 ++++++++++++++++------ 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/doc/manual.html b/doc/manual.html index 8100bb82a7..a0c650e170 100644 --- a/doc/manual.html +++ b/doc/manual.html @@ -208,6 +208,19 @@

Configuration

indentation (only works if the mode supports indentation). Default is true. +
specialChars: RegExp
+
A regular expression used to determine which characters + should be replaced by a + special placeholder. + Mostly useful for non-printing special characters. The default + is /[\u0000-\u0019\u00ad\u200b\u2028\u2029\ufeff]/.
+
specialCharPlaceholder: function(char) → Element
+
A function that, given a special character identified by + the specialChars + option, produces a DOM node that is used to represent the + character. By default, a red dot () + is shown, with a title tooltip to indicate the character code.
+
rtlMoveVisually: boolean
Determines whether horizontal cursor movement through right-to-left (Arabic, Hebrew) text is visual (pressing the left diff --git a/lib/codemirror.js b/lib/codemirror.js index 78939b5599..8d4fbcaa26 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -3281,6 +3281,11 @@ window.CodeMirror = (function() { clearCaches(cm); regChange(cm); }, true); + option("specialChars", /[\t\u0000-\u0019\u00ad\u200b\u2028\u2029\ufeff]/, function(cm, val) { + cm.options.specialChars = new RegExp(val.source + (val.test("\t") ? "" : "|\t"), "g"); + cm.refresh(); + }, true); + option("specialCharPlaceholder", defaultSpecialCharPlaceholder, function(cm) {cm.refresh();}, true); option("electricChars", true); option("rtlMoveVisually", !windows); @@ -4426,17 +4431,23 @@ window.CodeMirror = (function() { return builder; } - var tokenSpecialChars = /[\t\u0000-\u0019\u00ad\u200b\u2028\u2029\uFEFF]/g; + function defaultSpecialCharPlaceholder(ch) { + var token = elt("span", "\u2022", "cm-invalidchar"); + token.title = "\\u" + ch.toString(16); + return token; + } + function buildToken(builder, text, style, startStyle, endStyle, title) { if (!text) return; - if (!tokenSpecialChars.test(text)) { + var special = builder.cm.options.specialChars; + if (!special.test(text)) { builder.col += text.length; var content = document.createTextNode(text); } else { var content = document.createDocumentFragment(), pos = 0; while (true) { - tokenSpecialChars.lastIndex = pos; - var m = tokenSpecialChars.exec(text); + special.lastIndex = pos; + var m = special.exec(text); var skipped = m ? m.index - pos : text.length - pos; if (skipped) { content.appendChild(document.createTextNode(text.slice(pos, pos + skipped))); @@ -4449,8 +4460,7 @@ window.CodeMirror = (function() { content.appendChild(elt("span", spaceStr(tabWidth), "cm-tab")); builder.col += tabWidth; } else { - var token = elt("span", "\u2022", "cm-invalidchar"); - token.title = "\\u" + m[0].charCodeAt(0).toString(16); + var token = builder.cm.options.specialCharPlaceholder(m[0].charCodeAt(0)); content.appendChild(token); builder.col += 1; } From 3853222ea46bff376fca7a965d6be178ccc568fa Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Tue, 19 Nov 2013 18:46:41 +0100 Subject: [PATCH 0011/4131] Fix two bugs in f0610e60c3b220 Issue #649 --- lib/codemirror.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/codemirror.js b/lib/codemirror.js index 8d4fbcaa26..73782aa4fd 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -3281,7 +3281,7 @@ window.CodeMirror = (function() { clearCaches(cm); regChange(cm); }, true); - option("specialChars", /[\t\u0000-\u0019\u00ad\u200b\u2028\u2029\ufeff]/, function(cm, val) { + option("specialChars", /[\t\u0000-\u0019\u00ad\u200b\u2028\u2029\ufeff]/g, function(cm, val) { cm.options.specialChars = new RegExp(val.source + (val.test("\t") ? "" : "|\t"), "g"); cm.refresh(); }, true); @@ -4433,7 +4433,7 @@ window.CodeMirror = (function() { function defaultSpecialCharPlaceholder(ch) { var token = elt("span", "\u2022", "cm-invalidchar"); - token.title = "\\u" + ch.toString(16); + token.title = "\\u" + ch.charCodeAt(0).toString(16); return token; } @@ -4460,7 +4460,7 @@ window.CodeMirror = (function() { content.appendChild(elt("span", spaceStr(tabWidth), "cm-tab")); builder.col += tabWidth; } else { - var token = builder.cm.options.specialCharPlaceholder(m[0].charCodeAt(0)); + var token = builder.cm.options.specialCharPlaceholder(m[0]); content.appendChild(token); builder.col += 1; } From e446407ac121532a21ef7b129b32365532529404 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Tue, 19 Nov 2013 18:56:51 +0100 Subject: [PATCH 0012/4131] Run mode over the whole line in long lines when in background-processing mode Issue #1908 --- lib/codemirror.js | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/lib/codemirror.js b/lib/codemirror.js index 73782aa4fd..1dff8d4c35 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -910,7 +910,7 @@ window.CodeMirror = (function() { doc.iter(doc.frontier, Math.min(doc.first + doc.size, cm.display.showingTo + 500), function(line) { if (doc.frontier >= cm.display.showingFrom) { // Visible var oldStyles = line.styles; - line.styles = highlightLine(cm, line, state); + line.styles = highlightLine(cm, line, state, true); var ischange = !oldStyles || oldStyles.length != line.styles.length; for (var i = 0; !ischange && i < oldStyles.length; ++i) ischange = oldStyles[i] != line.styles[i]; if (ischange) { @@ -919,7 +919,7 @@ window.CodeMirror = (function() { } line.stateAfter = copyState(doc.mode, state); } else { - processLine(cm, line, state); + processLine(cm, line.text, state); line.stateAfter = doc.frontier % 5 == 0 ? copyState(doc.mode, state) : null; } ++doc.frontier; @@ -963,7 +963,7 @@ window.CodeMirror = (function() { if (!state) state = startState(doc.mode); else state = copyState(doc.mode, state); doc.iter(pos, n, function(line) { - processLine(cm, line, state); + processLine(cm, line.text, state); var save = pos == n - 1 || pos % 5 == 0 || pos >= display.showingFrom && pos < display.showingTo; line.stateAfter = save ? copyState(doc.mode, state) : null; ++pos; @@ -4281,7 +4281,7 @@ window.CodeMirror = (function() { // Run the given mode's parser over a line, update the styles // array, which contains alternating fragments of text and CSS // classes. - function runMode(cm, text, mode, state, f) { + function runMode(cm, text, mode, state, f, forceToEnd) { var flattenSpans = mode.flattenSpans; if (flattenSpans == null) flattenSpans = cm.options.flattenSpans; var curStart = 0, curStyle = null; @@ -4290,6 +4290,7 @@ window.CodeMirror = (function() { while (!stream.eol()) { if (stream.pos > cm.options.maxHighlightLength) { flattenSpans = false; + if (forceToEnd) processLine(cm, text, state, stream.pos); stream.pos = text.length; style = null; } else { @@ -4309,12 +4310,14 @@ window.CodeMirror = (function() { } } - function highlightLine(cm, line, state) { + function highlightLine(cm, line, state, forceToEnd) { // A styles array always starts with a number identifying the // mode/overlays that it is based on (for easy invalidation). var st = [cm.state.modeGen]; // Compute the base array of styles - runMode(cm, line.text, cm.doc.mode, state, function(end, style) {st.push(end, style);}); + runMode(cm, line.text, cm.doc.mode, state, function(end, style) { + st.push(end, style); + }, forceToEnd); // Run overlays, adjust style array. for (var o = 0; o < cm.state.overlays.length; ++o) { @@ -4353,10 +4356,11 @@ window.CodeMirror = (function() { // Lightweight form of highlight -- proceed over this line and // update state, but don't save a style array. - function processLine(cm, line, state) { + function processLine(cm, text, state, startAt) { var mode = cm.doc.mode; - var stream = new StringStream(line.text, cm.options.tabSize); - if (line.text == "" && mode.blankLine) mode.blankLine(state); + var stream = new StringStream(text, cm.options.tabSize); + stream.start = stream.pos = startAt || 0; + if (text == "" && mode.blankLine) mode.blankLine(state); while (!stream.eol() && stream.pos <= cm.options.maxHighlightLength) { mode.token(stream, state); stream.start = stream.pos; From 53cce13c9e67985851efb2ff96a9388204ed25e5 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 21 Nov 2013 12:27:01 +0100 Subject: [PATCH 0013/4131] Fix completely botched IE11+ check --- lib/codemirror.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/codemirror.js b/lib/codemirror.js index 1dff8d4c35..1493b1a524 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -13,7 +13,7 @@ window.CodeMirror = (function() { var ie = /MSIE \d/.test(navigator.userAgent); var ie_lt8 = ie && (document.documentMode == null || document.documentMode < 8); var ie_lt9 = ie && (document.documentMode == null || document.documentMode < 9); - var ie_gt10 = /Trident\/([7-9]|\d{2,})\./; + var ie_gt10 = /Trident\/([7-9]|\d{2,})\./.test(navigator.userAgent); var webkit = /WebKit\//.test(navigator.userAgent); var qtwebkit = webkit && /Qt\/\d+\.\d+/.test(navigator.userAgent); var chrome = /Chrome\//.test(navigator.userAgent); From 31a77ad4c8f2f28d153c9abf60a979784568a2dc Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 21 Nov 2013 12:34:32 +0100 Subject: [PATCH 0014/4131] Export lineNo utility Issue #1969 --- lib/codemirror.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/codemirror.js b/lib/codemirror.js index 1493b1a524..b91baacc27 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -5088,7 +5088,7 @@ window.CodeMirror = (function() { for (var n = line; n; n = n.parent) n.height += diff; } - function lineNo(line) { + var lineNo = CodeMirror.lineNo = function(line) { if (line.parent == null) return null; var cur = line.parent, no = indexOf(cur.lines, line); for (var chunk = cur.parent; chunk; cur = chunk, chunk = chunk.parent) { @@ -5098,7 +5098,7 @@ window.CodeMirror = (function() { } } return no + cur.first; - } + }; function lineAtHeight(chunk, h) { var n = chunk.first; From 2546a4a4775b496911d993a8b9c767b410662132 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 21 Nov 2013 12:36:21 +0100 Subject: [PATCH 0015/4131] Make lineNo a method after all Issue #1969 --- lib/codemirror.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/codemirror.js b/lib/codemirror.js index b91baacc27..fb2e0c5604 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -4261,6 +4261,7 @@ window.CodeMirror = (function() { this.height = estimateHeight ? estimateHeight(this) : 1; }; eventMixin(Line); + Line.prototype.lineNo = function() { return lineNo(this); }; function updateLine(line, text, markedSpans, estimateHeight) { line.text = text; @@ -5088,7 +5089,7 @@ window.CodeMirror = (function() { for (var n = line; n; n = n.parent) n.height += diff; } - var lineNo = CodeMirror.lineNo = function(line) { + function lineNo(line) { if (line.parent == null) return null; var cur = line.parent, no = indexOf(cur.lines, line); for (var chunk = cur.parent; chunk; cur = chunk, chunk = chunk.parent) { @@ -5098,7 +5099,7 @@ window.CodeMirror = (function() { } } return no + cur.first; - }; + } function lineAtHeight(chunk, h) { var n = chunk.first; From d07ec7eee25e557d1109b90e82c6d09a8204127e Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 21 Nov 2013 12:52:39 +0100 Subject: [PATCH 0016/4131] Add (undocumented) wholeLineUpdateBefore option Issue #1972 Issue #1967 --- lib/codemirror.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/codemirror.js b/lib/codemirror.js index fb2e0c5604..0343a176bf 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -3288,6 +3288,7 @@ window.CodeMirror = (function() { option("specialCharPlaceholder", defaultSpecialCharPlaceholder, function(cm) {cm.refresh();}, true); option("electricChars", true); option("rtlMoveVisually", !windows); + option("wholeLineUpdateBefore", true); option("theme", "default", function(cm) { themeChanged(cm); @@ -4618,7 +4619,8 @@ window.CodeMirror = (function() { var lastText = lst(text), lastSpans = spansFor(text.length - 1), nlines = to.line - from.line; // First adjust the line structure - if (from.ch == 0 && to.ch == 0 && lastText == "") { + if (from.ch == 0 && to.ch == 0 && lastText == "" && + (!doc.cm || doc.cm.options.wholeLineUpdateBefore)) { // This is a whole-line replace. Treated specially to make // sure line objects move the way they are supposed to. for (var i = 0, e = text.length - 1, added = []; i < e; ++i) From 9aa224094e26b8f9badd3a9877373a9c2ea86992 Mon Sep 17 00:00:00 2001 From: Luciano Longo Date: Wed, 20 Nov 2013 17:17:28 -0300 Subject: [PATCH 0017/4131] [placeholder addon] Don't hide placeholder text on focus Most modern browsers now keep displaying the placeholder even if the user has focus on the input and only hide it when the input has content. This change is to make this addon consistent with this, so users won't tell the difference with native inputs' placeholder behaviour. --- addon/display/placeholder.js | 6 ------ 1 file changed, 6 deletions(-) diff --git a/addon/display/placeholder.js b/addon/display/placeholder.js index 18f9dff3ab..748afe7275 100644 --- a/addon/display/placeholder.js +++ b/addon/display/placeholder.js @@ -2,12 +2,10 @@ CodeMirror.defineOption("placeholder", "", function(cm, val, old) { var prev = old && old != CodeMirror.Init; if (val && !prev) { - cm.on("focus", onFocus); cm.on("blur", onBlur); cm.on("change", onChange); onChange(cm); } else if (!val && prev) { - cm.off("focus", onFocus); cm.off("blur", onBlur); cm.off("change", onChange); clearPlaceholder(cm); @@ -33,9 +31,6 @@ cm.display.lineSpace.insertBefore(elt, cm.display.lineSpace.firstChild); } - function onFocus(cm) { - clearPlaceholder(cm); - } function onBlur(cm) { if (isEmpty(cm)) setPlaceholder(cm); } @@ -43,7 +38,6 @@ var wrapper = cm.getWrapperElement(), empty = isEmpty(cm); wrapper.className = wrapper.className.replace(" CodeMirror-empty", "") + (empty ? " CodeMirror-empty" : ""); - if (cm.hasFocus()) return; if (empty) setPlaceholder(cm); else clearPlaceholder(cm); } From 0e58d2cf24d613805ee8b5fa41811a985515e924 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 21 Nov 2013 13:34:46 +0100 Subject: [PATCH 0018/4131] Mark release 3.20 --- doc/compress.html | 1 + doc/releases.html | 11 +++++++++++ index.html | 2 +- lib/codemirror.js | 2 +- package.json | 2 +- 5 files changed, 15 insertions(+), 3 deletions(-) diff --git a/doc/compress.html b/doc/compress.html index f49c978b2e..3f3bfb0465 100644 --- a/doc/compress.html +++ b/doc/compress.html @@ -33,6 +33,7 @@

Script compression helper

Version: '; var doReplaceConfirm = "Replace? "; function replace(cm, all) { - dialog(cm, replaceQueryDialog, "Replace:", function(query) { + dialog(cm, replaceQueryDialog, "Replace:", cm.getSelection(), function(query) { if (!query) return; query = parseQuery(query); - dialog(cm, replacementQueryDialog, "Replace with:", function(text) { + dialog(cm, replacementQueryDialog, "Replace with:", "", function(text) { if (all) { cm.operation(function() { for (var cursor = getSearchCursor(cm, query); cursor.findNext();) { From 5d752bbd7bbccf33c986dd5bf7f19ab752c6a4aa Mon Sep 17 00:00:00 2001 From: Sascha Peilicke Date: Mon, 25 Nov 2013 10:58:53 +0100 Subject: [PATCH 0033/4131] [rpm mode] Add 'preinstall' and 'postinstall' sections --- mode/rpm/spec/spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mode/rpm/spec/spec.js b/mode/rpm/spec/spec.js index 9f339c21b1..0fab6c4891 100644 --- a/mode/rpm/spec/spec.js +++ b/mode/rpm/spec/spec.js @@ -4,7 +4,7 @@ CodeMirror.defineMode("spec", function() { var arch = /^(i386|i586|i686|x86_64|ppc64|ppc|ia64|s390x|s390|sparc64|sparcv9|sparc|noarch|alphaev6|alpha|hppa|mipsel)/; var preamble = /^(Name|Version|Release|License|Summary|Url|Group|Source|BuildArch|BuildRequires|BuildRoot|AutoReqProv|Provides|Requires(\(\w+\))?|Obsoletes|Conflicts|Recommends|Source\d*|Patch\d*|ExclusiveArch|NoSource|Supplements):/; - var section = /^%(debug_package|package|description|prep|build|install|files|clean|changelog|preun|postun|pre|post|triggerin|triggerun|pretrans|posttrans|verifyscript|check|triggerpostun|triggerprein|trigger)/; + var section = /^%(debug_package|package|description|prep|build|install|files|clean|changelog|preinstall|preun|postinstall|postun|pre|post|triggerin|triggerun|pretrans|posttrans|verifyscript|check|triggerpostun|triggerprein|trigger)/; var control_flow_complex = /^%(ifnarch|ifarch|if)/; // rpm control flow macros var control_flow_simple = /^%(else|endif)/; // rpm control flow macros var operators = /^(\!|\?|\<\=|\<|\>\=|\>|\=\=|\&\&|\|\|)/; // operators in control flow macros From c84f676ebc6302102bc8e9ac1317c59b656ee74f Mon Sep 17 00:00:00 2001 From: Forbes Lindesay Date: Mon, 25 Nov 2013 11:52:34 +0000 Subject: [PATCH 0034/4131] Use the github url for `repository` This makes it easy to find the GitHub repo from https://npmjs.org/package/codemirror --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ab323b0110..27bb735827 100644 --- a/package.json +++ b/package.json @@ -15,5 +15,5 @@ "email": "marijnh@gmail.com", "web": "http://marijnhaverbeke.nl"}], "repository": {"type": "git", - "url": "http://marijnhaverbeke.nl/git/codemirror"} + "url": "https://github.com/marijnh/CodeMirror.git"} } From f5bcce05dceb4f60c9685733d2f074d75fb96118 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 25 Nov 2013 17:36:19 +0100 Subject: [PATCH 0035/4131] Fix a bidi cursor drawing bug --- lib/codemirror.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/codemirror.js b/lib/codemirror.js index 70d8091db7..fc2e971e7b 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -5712,22 +5712,22 @@ window.CodeMirror = (function() { } var bidiOther; function getBidiPartAt(order, pos) { + bidiOther = null; for (var i = 0, found; i < order.length; ++i) { var cur = order[i]; - if (cur.from < pos && cur.to > pos) { bidiOther = null; return i; } - if (cur.from == pos || cur.to == pos) { + if (cur.from < pos && cur.to > pos) return i; + if ((cur.from == pos || cur.to == pos)) { if (found == null) { found = i; } else if (compareBidiLevel(order, cur.level, order[found].level)) { - bidiOther = found; + if (cur.from != cur.to) bidiOther = found; return i; } else { - bidiOther = i; + if (cur.from != cur.to) bidiOther = i; return found; } } } - bidiOther = null; return found; } From 3e614e48f31ed20364ffdde764049fa733f7b10f Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Tue, 26 Nov 2013 10:08:59 +0100 Subject: [PATCH 0036/4131] [closetag addon] Prevent action in another corner case (When slicing the part before the cursor from the tagname causes it to be empty.) Closes #1998 --- addon/edit/closetag.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/addon/edit/closetag.js b/addon/edit/closetag.js index 1da89ba6dc..bbd1c6e10c 100644 --- a/addon/edit/closetag.js +++ b/addon/edit/closetag.js @@ -53,7 +53,8 @@ if (tok.end > pos.ch) tagName = tagName.slice(0, tagName.length - tok.end + pos.ch); var lowerTagName = tagName.toLowerCase(); // Don't process the '>' at the end of an end-tag or self-closing tag - if (tok.type == "string" && (tok.end != pos.ch || !/[\"\']/.test(tok.string.charAt(tok.string.length - 1)) || tok.string.length == 1) || + if (!tagName || + tok.type == "string" && (tok.end != pos.ch || !/[\"\']/.test(tok.string.charAt(tok.string.length - 1)) || tok.string.length == 1) || tok.type == "tag" && state.type == "closeTag" || tok.string.indexOf("/") == (tok.string.length - 1) || // match something like dontCloseTags && indexOf(dontCloseTags, lowerTagName) > -1) From dafd825598f12dfe193ac85b17cc10372e2e4705 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Tue, 26 Nov 2013 10:23:35 +0100 Subject: [PATCH 0037/4131] Fix a bug in the bidi algorithm --- lib/codemirror.js | 4 ++-- test/test.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/codemirror.js b/lib/codemirror.js index fc2e971e7b..d1e82bccbf 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -5861,7 +5861,7 @@ window.CodeMirror = (function() { if (type == ",") types[i] = "N"; else if (type == "%") { for (var end = i + 1; end < len && types[end] == "%"; ++end) {} - var replace = (i && types[i-1] == "!") || (end < len - 1 && types[end] == "1") ? "1" : "N"; + var replace = (i && types[i-1] == "!") || (end < len && types[end] == "1") ? "1" : "N"; for (var j = i; j < end; ++j) types[j] = replace; i = end - 1; } @@ -5886,7 +5886,7 @@ window.CodeMirror = (function() { if (isNeutral.test(types[i])) { for (var end = i + 1; end < len && isNeutral.test(types[end]); ++end) {} var before = (i ? types[i-1] : outerType) == "L"; - var after = (end < len - 1 ? types[end] : outerType) == "L"; + var after = (end < len ? types[end] : outerType) == "L"; var replace = before || after ? "L" : "R"; for (var j = i; j < end; ++j) types[j] = replace; i = end - 1; diff --git a/test/test.js b/test/test.js index e5d9afdedd..dad089fa46 100644 --- a/test/test.js +++ b/test/test.js @@ -1141,7 +1141,7 @@ testCM("verticalMovementCommandsWrapping", function(cm) { testCM("rtlMovement", function(cm) { forEach(["خحج", "خحabcخحج", "abخحخحجcd", "abخde", "abخح2342خ1حج", "خ1ح2خح3حxج", - "خحcd", "1خحcd", "abcdeح1ج", "خمرحبها مها!", "foobarر", + "خحcd", "1خحcd", "abcdeح1ج", "خمرحبها مها!", "foobarر", "خ ة ق", ""], function(line) { var inv = line.charAt(0) == "خ"; cm.setValue(line + "\n"); cm.execCommand(inv ? "goLineEnd" : "goLineStart"); From bcf48d30b9170d7cf629452119a9b8fe52bd6c30 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Tue, 26 Nov 2013 10:56:33 +0100 Subject: [PATCH 0038/4131] Fix bug in IE bidi measuring hack --- lib/codemirror.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/codemirror.js b/lib/codemirror.js index d1e82bccbf..5a8fc92b5c 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -1113,7 +1113,7 @@ window.CodeMirror = (function() { } } if (!rect) rect = data[i] = measureRect(getRect(node)); - if (cur.measureRight) rect.right = getRect(cur.measureRight).left; + if (cur.measureRight) rect.right = getRect(cur.measureRight).left - outer.left; if (cur.leftSide) rect.leftSide = measureRect(getRect(cur.leftSide)); } removeChildren(cm.display.measure); From 755f3a7bafaff694f488c9df390528a5a578ce7e Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Tue, 26 Nov 2013 11:19:25 +0100 Subject: [PATCH 0039/4131] [javascript mode] Fix context tracking for comma-separated bodies Closes #2000 --- addon/tern/tern.js | 6 +++--- mode/javascript/javascript.js | 30 +++++++++++++++++------------- 2 files changed, 20 insertions(+), 16 deletions(-) diff --git a/addon/tern/tern.js b/addon/tern/tern.js index 1f18a657fb..7f83c4e4c0 100644 --- a/addon/tern/tern.js +++ b/addon/tern/tern.js @@ -251,7 +251,7 @@ var lex = inner.state.lexical; if (lex.info != "call") return; - var ch, pos = lex.pos || 0, tabSize = cm.getOption("tabSize"); + var ch, argPos = lex.pos || 0, tabSize = cm.getOption("tabSize"); for (var line = cm.getCursor().line, e = Math.max(0, line - 9), found = false; line >= e; --line) { var str = cm.getLine(line), extra = 0; for (var pos = 0;;) { @@ -268,7 +268,7 @@ var start = Pos(line, ch); var cache = ts.cachedArgHints; if (cache && cache.doc == cm.getDoc() && cmpPos(start, cache.start) == 0) - return showArgHints(ts, cm, pos); + return showArgHints(ts, cm, argPos); ts.request(cm, {type: "type", preferFunction: true, end: start}, function(error, data) { if (error || !data.type || !(/^fn\(/).test(data.type)) return; @@ -279,7 +279,7 @@ guess: data.guess, doc: cm.getDoc() }; - showArgHints(ts, cm, pos); + showArgHints(ts, cm, argPos); }); } diff --git a/mode/javascript/javascript.js b/mode/javascript/javascript.js index f27c06346c..a2974ee5c4 100644 --- a/mode/javascript/javascript.js +++ b/mode/javascript/javascript.js @@ -327,7 +327,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { function expressionInner(type, noComma) { if (cx.state.fatArrowAt == cx.stream.start) { var body = noComma ? arrowBodyNoComma : arrowBody; - if (type == "(") return cont(pushcontext, commasep(pattern, ")"), expect("=>"), body, popcontext); + if (type == "(") return cont(pushcontext, pushlex(")"), commasep(pattern, ")"), poplex, expect("=>"), body, popcontext); else if (type == "variable") return pass(pushcontext, pattern, expect("=>"), body, popcontext); } @@ -338,7 +338,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { if (type == "(") return cont(pushlex(")"), maybeexpression, comprehension, expect(")"), poplex, maybeop); if (type == "operator" || type == "spread") return cont(noComma ? expressionNoComma : expression); if (type == "[") return cont(pushlex("]"), expressionNoComma, maybeArrayComprehension, poplex, maybeop); - if (type == "{") return cont(commasep(objprop, "}"), maybeop); + if (type == "{") return contCommasep(objprop, "}", null, maybeop); return cont(); } function maybeexpression(type) { @@ -365,7 +365,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { } if (type == "quasi") { cx.cc.push(me); return quasi(value); } if (type == ";") return; - if (type == "(") return cont(commasep(expressionNoComma, ")", "call"), me); + if (type == "(") return contCommasep(expressionNoComma, ")", "call", me); if (type == ".") return cont(property, me); if (type == "[") return cont(pushlex("]"), maybeexpression, expect("]"), poplex, me); } @@ -418,7 +418,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { if (type == ":") return cont(expressionNoComma); if (type == "(") return pass(functiondef); } - function commasep(what, end, info) { + function commasep(what, end) { function proceed(type) { if (type == ",") { var lex = cx.state.lexical; @@ -430,10 +430,14 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { } return function(type) { if (type == end) return cont(); - if (info === false) return pass(what, proceed); - return pass(pushlex(end, info), what, proceed, poplex); + return pass(what, proceed); }; } + function contCommasep(what, end, info) { + for (var i = 3; i < arguments.length; i++) + cx.cc.push(arguments[i]); + return cont(pushlex(end, info), commasep(what, end), poplex); + } function block(type) { if (type == "}") return cont(); return pass(statement, block); @@ -449,8 +453,8 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { } function pattern(type, value) { if (type == "variable") { register(value); return cont(); } - if (type == "[") return cont(commasep(pattern, "]")); - if (type == "{") return cont(commasep(proppattern, "}")); + if (type == "[") return contCommasep(pattern, "]"); + if (type == "{") return contCommasep(proppattern, "}"); } function proppattern(type, value) { if (type == "variable" && !cx.stream.match(/^\s*:/, false)) { @@ -493,7 +497,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { function functiondef(type, value) { if (value == "*") {cx.marked = "keyword"; return cont(functiondef);} if (type == "variable") {register(value); return cont(functiondef);} - if (type == "(") return cont(pushcontext, commasep(funarg, ")"), statement, popcontext); + if (type == "(") return cont(pushcontext, pushlex(")"), commasep(funarg, ")"), poplex, statement, popcontext); } function funarg(type) { if (type == "spread") return cont(funarg); @@ -506,7 +510,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { if (value == "extends") return cont(expression); } function objlit(type) { - if (type == "{") return cont(commasep(objprop, "}")); + if (type == "{") return contCommasep(objprop, "}"); } function afterModule(type, value) { if (type == "string") return cont(statement); @@ -522,7 +526,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { return pass(importSpec, maybeFrom); } function importSpec(type, value) { - if (type == "{") return cont(commasep(importSpec, "}")); + if (type == "{") return contCommasep(importSpec, "}"); if (type == "variable") register(value); return cont(); } @@ -531,8 +535,8 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { } function maybeArrayComprehension(type) { if (type == "for") return pass(comprehension); - if (type == ",") return cont(commasep(expressionNoComma, "]", false)); - return pass(commasep(expressionNoComma, "]", false)); + if (type == ",") return cont(commasep(expressionNoComma, "]")); + return pass(commasep(expressionNoComma, "]")); } function comprehension(type) { if (type == "for") return cont(forspec, comprehension); From 3e710f9162bc3a030d3a157fea5a1dbeac864d26 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Tue, 26 Nov 2013 21:40:36 +0100 Subject: [PATCH 0040/4131] [javascript mode] Fix indentation after empty array literal Closes #2001 --- mode/javascript/javascript.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/mode/javascript/javascript.js b/mode/javascript/javascript.js index a2974ee5c4..c49b873317 100644 --- a/mode/javascript/javascript.js +++ b/mode/javascript/javascript.js @@ -337,7 +337,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { if (type == "keyword c") return cont(noComma ? maybeexpressionNoComma : maybeexpression); if (type == "(") return cont(pushlex(")"), maybeexpression, comprehension, expect(")"), poplex, maybeop); if (type == "operator" || type == "spread") return cont(noComma ? expressionNoComma : expression); - if (type == "[") return cont(pushlex("]"), expressionNoComma, maybeArrayComprehension, poplex, maybeop); + if (type == "[") return cont(pushlex("]"), arrayLiteral, poplex, maybeop); if (type == "{") return contCommasep(objprop, "}", null, maybeop); return cont(); } @@ -533,6 +533,10 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { function maybeFrom(_type, value) { if (value == "from") { cx.marked = "keyword"; return cont(expression); } } + function arrayLiteral(type) { + if (type == "]") return cont(); + return pass(expressionNoComma, maybeArrayComprehension); + } function maybeArrayComprehension(type) { if (type == "for") return pass(comprehension); if (type == ",") return cont(commasep(expressionNoComma, "]")); From 4841f63e21cc31af4c91aac3d566f67950809ed0 Mon Sep 17 00:00:00 2001 From: Pavel Strashkin Date: Tue, 26 Nov 2013 13:21:07 -0800 Subject: [PATCH 0041/4131] [docs] Make markText to be a ref within setBookmark --- doc/manual.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/manual.html b/doc/manual.html index a0c650e170..796663fc88 100644 --- a/doc/manual.html +++ b/doc/manual.html @@ -1273,7 +1273,7 @@

Text-marking methods

widget: Element
Can be used to display a DOM node at the current location of the bookmark (analogous to the replacedWith - option to markText).
+ option to markText).
insertLeft: boolean
By default, text typed when the cursor is on top of the bookmark will end up to the right of the bookmark. Set this option to true to make it go From 6b131f19e89f3656079c98ebcce67148c4244fce Mon Sep 17 00:00:00 2001 From: Enam Mijbah Noor Date: Wed, 27 Nov 2013 05:00:30 +0600 Subject: [PATCH 0042/4131] added missing keywords in jinja2 mode --- mode/jinja2/jinja2.js | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/mode/jinja2/jinja2.js b/mode/jinja2/jinja2.js index 16b06c48ef..b28af098d0 100644 --- a/mode/jinja2/jinja2.js +++ b/mode/jinja2/jinja2.js @@ -1,7 +1,17 @@ CodeMirror.defineMode("jinja2", function() { - var keywords = ["block", "endblock", "for", "endfor", "in", "true", "false", - "loop", "none", "self", "super", "if", "as", "not", "and", - "else", "import", "with", "without", "context"]; + var keywords = ["and", "as", "block", "endblock", "by", "cycle", "debug", "else", "elif", + "extends", "filter", "endfilter", "firstof", "for", + "endfor", "if", "endif", "ifchanged", "endifchanged", + "ifequal", "endifequal", "ifnotequal", + "endifnotequal", "in", "include", "load", "not", "now", "or", + "parsed", "regroup", "reversed", "spaceless", + "endspaceless", "ssi", "templatetag", "openblock", + "closeblock", "openvariable", "closevariable", + "openbrace", "closebrace", "opencomment", + "closecomment", "widthratio", "url", "with", "endwith", + "get_current_language", "trans", "noop", "blocktrans", + "endblocktrans", "get_available_languages", + "get_current_language_bidi", "plural"]; keywords = new RegExp("^((" + keywords.join(")|(") + "))\\b"); function tokenBase (stream, state) { From 268cc7422b21d95e8f3db0d346d4fec346bc76ff Mon Sep 17 00:00:00 2001 From: Yunchi Luo Date: Sun, 24 Nov 2013 11:48:48 -0500 Subject: [PATCH 0043/4131] [vim] Fix failing tests in ie8 --- keymap/vim.js | 20 +++++++++++++------- test/vim_test.js | 10 ++++++++-- 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/keymap/vim.js b/keymap/vim.js index dab10e21a4..164d51b1a4 100644 --- a/keymap/vim.js +++ b/keymap/vim.js @@ -2955,6 +2955,7 @@ exCommands[commandName](cm, params); } catch(e) { showConfirm(cm, e); + throw e; } }, parseInput_: function(cm, inputStream, result) { @@ -3115,7 +3116,7 @@ var args = new CodeMirror.StringStream(params.argString); if (args.eat('!')) { reverse = true; } if (args.eol()) { return; } - if (!args.eatSpace()) { throw new Error('invalid arguments ' + args.match(/.*/)[0]); } + if (!args.eatSpace()) { return 'Invalid arguments'; } var opts = args.match(/[a-z]+/); if (opts) { opts = opts[0]; @@ -3124,13 +3125,17 @@ var decimal = opts.indexOf('d') != -1 && 1; var hex = opts.indexOf('x') != -1 && 1; var octal = opts.indexOf('o') != -1 && 1; - if (decimal + hex + octal > 1) { throw new Error('invalid arguments'); } + if (decimal + hex + octal > 1) { return 'Invalid arguments'; } number = decimal && 'decimal' || hex && 'hex' || octal && 'octal'; } - if (args.eatSpace() && args.match(/\/.*\//)) { throw new Error('patterns not supported'); } + if (args.eatSpace() && args.match(/\/.*\//)) { 'patterns not supported'; } } } - parseArgs(); + var err = parseArgs(); + if (err) { + showConfirm(cm, err + ': ' + params.argString); + return; + } var lineStart = params.line || cm.firstLine(); var lineEnd = params.lineEnd || params.line || cm.lastLine(); if (lineStart == lineEnd) { return; } @@ -3251,13 +3256,13 @@ clearSearchHighlight(cm); }, delmarks: function(cm, params) { - if (!params.argString || !params.argString.trim()) { + if (!params.argString || !trim(params.argString)) { showConfirm(cm, 'Argument required'); return; } var state = cm.state.vim; - var stream = new CodeMirror.StringStream(params.argString.trim()); + var stream = new CodeMirror.StringStream(trim(params.argString)); while (!stream.eol()) { stream.eatSpace(); @@ -3394,7 +3399,8 @@ // Actually do replace. next(); if (done) { - throw new Error('No matches for ' + query.source); + showConfirm(cm, 'No matches for ' + query.source); + return; } if (!confirm) { replaceAll(); diff --git a/test/vim_test.js b/test/vim_test.js index fe272551c5..c65b5cad03 100644 --- a/test/vim_test.js +++ b/test/vim_test.js @@ -96,6 +96,12 @@ function copyCursor(cur) { return { ch: cur.ch, line: cur.line }; } +function forEach(arr, func) { + for (var i = 0; i < arr.length; i++) { + func(arr[i]); + } +} + function testVim(name, run, opts, expectedFail) { var vimOpts = { lineNumbers: true, @@ -1047,7 +1053,7 @@ testVim('ctrl-x', function(cm, vim, helpers) { eq('-3', cm.getValue()); }, {value: '0'}); testVim('/ search forward', function(cm, vim, helpers) { - ['', ''].forEach(function(key) { + forEach(['', ''], function(key) { cm.setCursor(0, 0); helpers.doKeys(key); helpers.assertCursorAt(0, 5); @@ -2080,7 +2086,7 @@ testVim('[(, ])', function(cm, vim, helpers) { helpers.assertCursorAt(8,0); }, { value: squareBracketMotionSandbox}); testVim('[*, ]*, [/, ]/', function(cm, vim, helpers) { - ['*', '/'].forEach(function(key){ + forEach(['*', '/'], function(key){ cm.setCursor(7, 0); helpers.doKeys('2', '[', key); helpers.assertCursorAt(2,2); From 8f7c87245d5c0a8841748c180b24401a51ab08d2 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 28 Nov 2013 13:38:24 +0100 Subject: [PATCH 0044/4131] [search addon] Make overlay's case-sensitivity correspond to search Closes #2008 --- addon/search/search.js | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/addon/search/search.js b/addon/search/search.js index ddb6eeea90..049f72f3dc 100644 --- a/addon/search/search.js +++ b/addon/search/search.js @@ -7,7 +7,15 @@ // Ctrl-G. (function() { - function searchOverlay(query) { + function searchOverlay(query, caseInsensitive) { + var startChar; + if (typeof query == "string") { + startChar = query.charAt(0); + query = new RegExp("^" + query.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"), + caseInsensitive ? "i" : ""); + } else { + query = new RegExp("^(?:" + query.source + ")", query.ignoreCase ? "i" : ""); + } if (typeof query == "string") return {token: function(stream) { if (stream.match(query)) return "searching"; stream.next(); @@ -17,6 +25,8 @@ if (stream.match(query)) return "searching"; while (!stream.eol()) { stream.next(); + if (startChar) + stream.skipTo(startChar) || stream.skipToEnd(); if (stream.match(query, false)) break; } }}; @@ -29,9 +39,12 @@ function getSearchState(cm) { return cm.state.search || (cm.state.search = new SearchState()); } + function queryCaseInsensitive(query) { + return typeof query == "string" && query == query.toLowerCase(); + } function getSearchCursor(cm, query, pos) { // Heuristic: if the query string is all lowercase, do a case insensitive search. - return cm.getSearchCursor(query, pos, typeof query == "string" && query == query.toLowerCase()); + return cm.getSearchCursor(query, pos, queryCaseInsensitive(query)); } function dialog(cm, text, shortText, deflt, f) { if (cm.openDialog) cm.openDialog(text, f, {value: deflt}); @@ -54,7 +67,7 @@ cm.operation(function() { if (!query || state.query) return; state.query = parseQuery(query); - cm.removeOverlay(state.overlay); + cm.removeOverlay(state.overlay, queryCaseInsensitive(state.query)); state.overlay = searchOverlay(state.query); cm.addOverlay(state.overlay); state.posFrom = state.posTo = cm.getCursor(); From 4b3cbc1f83aff39f481c07883a5b98c82bdfabf1 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 28 Nov 2013 16:49:46 +0100 Subject: [PATCH 0045/4131] Prevent gutter height from forcing a scrollbar when none is needed Issue #1999 --- lib/codemirror.js | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/codemirror.js b/lib/codemirror.js index 5a8fc92b5c..0e5592fb17 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -535,6 +535,7 @@ window.CodeMirror = (function() { } display.showingFrom = from; display.showingTo = to; + display.gutters.style.height = ""; updateHeightsInViewport(cm); updateViewOffset(cm); From 45f673a108dabcb2d1ace294286aa233da35dfaa Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 28 Nov 2013 17:48:27 +0100 Subject: [PATCH 0046/4131] [hardwrap addon] Preserve trailing whitespace --- addon/fold/indent-fold.js | 4 ++-- addon/wrap/hardwrap.js | 18 +++++++++++++----- demo/hardwrap.html | 7 ++++++- 3 files changed, 21 insertions(+), 8 deletions(-) diff --git a/addon/fold/indent-fold.js b/addon/fold/indent-fold.js index 1bd600be42..434c2bc5ca 100644 --- a/addon/fold/indent-fold.js +++ b/addon/fold/indent-fold.js @@ -1,8 +1,8 @@ CodeMirror.registerHelper("fold", "indent", function(cm, start) { var tabSize = cm.getOption("tabSize"), firstLine = cm.getLine(start.line); if (!/\S/.test(firstLine)) return; - var getIndent = function(lineNum) { - return CodeMirror.countColumn(lineNum, null, tabSize); + var getIndent = function(line) { + return CodeMirror.countColumn(line, null, tabSize); }; var myIndent = getIndent(firstLine); var lastLineInFold = null; diff --git a/addon/wrap/hardwrap.js b/addon/wrap/hardwrap.js index f252ffc9e9..9260c75bbb 100644 --- a/addon/wrap/hardwrap.js +++ b/addon/wrap/hardwrap.js @@ -36,31 +36,39 @@ var killTrailing = options.killTrailingSpace !== false; var changes = [], curLine = "", curNo = from.line; var lines = cm.getRange(from, to, false); + var leadingSpace = lines[0].match(/^[ \t]*/)[0]; + for (var i = 0; i < lines.length; ++i) { var text = lines[i], oldLen = curLine.length, spaceInserted = 0; if (curLine && text && !wrapOn.test(curLine.charAt(curLine.length - 1) + text.charAt(0))) { curLine += " "; spaceInserted = 1; } + var spaceTrimmed = ""; + if (i) { + spaceTrimmed = text.match(/^\s*/)[0]; + text = text.slice(spaceTrimmed.length); + } curLine += text; if (i) { - var firstBreak = curLine.length > column && findBreakPoint(curLine, column, wrapOn, killTrailing); + var firstBreak = curLine.length > column && leadingSpace == spaceTrimmed && + findBreakPoint(curLine, column, wrapOn, killTrailing); // If this isn't broken, or is broken at a different point, remove old break if (!firstBreak || firstBreak.from != oldLen || firstBreak.to != oldLen + spaceInserted) { changes.push({text: spaceInserted ? " " : "", from: Pos(curNo, oldLen), - to: Pos(curNo + 1, 0)}); + to: Pos(curNo + 1, spaceTrimmed.length)}); } else { - curLine = text; + curLine = leadingSpace + text; ++curNo; } } while (curLine.length > column) { var bp = findBreakPoint(curLine, column, wrapOn, killTrailing); - changes.push({text: "\n", + changes.push({text: "\n" + leadingSpace, from: Pos(curNo, bp.from), to: Pos(curNo, bp.to)}); - curLine = curLine.slice(bp.to); + curLine = leadingSpace + curLine.slice(bp.to); ++curNo; } } diff --git a/demo/hardwrap.html b/demo/hardwrap.html index a53d68dec6..6cfd9c87c2 100644 --- a/demo/hardwrap.html +++ b/demo/hardwrap.html @@ -55,10 +55,15 @@

Hard-wrapping Demo

+ diff --git a/test/search_test.js b/test/search_test.js new file mode 100644 index 0000000000..c6aaa5809e --- /dev/null +++ b/test/search_test.js @@ -0,0 +1,61 @@ +(function() { + "use strict"; + + function test(name) { + var text = Array.prototype.slice.call(arguments, 1, arguments.length - 1).join("\n"); + var body = arguments[arguments.length - 1]; + return window.test("search_" + name, function() { + body(new CodeMirror.Doc(text)); + }); + } + + function run(doc, query, insensitive) { + var cursor = doc.getSearchCursor(query, null, insensitive); + for (var i = 3; i < arguments.length; i += 4) { + var found = cursor.findNext(); + is(found, "not enough results (forward)"); + eqPos(Pos(arguments[i], arguments[i + 1]), cursor.from(), "from, forward, " + (i - 3) / 4); + eqPos(Pos(arguments[i + 2], arguments[i + 3]), cursor.to(), "to, forward, " + (i - 3) / 4); + } + is(!cursor.findNext(), "too many matches (forward)"); + for (var i = arguments.length - 4; i >= 3; i -= 4) { + var found = cursor.findPrevious(); + is(found, "not enough results (backwards)"); + eqPos(Pos(arguments[i], arguments[i + 1]), cursor.from(), "from, backwards, " + (i - 3) / 4); + eqPos(Pos(arguments[i + 2], arguments[i + 3]), cursor.to(), "to, backwards, " + (i - 3) / 4); + } + is(!cursor.findPrevious(), "too many matches (backwards)"); + } + + test("simple", "abcdefg", "abcdefg", function(doc) { + run(doc, "cde", false, 0, 2, 0, 5, 1, 2, 1, 5); + }); + + test("multiline", "hallo", "goodbye", function(doc) { + run(doc, "llo\ngoo", false, 0, 2, 1, 3); + run(doc, "blah\nhall", false); + run(doc, "bye\neye", false); + }); + + test("regexp", "abcde", "abcde", function(doc) { + run(doc, /bcd/, false, 0, 1, 0, 4, 1, 1, 1, 4); + run(doc, /BCD/, false); + run(doc, /BCD/i, false, 0, 1, 0, 4, 1, 1, 1, 4); + }); + + test("insensitive", "hallo", "HALLO", "oink", "hAllO", function(doc) { + run(doc, "All", false, 3, 1, 3, 4); + run(doc, "All", true, 0, 1, 0, 4, 1, 1, 1, 4, 3, 1, 3, 4); + }); + + test("multilineInsensitive", "zie ginds komT", "De Stoomboot", "uit Spanje weer aan", function(doc) { + run(doc, "komt\nde stoomboot\nuit", false); + run(doc, "komt\nde stoomboot\nuit", true, 0, 10, 2, 3); + run(doc, "kOMt\ndE stOOmboot\nuiT", true, 0, 10, 2, 3); + }); + + test("expandingCaseFold", "İİ İİ", "uu uu", function(doc) { + run(doc, "", true, 0, 8, 0, 12, 1, 8, 1, 12); + run(doc, "İİ", true, 0, 3, 0, 5, 0, 6, 0, 8); + }); +})(); From 48d11dad21e6cca117d0568469a7a3df6d90276d Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Tue, 3 Dec 2013 21:09:56 +0100 Subject: [PATCH 0051/4131] [activeline addon] Optimize Issue #2007 --- addon/selection/active-line.js | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/addon/selection/active-line.js b/addon/selection/active-line.js index e50508653a..35e989dcf8 100644 --- a/addon/selection/active-line.js +++ b/addon/selection/active-line.js @@ -12,10 +12,10 @@ CodeMirror.defineOption("styleActiveLine", false, function(cm, val, old) { var prev = old && old != CodeMirror.Init; if (val && !prev) { - updateActiveLine(cm); - cm.on("cursorActivity", updateActiveLine); + updateActiveLine(cm, cm.getCursor().line); + cm.on("beforeSelectionChange", selectionChange); } else if (!val && prev) { - cm.off("cursorActivity", updateActiveLine); + cm.off("beforeSelecionChange", selectionChange); clearActiveLine(cm); delete cm.state.activeLine; } @@ -28,12 +28,18 @@ } } - function updateActiveLine(cm) { - var line = cm.getLineHandleVisualStart(cm.getCursor().line); + function updateActiveLine(cm, selectedLine) { + var line = cm.getLineHandleVisualStart(selectedLine); if (cm.state.activeLine == line) return; - clearActiveLine(cm); - cm.addLineClass(line, "wrap", WRAP_CLASS); - cm.addLineClass(line, "background", BACK_CLASS); - cm.state.activeLine = line; + cm.operation(function() { + clearActiveLine(cm); + cm.addLineClass(line, "wrap", WRAP_CLASS); + cm.addLineClass(line, "background", BACK_CLASS); + cm.state.activeLine = line; + }); + } + + function selectionChange(cm, sel) { + updateActiveLine(cm, sel.head.line); } })(); From 8914577694e56be06c1239755a20a383d9841ee9 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Tue, 3 Dec 2013 21:27:37 +0100 Subject: [PATCH 0052/4131] Add an (experimental) hideFirstChars method to StringStream Issue #2019 --- lib/codemirror.js | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/lib/codemirror.js b/lib/codemirror.js index 8be133ace0..a98888256b 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -3710,11 +3710,12 @@ window.CodeMirror = (function() { this.string = string; this.tabSize = tabSize || 8; this.lastColumnPos = this.lastColumnValue = 0; + this.lineStart = 0; } StringStream.prototype = { eol: function() {return this.pos >= this.string.length;}, - sol: function() {return this.pos == 0;}, + sol: function() {return this.pos == this.lineStart;}, peek: function() {return this.string.charAt(this.pos) || undefined;}, next: function() { if (this.pos < this.string.length) @@ -3747,9 +3748,12 @@ window.CodeMirror = (function() { this.lastColumnValue = countColumn(this.string, this.start, this.tabSize, this.lastColumnPos, this.lastColumnValue); this.lastColumnPos = this.start; } - return this.lastColumnValue; + return this.lastColumnValue - (this.lineStart ? countColumn(this.string, this.lineStart, this.tabSize) : 0); + }, + indentation: function() { + return countColumn(this.string, null, this.tabSize) - + (this.lineStart ? countColumn(this.string, this.lineStart, this.tabSize) : 0); }, - indentation: function() {return countColumn(this.string, null, this.tabSize);}, match: function(pattern, consume, caseInsensitive) { if (typeof pattern == "string") { var cased = function(str) {return caseInsensitive ? str.toLowerCase() : str;}; @@ -3765,7 +3769,12 @@ window.CodeMirror = (function() { return match; } }, - current: function(){return this.string.slice(this.start, this.pos);} + current: function(){return this.string.slice(this.start, this.pos);}, + hideFirstChars: function(n, inner) { + this.lineStart += n; + try { return inner(); } + finally { this.lineStart -= n; } + } }; CodeMirror.StringStream = StringStream; From e7b737c8a470b210ac4b8fb342c126d4d19f47b0 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Tue, 3 Dec 2013 21:51:07 +0100 Subject: [PATCH 0053/4131] Disable a search test on Phantom Due to unexplainable hanging. --- test/search_test.js | 1 + 1 file changed, 1 insertion(+) diff --git a/test/search_test.js b/test/search_test.js index c6aaa5809e..04a1e685ab 100644 --- a/test/search_test.js +++ b/test/search_test.js @@ -55,6 +55,7 @@ }); test("expandingCaseFold", "İİ İİ", "uu uu", function(doc) { + if (phantom) return; // A Phantom bug makes this hang run(doc, "", true, 0, 8, 0, 12, 1, 8, 1, 12); run(doc, "İİ", true, 0, 3, 0, 5, 0, 6, 0, 8); }); From 004734cfbd0e1e0e109675dd9d51d985fdfe6ecb Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Wed, 4 Dec 2013 15:55:05 +0100 Subject: [PATCH 0054/4131] Replace accidental emdash with dash in regexp --- lib/codemirror.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/codemirror.js b/lib/codemirror.js index a98888256b..7456147289 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -5522,7 +5522,7 @@ window.CodeMirror = (function() { return true; } - var isExtendingChar = /[\u0300-\u036F\u0483-\u0487\u0488-\u0489\u0591-\u05BD\u05BF\u05C1-\u05C2\u05C4-\u05C5\u05C7\u0610-\u061A\u064B-\u065F\u0670\u06D6-\u06DC\u06DF-\u06E4\u06E7-\u06E8\u06EA-\u06ED\uA66F\u1DC0–\u1DFF\u20D0–\u20FF\uA670-\uA672\uA674-\uA67D\uA69F\udc00-\udfff\uFE20–\uFE2F]/; + var isExtendingChar = window.ext = /[\u0300-\u036F\u0483-\u0487\u0488-\u0489\u0591-\u05BD\u05BF\u05C1-\u05C2\u05C4-\u05C5\u05C7\u0610-\u061A\u064B-\u065F\u0670\u06D6-\u06DC\u06DF-\u06E4\u06E7-\u06E8\u06EA-\u06ED\uA66F\u1DC0–\u1DFF\u20D0–\u20FF\uA670-\uA672\uA674-\uA67D\uA69F\udc00-\udfff\uFE20-\uFE2F]/; // DOM UTILITIES From 58ce53c1580339375d16e9111791ed5e8e3634b8 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Wed, 4 Dec 2013 16:05:19 +0100 Subject: [PATCH 0055/4131] Remove all non-ascii text from codemirror.js --- lib/codemirror.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/codemirror.js b/lib/codemirror.js index 7456147289..dc3451b98c 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -5522,7 +5522,7 @@ window.CodeMirror = (function() { return true; } - var isExtendingChar = window.ext = /[\u0300-\u036F\u0483-\u0487\u0488-\u0489\u0591-\u05BD\u05BF\u05C1-\u05C2\u05C4-\u05C5\u05C7\u0610-\u061A\u064B-\u065F\u0670\u06D6-\u06DC\u06DF-\u06E4\u06E7-\u06E8\u06EA-\u06ED\uA66F\u1DC0–\u1DFF\u20D0–\u20FF\uA670-\uA672\uA674-\uA67D\uA69F\udc00-\udfff\uFE20-\uFE2F]/; + var isExtendingChar = /[\u0300-\u036F\u0483-\u0487\u0488-\u0489\u0591-\u05BD\u05BF\u05C1-\u05C2\u05C4-\u05C5\u05C7\u0610-\u061A\u064B-\u065F\u0670\u06D6-\u06DC\u06DF-\u06E4\u06E7-\u06E8\u06EA-\u06ED\uA66F\u1DC0-\u1DFF\u20D0-\u20FF\uA670-\uA672\uA674-\uA67D\uA69F\udc00-\udfff\uFE20-\uFE2F]/; // DOM UTILITIES @@ -5595,7 +5595,7 @@ window.CodeMirror = (function() { if (/\w/.test(str.charAt(i - 2)) && /[^\-?\.]/.test(str.charAt(i))) return true; if (i > 2 && /[\d\.,]/.test(str.charAt(i - 2)) && /[\d\.,]/.test(str.charAt(i))) return false; } - return /[~!#%&*)=+}\]\\|\"\.>,:;][({[<]|-[^\-?\.\u2010-\u201f\u2026]|\?[\w~`@#$%\^&*(_=+{[|><]|…[\w~`@#$%\^&*(_=+{[><]/.test(str.slice(i - 1, i + 1)); + return /[~!#%&*)=+}\]\\|\"\.>,:;][({[<]|-[^\-?\.\u2010-\u201f\u2026]|\?[\w~`@#$%\^&*(_=+{[|><]|\u2026[\w~`@#$%\^&*(_=+{[><]/.test(str.slice(i - 1, i + 1)); }; var knownScrollbarWidth; From 6b53fa295b58b4b19a42d61034ad2f1f40c43322 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 5 Dec 2013 12:25:49 +0100 Subject: [PATCH 0056/4131] [merge addon] Support passing in document objects as content --- addon/merge/merge.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/addon/merge/merge.js b/addon/merge/merge.js index 70341e4d12..89f852652b 100644 --- a/addon/merge/merge.js +++ b/addon/merge/merge.js @@ -29,7 +29,7 @@ this.edit = this.mv.edit; this.orig = CodeMirror(pane, copyObj({value: orig, readOnly: true}, copyObj(options))); - this.diff = getDiff(orig, options.value); + this.diff = getDiff(asString(orig), asString(options.value)); this.diffOutOfDate = false; this.showDifferences = options.showDifferences !== false; @@ -352,6 +352,11 @@ } }; + function asString(obj) { + if (typeof obj == "string") return obj; + else return obj.getValue(); + } + // Operations on diffs var dmp = new diff_match_patch(); From 524159fc16f52cbdb11b65480dc8825d3fa3e5fd Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 5 Dec 2013 15:39:32 +0100 Subject: [PATCH 0057/4131] [merge demo] Remove layout-breaking css rule --- demo/merge.html | 1 - 1 file changed, 1 deletion(-) diff --git a/demo/merge.html b/demo/merge.html index d2df900c20..fc272f0652 100644 --- a/demo/merge.html +++ b/demo/merge.html @@ -12,7 +12,6 @@ + + + + + + + + + + + + + +
-

Code Folding Demo

-
-
JavaScript:
-
HTML:
-
- -
+ + + diff --git a/demo/html5complete.html b/demo/html5complete.html index 899260aa20..94ced527d0 100644 --- a/demo/html5complete.html +++ b/demo/html5complete.html @@ -1,37 +1,41 @@ -CodeMirror: HTML completion demo - - - - - - - - - - - - - - - - -
-

HTML completion demo

+ + CodeMirror: HTML completion demo + + + + + + + + + + + + + + + + + + + +
+

HTML completion demo

Shows the XML completer parameterized with information about the tags in HTML. @@ -40,15 +44,13 @@

HTML completion demo

+ diff --git a/doc/manual.html b/doc/manual.html index 98d7fb88ec..0dc120ddf3 100644 --- a/doc/manual.html +++ b/doc/manual.html @@ -1533,18 +1533,35 @@

Mode, state, and token-related methods

unstyled tokens, and a string, potentially containing multiple space-separated style names, otherwise.
+
cm.getHelpers(pos: {line, ch}, type: string) → array<helper>
+
Fetch the set of applicable helper values for the given + position. Helpers provide a way to look up functionality + appropriate for a mode. The type argument provides + the helper namespace (see + registerHelper), in + which the values will be looked up. When the mode itself has a + property that corresponds to the type, that + directly determines the keys that are used to look up the helper + values (it may be either a single string, or an array of + strings). Failing that, the mode's helperType + property and finally the mode's name are used.
+
For example, the JavaScript mode has a + property fold containing "brace". When + the brace-fold addon is loaded, that defines a + helper named brace in the fold + namespace. This is then used by + the foldcode addon to + figure out that it can use that folding function to fold + JavaScript code.
+
When any 'global' + helpers are defined for the given namespace, their predicates + are called on the current mode and editor, and all those that + declare they are applicable will also be added to the array that + is returned.
+
cm.getHelper(pos: {line, ch}, type: string) → helper
-
Fetch appropriate helper for the given position. Helpers - provide a way to look up functionality appropriate for a mode. - The type argument provides the helper namespace - (see - also registerHelper), - in which the value will be looked up. The key that is used - depends on the mode active at the given - position. If the mode object contains a property with the same - name as the type argument, that is tried first. - Next, the mode's helperType, if any, is tried. And - finally, the mode's name.
+
Returns the first applicable helper value. + See getHelpers.
cm.getStateAfter(?line: integer, ?precise: boolean) → object
Returns the mode's parser state, if any, at the end of the @@ -1689,7 +1706,7 @@

Static properties

(with the instance as argument) whenever a new CodeMirror instance is initialized.
-
CodeMirror.registerHelper(type: string, name: string, value: helper)
+
CodeMirror.registerHelper(type: string, name: string, value: helper)
Registers a helper value with the given name in the given namespace (type). This is used to define functionality that may be looked up by mode. Will create (if it @@ -1700,6 +1717,14 @@

Static properties

myFoo), the value CodeMirror.hint.foo will point to myFoo.
+
CodeMirror.registerGlobalHelper(type: string, name: string, predicate: fn(mode, CodeMirror), value: helper)
+
Acts + like registerHelper, + but also registers this helper as 'global', meaning that it will + be included by getHelpers + whenever the given predicate returns true when + called with the local mode and editor.
+
CodeMirror.Pos(line: integer, ?ch: integer)
A constructor for the {line, ch} objects that are used to represent positions in editor documents.
@@ -1881,11 +1906,12 @@

Addons

supporting the following properties:
rangeFinder: fn(CodeMirror, Pos)
-
The function that is used to find foldable ranges. If this - is not directly passed, it will - call getHelper with - a "fold" type to find one that's appropriate for - the mode. There are files in +
The function that is used to find + foldable ranges. If this is not directly passed, it will + default to CodeMirror.fold.auto, which + uses getHelpers with + a "fold" type to find folding functions + appropriate for the local mode. There are files in the addon/fold/ directory providing CodeMirror.fold.brace, which finds blocks in brace languages (JavaScript, C, Java, @@ -1944,8 +1970,8 @@

Addons

rangeFinder: fn(CodeMirror, Pos)
The range-finder function to use when determining whether something can be folded. When not - given, getHelper will be - used to determine a default.
+ given, CodeMirror.fold.auto + will be used as default.
Demo here. @@ -2017,9 +2043,17 @@

Addons

is an array of strings or objects (the completions), and from and to give the start and end of the token that is being completed as {line, ch} - objects. If no hinting function is given, the addon will try to - use getHelper with - the "hint" type to find one. When completions + objects. +
If no hinting function is given, the addon will + use CodeMirror.hint.auto, with + calls getHelpers with + the "hint" type to find applicable hinting + functions, and tries them one by one. If that fails, it looks + for a "hintWords" helper to fetch a list of + completable words for the mode, and + uses CodeMirror.hint.fromList to complete from + those.
+
When completions aren't simple strings, they should be objects with the folowing properties:
@@ -2523,6 +2557,13 @@

Writing CodeMirror Modes

object specifying a mode, as in the mode option.

+

If a mode specification wants to add some properties to the + resulting mode object, typically for use + with getHelpers, it may + contain a modeProps property, which holds an object. + This object's properties will be copied to the actual mode + object.

+

Sometimes, it is useful to add or override mode object properties from external code. The CodeMirror.extendMode function diff --git a/lib/codemirror.js b/lib/codemirror.js index ba24bbcf3d..7b1b67dc0e 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -2977,11 +2977,31 @@ window.CodeMirror = (function() { }, getHelper: function(pos, type) { - if (!helpers.hasOwnProperty(type)) return; + return this.getHelpers(pos, type)[0]; + }, + + getHelpers: function(pos, type) { + var found = []; + if (!helpers.hasOwnProperty(type)) return helpers; var help = helpers[type], mode = this.getModeAt(pos); - return mode[type] && help[mode[type]] || - mode.helperType && help[mode.helperType] || - help[mode.name]; + if (typeof mode[type] == "string") { + if (help[mode[type]]) found.push(help[mode[type]]); + } else if (mode[type]) { + for (var i = 0; i < mode[type].length; i++) { + var val = help[mode[type][i]]; + if (val) found.push(val); + } + } else if (mode.helperType && help[mode.helperType]) { + found.push(help[mode.helperType]); + } else if (help[mode.name]) { + found.push(help[mode.name]); + } + for (var i = 0; i < help._global.length; i++) { + var cur = help._global[i]; + if (cur.pred(mode, this) && indexOf(found, cur.val) == -1) + found.push(cur.val); + } + return found; }, getStateAfter: function(line, precise) { @@ -3413,6 +3433,9 @@ window.CodeMirror = (function() { } } modeObj.name = spec.name; + if (spec.helperType) modeObj.helperType = spec.helperType; + if (spec.modeProps) for (var prop in spec.modeProps) + modeObj[prop] = spec.modeProps[prop]; return modeObj; }; @@ -3443,9 +3466,13 @@ window.CodeMirror = (function() { var helpers = CodeMirror.helpers = {}; CodeMirror.registerHelper = function(type, name, value) { - if (!helpers.hasOwnProperty(type)) helpers[type] = CodeMirror[type] = {}; + if (!helpers.hasOwnProperty(type)) helpers[type] = CodeMirror[type] = {_global: []}; helpers[type][name] = value; }; + CodeMirror.registerGlobalHelper = function(type, name, predicate, value) { + CodeMirror.registerHelper(type, name, value); + helpers[type]._global.push({pred: predicate, val: value}); + }; // UTILITIES diff --git a/mode/clike/clike.js b/mode/clike/clike.js index f6626cd0ea..4e4988dd81 100644 --- a/mode/clike/clike.js +++ b/mode/clike/clike.js @@ -203,18 +203,34 @@ CodeMirror.defineMode("clike", function(config, parserConfig) { return "string"; } - function mimes(ms, mode) { - for (var i = 0; i < ms.length; ++i) CodeMirror.defineMIME(ms[i], mode); + function def(mimes, mode) { + var words = []; + function add(obj) { + if (obj) for (var prop in obj) if (obj.hasOwnProperty(prop)) + words.push(prop); + } + add(mode.keywords); + add(mode.builtin); + add(mode.atoms); + if (words.length) { + mode.helperType = mimes[0]; + CodeMirror.registerHelper("hintWords", mimes[0], words); + } + + for (var i = 0; i < mimes.length; ++i) + CodeMirror.defineMIME(mimes[i], mode); } - mimes(["text/x-csrc", "text/x-c", "text/x-chdr"], { + def(["text/x-csrc", "text/x-c", "text/x-chdr"], { name: "clike", keywords: words(cKeywords), blockKeywords: words("case do else for if switch while struct"), atoms: words("null"), - hooks: {"#": cppHook} + hooks: {"#": cppHook}, + modeProps: {fold: ["brace", "include"]} }); - mimes(["text/x-c++src", "text/x-c++hdr"], { + + def(["text/x-c++src", "text/x-c++hdr"], { name: "clike", keywords: words(cKeywords + " asm dynamic_cast namespace reinterpret_cast try bool explicit new " + "static_cast typeid catch operator template typename class friend private " + @@ -222,7 +238,8 @@ CodeMirror.defineMode("clike", function(config, parserConfig) { "wchar_t"), blockKeywords: words("catch class do else finally for if struct switch try while"), atoms: words("true false null"), - hooks: {"#": cppHook} + hooks: {"#": cppHook}, + modeProps: {fold: ["brace", "include"]} }); CodeMirror.defineMIME("text/x-java", { name: "clike", @@ -238,7 +255,8 @@ CodeMirror.defineMode("clike", function(config, parserConfig) { stream.eatWhile(/[\w\$_]/); return "meta"; } - } + }, + modeProps: {fold: ["brace", "import"]} }); CodeMirror.defineMIME("text/x-csharp", { name: "clike", @@ -303,7 +321,7 @@ CodeMirror.defineMode("clike", function(config, parserConfig) { } } }); - mimes(["x-shader/x-vertex", "x-shader/x-fragment"], { + def(["x-shader/x-vertex", "x-shader/x-fragment"], { name: "clike", keywords: words("float int bool void " + "vec2 vec3 vec4 ivec2 ivec3 ivec4 bvec2 bvec3 bvec4 " + @@ -357,6 +375,7 @@ CodeMirror.defineMode("clike", function(config, parserConfig) { "gl_MaxVertexTextureImageUnits gl_MaxTextureImageUnits " + "gl_MaxFragmentUniformComponents gl_MaxCombineTextureImageUnits " + "gl_MaxDrawBuffers"), - hooks: {"#": cppHook} + hooks: {"#": cppHook}, + modeProps: {fold: ["brace", "include"]} }); }()); diff --git a/test/test.js b/test/test.js index 439f2412af..86b0bfe178 100644 --- a/test/test.js +++ b/test/test.js @@ -1625,3 +1625,22 @@ testCM("lineStyleFromMode", function(cm) { eq(parenElts[0].nodeName, "DIV"); is(!/parens.*parens/.test(parenElts[0].className)); }, {value: "line1: [br] [br]\nline2: (par) (par)\nline3: nothing"}); + +CodeMirror.registerHelper("xxx", "a", "A"); +CodeMirror.registerHelper("xxx", "b", "B"); +CodeMirror.defineMode("yyy", function() { + return { + token: function(stream) { stream.skipToEnd(); }, + xxx: ["a", "b", "q"] + }; +}); +CodeMirror.registerGlobalHelper("xxx", "c", function(m) { return m.enableC; }, "C"); + +testCM("helpers", function(cm) { + cm.setOption("mode", "yyy"); + eq(cm.getHelpers(Pos(0, 0), "xxx").join("/"), "A/B"); + cm.setOption("mode", {name: "yyy", modeProps: {xxx: "b", enableC: true}}); + eq(cm.getHelpers(Pos(0, 0), "xxx").join("/"), "B/C"); + cm.setOption("mode", "javascript"); + eq(cm.getHelpers(Pos(0, 0), "xxx").join("/"), ""); +}); From 48b40a43680091b05e85bfcf709b32384079a874 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Tue, 10 Dec 2013 11:43:36 +0100 Subject: [PATCH 0081/4131] [css mode] Refactor, step 1 (tokenizer) --- mode/css/css.js | 56 +++++++++++++++++++------------------------ mode/css/scss_test.js | 38 ++++++++++++++--------------- mode/css/test.js | 36 ++++++++++++++-------------- 3 files changed, 61 insertions(+), 69 deletions(-) diff --git a/mode/css/css.js b/mode/css/css.js index d8c30cf33d..655261d887 100644 --- a/mode/css/css.js +++ b/mode/css/css.js @@ -18,57 +18,48 @@ CodeMirror.defineMode("css", function(config, parserConfig) { function tokenBase(stream, state) { var ch = stream.next(); if (hooks[ch]) { - // result[0] is style and result[1] is type var result = hooks[ch](stream, state); if (result !== false) return result; } - if (ch == "@") {stream.eatWhile(/[\w\\\-]/); return ret("def", stream.current());} - else if (ch == "=") ret(null, "compare"); - else if ((ch == "~" || ch == "|") && stream.eat("=")) return ret(null, "compare"); - else if (ch == "\"" || ch == "'") { + if (ch == "@") { + stream.eatWhile(/[\w\\\-]/); + return ret("def", stream.current()); + } else if (ch == "=" || (ch == "~" || ch == "|") && stream.eat("=")) { + return ret(null, "compare"); + } else if (ch == "\"" || ch == "'") { state.tokenize = tokenString(ch); return state.tokenize(stream, state); - } - else if (ch == "#") { + } else if (ch == "#") { stream.eatWhile(/[\w\\\-]/); return ret("atom", "hash"); - } - else if (ch == "!") { + } else if (ch == "!") { stream.match(/^\s*\w*/); return ret("keyword", "important"); - } - else if (/\d/.test(ch) || ch == "." && stream.eat(/\d/)) { + } else if (/\d/.test(ch) || ch == "." && stream.eat(/\d/)) { stream.eatWhile(/[\w.%]/); return ret("number", "unit"); - } - else if (ch === "-") { - if (/\d/.test(stream.peek())) { + } else if (ch === "-") { + if (/[\d.]/.test(stream.peek())) { stream.eatWhile(/[\w.%]/); return ret("number", "unit"); } else if (stream.match(/^[^-]+-/)) { return ret("meta", "meta"); } - } - else if (/[,+>*\/]/.test(ch)) { + } else if (/[,+>*\/]/.test(ch)) { return ret(null, "select-op"); - } - else if (ch == "." && stream.match(/^-?[_a-z][_a-z0-9-]*/i)) { + } else if (ch == "." && stream.match(/^-?[_a-z][_a-z0-9-]*/i)) { return ret("qualifier", "qualifier"); - } - else if (ch == ":") { - return ret("operator", ch); - } - else if (/[;{}\[\]\(\)]/.test(ch)) { + } else if (/[:;{}\[\]\(\)]/.test(ch)) { return ret(null, ch); - } - else if (ch == "u" && stream.match("rl(")) { + } else if (ch == "u" && stream.match("rl(")) { stream.backUp(1); state.tokenize = tokenParenthesized; return ret("property", "variable"); - } - else { + } else if (/[\w\\\-]/.test(ch)) { stream.eatWhile(/[\w\\\-]/); return ret("property", "variable"); + } else { + return ret(null, null); } } @@ -106,6 +97,12 @@ CodeMirror.defineMode("css", function(config, parserConfig) { }, token: function(stream, state) { + if (!state.tokenize && stream.eatSpace()) return null; + var style = (state.tokenize || tokenBase)(stream, state); + if (style && typeof style == "object") { + type = style[1]; + style = style[0]; + } // Use these terms when applicable (see http://www.xanthir.com/blog/b4E50) // @@ -153,11 +150,6 @@ CodeMirror.defineMode("css", function(config, parserConfig) { // sequence of selectors: // One or more of the named type of selector chained with commas. - state.tokenize = state.tokenize || tokenBase; - if (state.tokenize == tokenBase && stream.eatSpace()) return null; - var style = state.tokenize(stream, state); - if (style && typeof style != "string") style = ret(style[0], style[1]); - // Changing style returned based on context var context = state.stack[state.stack.length-1]; if (style == "variable") { diff --git a/mode/css/scss_test.js b/mode/css/scss_test.js index 9998e2aacb..ec66473f29 100644 --- a/mode/css/scss_test.js +++ b/mode/css/scss_test.js @@ -4,31 +4,31 @@ function IT(name) { test.indentation(name, mode, Array.prototype.slice.call(arguments, 1), "scss"); } MT('url_with_quotation', - "[tag foo] { [property background][operator :][string-2 url]([string test.jpg]) }"); + "[tag foo] { [property background]:[string-2 url]([string test.jpg]) }"); MT('url_with_double_quotes', - "[tag foo] { [property background][operator :][string-2 url]([string \"test.jpg\"]) }"); + "[tag foo] { [property background]:[string-2 url]([string \"test.jpg\"]) }"); MT('url_with_single_quotes', - "[tag foo] { [property background][operator :][string-2 url]([string \'test.jpg\']) }"); + "[tag foo] { [property background]:[string-2 url]([string \'test.jpg\']) }"); MT('string', "[def @import] [string \"compass/css3\"]"); MT('important_keyword', - "[tag foo] { [property background][operator :][string-2 url]([string \'test.jpg\']) [keyword !important] }"); + "[tag foo] { [property background]:[string-2 url]([string \'test.jpg\']) [keyword !important] }"); MT('variable', - "[variable-2 $blue][operator :][atom #333]"); + "[variable-2 $blue]:[atom #333]"); MT('variable_as_attribute', - "[tag foo] { [property color][operator :][variable-2 $blue] }"); + "[tag foo] { [property color]:[variable-2 $blue] }"); MT('numbers', - "[tag foo] { [property padding][operator :][number 10px] [number 10] [number 10em] [number 8in] }"); + "[tag foo] { [property padding]:[number 10px] [number 10] [number 10em] [number 8in] }"); MT('number_percentage', - "[tag foo] { [property width][operator :][number 80%] }"); + "[tag foo] { [property width]:[number 80%] }"); MT('selector', "[builtin #hello][qualifier .world]{}"); @@ -40,44 +40,44 @@ "[comment /*foobar*/]"); MT('attribute_with_hyphen', - "[tag foo] { [property font-size][operator :][number 10px] }"); + "[tag foo] { [property font-size]:[number 10px] }"); MT('string_after_attribute', - "[tag foo] { [property content][operator :][string \"::\"] }"); + "[tag foo] { [property content]:[string \"::\"] }"); MT('directives', "[def @include] [qualifier .mixin]"); MT('basic_structure', - "[tag p] { [property background][operator :][keyword red]; }"); + "[tag p] { [property background]:[keyword red]; }"); MT('nested_structure', - "[tag p] { [tag a] { [property color][operator :][keyword red]; } }"); + "[tag p] { [tag a] { [property color]:[keyword red]; } }"); MT('mixin', "[def @mixin] [tag table-base] {}"); MT('number_without_semicolon', - "[tag p] {[property width][operator :][number 12]}", - "[tag a] {[property color][operator :][keyword red];}"); + "[tag p] {[property width]:[number 12]}", + "[tag a] {[property color]:[keyword red];}"); MT('atom_in_nested_block', - "[tag p] { [tag a] { [property color][operator :][atom #000]; } }"); + "[tag p] { [tag a] { [property color]:[atom #000]; } }"); MT('interpolation_in_property', "[tag foo] { [operator #{][variable-2 $hello][operator }:][number 2]; }"); MT('interpolation_in_selector', - "[tag foo][operator #{][variable-2 $hello][operator }] { [property color][operator :][atom #000]; }"); + "[tag foo][operator #{][variable-2 $hello][operator }] { [property color]:[atom #000]; }"); MT('interpolation_error', - "[tag foo][operator #{][error foo][operator }] { [property color][operator :][atom #000]; }"); + "[tag foo][operator #{][error foo][operator }] { [property color]:[atom #000]; }"); MT("divide_operator", - "[tag foo] { [property width][operator :][number 4] [operator /] [number 2] }"); + "[tag foo] { [property width]:[number 4] [operator /] [number 2] }"); MT('nested_structure_with_id_selector', - "[tag p] { [builtin #hello] { [property color][operator :][keyword red]; } }"); + "[tag p] { [builtin #hello] { [property color]:[keyword red]; } }"); IT('mixin', "@mixin container[1 (][2 $a: 10][1 , ][2 $b: 10][1 , ][2 $c: 10]) [1 {]}"); diff --git a/mode/css/test.js b/mode/css/test.js index 3c52460d9f..76b94327bc 100644 --- a/mode/css/test.js +++ b/mode/css/test.js @@ -62,7 +62,7 @@ // Make sure nesting works with media queries MT("atMediaMaxWidthNested", - "[def @media] [attribute screen] [operator and] ([property max-width][operator :] [number 25px]) { [tag foo] { } }"); + "[def @media] [attribute screen] [operator and] ([property max-width]: [number 25px]) { [tag foo] { } }"); MT("tagSelector", "[tag foo] { }"); @@ -74,53 +74,53 @@ "[builtin #foo] { [error #foo] }"); MT("tagSelectorUnclosed", - "[tag foo] { [property margin][operator :] [number 0] } [tag bar] { }"); + "[tag foo] { [property margin]: [number 0] } [tag bar] { }"); MT("tagStringNoQuotes", - "[tag foo] { [property font-family][operator :] [variable-2 hello] [variable-2 world]; }"); + "[tag foo] { [property font-family]: [variable-2 hello] [variable-2 world]; }"); MT("tagStringDouble", - "[tag foo] { [property font-family][operator :] [string \"hello world\"]; }"); + "[tag foo] { [property font-family]: [string \"hello world\"]; }"); MT("tagStringSingle", - "[tag foo] { [property font-family][operator :] [string 'hello world']; }"); + "[tag foo] { [property font-family]: [string 'hello world']; }"); MT("tagColorKeyword", "[tag foo] {" + - "[property color][operator :] [keyword black];" + - "[property color][operator :] [keyword navy];" + - "[property color][operator :] [keyword yellow];" + + "[property color]: [keyword black];" + + "[property color]: [keyword navy];" + + "[property color]: [keyword yellow];" + "}"); MT("tagColorHex3", - "[tag foo] { [property background][operator :] [atom #fff]; }"); + "[tag foo] { [property background]: [atom #fff]; }"); MT("tagColorHex6", - "[tag foo] { [property background][operator :] [atom #ffffff]; }"); + "[tag foo] { [property background]: [atom #ffffff]; }"); MT("tagColorHex4", - "[tag foo] { [property background][operator :] [atom&error #ffff]; }"); + "[tag foo] { [property background]: [atom&error #ffff]; }"); MT("tagColorHexInvalid", - "[tag foo] { [property background][operator :] [atom&error #ffg]; }"); + "[tag foo] { [property background]: [atom&error #ffg]; }"); MT("tagNegativeNumber", - "[tag foo] { [property margin][operator :] [number -5px]; }"); + "[tag foo] { [property margin]: [number -5px]; }"); MT("tagPositiveNumber", - "[tag foo] { [property padding][operator :] [number 5px]; }"); + "[tag foo] { [property padding]: [number 5px]; }"); MT("tagVendor", - "[tag foo] { [meta -foo-][property box-sizing][operator :] [meta -foo-][string-2 border-box]; }"); + "[tag foo] { [meta -foo-][property box-sizing]: [meta -foo-][string-2 border-box]; }"); MT("tagBogusProperty", - "[tag foo] { [property&error barhelloworld][operator :] [number 0]; }"); + "[tag foo] { [property&error barhelloworld]: [number 0]; }"); MT("tagTwoProperties", - "[tag foo] { [property margin][operator :] [number 0]; [property padding][operator :] [number 0]; }"); + "[tag foo] { [property margin]: [number 0]; [property padding]: [number 0]; }"); MT("tagTwoPropertiesURL", - "[tag foo] { [property background][operator :] [string-2 url]([string //example.com/foo.png]); [property padding][operator :] [number 0]; }"); + "[tag foo] { [property background]: [string-2 url]([string //example.com/foo.png]); [property padding]: [number 0]; }"); MT("commentSGML", "[comment ]"); From c2b4f1509ead56bdbae88d5c1489ffd9503b2964 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Tue, 10 Dec 2013 14:14:30 +0100 Subject: [PATCH 0082/4131] [css mode] Refactor, step 2 (state machine) --- mode/css/css.js | 491 ++++++++++++++++++++---------------------- mode/css/scss_test.js | 10 +- mode/css/test.js | 12 +- test/mode_test.js | 7 +- 4 files changed, 248 insertions(+), 272 deletions(-) diff --git a/mode/css/css.js b/mode/css/css.js index 655261d887..b8081e0530 100644 --- a/mode/css/css.js +++ b/mode/css/css.js @@ -3,22 +3,24 @@ CodeMirror.defineMode("css", function(config, parserConfig) { if (!parserConfig.propertyKeywords) parserConfig = CodeMirror.resolveMode("text/css"); - var indentUnit = config.indentUnit || config.tabSize || 2, - hooks = parserConfig.hooks || {}, - atMediaTypes = parserConfig.atMediaTypes || {}, - atMediaFeatures = parserConfig.atMediaFeatures || {}, + var indentUnit = config.indentUnit, + tokenHooks = parserConfig.tokenHooks, + mediaTypes = parserConfig.mediaTypes || {}, + mediaFeatures = parserConfig.mediaFeatures || {}, propertyKeywords = parserConfig.propertyKeywords || {}, colorKeywords = parserConfig.colorKeywords || {}, valueKeywords = parserConfig.valueKeywords || {}, - allowNested = !!parserConfig.allowNested, - type = null; + allowNested = parserConfig.allowNested; + var type, override; function ret(style, tp) { type = tp; return style; } + // Tokenizers + function tokenBase(stream, state) { var ch = stream.next(); - if (hooks[ch]) { - var result = hooks[ch](stream, state); + if (tokenHooks[ch]) { + var result = tokenHooks[ch](stream, state); if (result !== false) return result; } if (ch == "@") { @@ -54,10 +56,10 @@ CodeMirror.defineMode("css", function(config, parserConfig) { } else if (ch == "u" && stream.match("rl(")) { stream.backUp(1); state.tokenize = tokenParenthesized; - return ret("property", "variable"); + return ret("property", "word"); } else if (/[\w\\\-]/.test(ch)) { stream.eatWhile(/[\w\\\-]/); - return ret("property", "variable"); + return ret("property", "word"); } else { return ret(null, null); } @@ -73,7 +75,7 @@ CodeMirror.defineMode("css", function(config, parserConfig) { } if (!escaped) { if (nonInclusive) stream.backUp(1); - state.tokenize = tokenBase; + state.tokenize = null; } return ret("string", "string"); }; @@ -84,16 +86,189 @@ CodeMirror.defineMode("css", function(config, parserConfig) { if (!stream.match(/\s*[\"\']/, false)) state.tokenize = tokenString(")", true); else - state.tokenize = tokenBase; + state.tokenize = null; return ret(null, "("); } + // Context management + + function Context(type, indent, prev) { + this.type = type; + this.indent = indent; + this.prev = prev; + } + + function pushContext(state, type) { + state.context = new Context(type, state.context.indent + indentUnit, state.context); + return type; + } + + function popContext(state) { + state.context = state.context.prev; + return state.context.type; + } + + function pass(type, stream, state) { + return states[state.context.type](type, stream, state); + } + function popAndPass(type, stream, state, n) { + for (var i = n || 1; i > 0; i--) + state.context = state.context.prev; + return pass(type, stream, state); + } + + // Parser + + var states = {}; + + states.top = function(type, _stream, state) { + if (type == "{") { + return pushContext(state, "block"); + } else if (type == "}" && state.context.prev) { + return popContext(state); + } else if (type == "@media") { + return pushContext(state, "media"); + } else if (type && type.charAt(0) == "@") { + return pushContext(state, "at"); + } else if (type == "hash") { + override = "builtin"; + } else if (type == "word") { + override = "tag"; + } else if (type == "variable-definition") { + return pushContext(state, "maybeprop"); + } else if (type == "interpolation") { + return pushContext(state, "interpolation"); + } else if (allowNested && type == "(") { + return pushContext(state, "params"); + } + return state.context.type; + }; + states.block = function(type, stream, state) { + if (type == "word") { + if (propertyKeywords.hasOwnProperty(stream.current().toLowerCase())) { + override = "property"; + return "maybeprop"; + } else if (allowNested) { + override = "tag"; + return "block"; + } else { + override += " error"; + return "maybeprop"; + } + } else if (type == "meta") { + return "block"; + } else if (!allowNested && (type == "hash" || type == "qualifier")) { + override = "error"; + return "block"; + } else { + return states.top(type, stream, state); + } + }; + states.maybeprop = function(type, _stream, state) { + if (type == ":") return pushContext(state, "prop"); + else return state.context.type; + }; + states.prop = function(type, stream, state) { + if (type == ";") return popContext(state); + if (type == "}" || type == "{") return popAndPass(type, stream, state); + if (type == "(") return pushContext(state, "parens"); + + if (type == "hash" && !/^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/.test(stream.current())) { + override += " error"; + } else if (type == "word") { + var word = stream.current().toLowerCase(); + if (valueKeywords.hasOwnProperty(word)) + override = "string-2"; + else if (colorKeywords.hasOwnProperty(word)) + override = "keyword"; + else + override = "variable-2"; + } else if (type == "interpolation") { + return pushContext(state, "interpolation"); + } + return "prop"; + }; + states.parens = function(type, stream, state) { + if (type == "{" || type == "}") return popAndPass(type, stream, state); + if (type == ")") return popContext(state); + return "parens"; + }; + states.media = function(type, stream, state) { + if (type == "(") return "media_parens"; + if (type == "}") return popAndPass(type, stream, state); + if (type == "{") return popContext(state) && pushContext(state, "top"); + if (type == "word") { + var word = stream.current(); + if (mediaTypes[word]) { + override = "attribute"; + return "mediatype"; + } else if (/^(only|not)$/.test(word)) { + override = "keyword"; + return "mediatype"; + } else if (word == "and" || mediaFeatures.hasOwnProperty(word)) { + override = "error"; + return "media"; + } else { + override = "attribute error"; + return "mediatype"; + } + } + return "media"; + }; + states.mediatype = function(type, stream, state) { + if (type == ",") return "media"; + if (type == "(") return pushContext(state, "media_parens"); + if (type == "}") return popAndPass(type, stream, state); + if (type == "{") return popContext(state) && pushContext(state, "top"); + if (type == "word") { + var word = stream.current(); + if (mediaTypes.hasOwnProperty(word)) + override = "attribute"; + else if (word == "and") + override = "operator"; + else + override = "error"; + } + return "mediatype"; + }; + states.media_parens = function(type, stream, state) { + if (type == ")") return popContext(state); + if (type == "{" || type == "}") return popAndPass(type, stream, state, 2); + if (type == "word") { + var word = stream.current().toLowerCase(); + if (propertyKeywords.hasOwnProperty(word)) + override = "property"; + else if (word == "and") + override = "operator"; + else + override = "error"; + } + return "media_parens"; + }; + states.at = function(type, stream, state) { + if (type == ";") return popContext(state); + if (type == "{" || type == "}") return popAndPass(type, stream, state); + if (type == "word") override = "tag"; + else if (type == "hash") override = "atom"; + return "at"; + }; + states.interpolation = function(type, stream, state) { + if (type == "}") return popContext(state); + if (type == "{" || type == ";") return popAndPass(type, stream, state); + if (type != "variable") override = "error"; + return "interpolation"; + }; + states.params = function(type, stream, state) { + if (type == ")") return popContext(state); + if (type == "{" || type == "}") return popAndPass(type, stream, state); + return "params"; + }; + return { startState: function(base) { - return {tokenize: tokenBase, - baseIndent: base || 0, - stack: [], - lastToken: null}; + return {tokenize: null, + state: "top", + context: new Context("top", base || 0, null)}; }, token: function(stream, state) { @@ -103,198 +278,15 @@ CodeMirror.defineMode("css", function(config, parserConfig) { type = style[1]; style = style[0]; } - - // Use these terms when applicable (see http://www.xanthir.com/blog/b4E50) - // - // rule** or **ruleset: - // A selector + braces combo, or an at-rule. - // - // declaration block: - // A sequence of declarations. - // - // declaration: - // A property + colon + value combo. - // - // property value: - // The entire value of a property. - // - // component value: - // A single piece of a property value. Like the 5px in - // text-shadow: 0 0 5px blue;. Can also refer to things that are - // multiple terms, like the 1-4 terms that make up the background-size - // portion of the background shorthand. - // - // term: - // The basic unit of author-facing CSS, like a single number (5), - // dimension (5px), string ("foo"), or function. Officially defined - // by the CSS 2.1 grammar (look for the 'term' production) - // - // - // simple selector: - // A single atomic selector, like a type selector, an attr selector, a - // class selector, etc. - // - // compound selector: - // One or more simple selectors without a combinator. div.example is - // compound, div > .example is not. - // - // complex selector: - // One or more compound selectors chained with combinators. - // - // combinator: - // The parts of selectors that express relationships. There are four - // currently - the space (descendant combinator), the greater-than - // bracket (child combinator), the plus sign (next sibling combinator), - // and the tilda (following sibling combinator). - // - // sequence of selectors: - // One or more of the named type of selector chained with commas. - - // Changing style returned based on context - var context = state.stack[state.stack.length-1]; - if (style == "variable") { - if (type == "variable-definition") state.stack.push("propertyValue"); - return state.lastToken = "variable-2"; - } else if (style == "property") { - var word = stream.current().toLowerCase(); - if (context == "propertyValue") { - if (valueKeywords.hasOwnProperty(word)) { - style = "string-2"; - } else if (colorKeywords.hasOwnProperty(word)) { - style = "keyword"; - } else { - style = "variable-2"; - } - } else if (context == "rule") { - if (!propertyKeywords.hasOwnProperty(word)) { - style += " error"; - } - } else if (context == "block") { - // if a value is present in both property, value, or color, the order - // of preference is property -> color -> value - if (propertyKeywords.hasOwnProperty(word)) { - style = "property"; - } else if (colorKeywords.hasOwnProperty(word)) { - style = "keyword"; - } else if (valueKeywords.hasOwnProperty(word)) { - style = "string-2"; - } else { - style = "tag"; - } - } else if (!context || context == "@media{") { - style = "tag"; - } else if (context == "@media") { - if (atMediaTypes[stream.current()]) { - style = "attribute"; // Known attribute - } else if (/^(only|not)$/.test(word)) { - style = "keyword"; - } else if (word == "and") { - style = "error"; // "and" is only allowed in @mediaType - } else if (atMediaFeatures.hasOwnProperty(word)) { - style = "error"; // Known property, should be in @mediaType( - } else { - // Unknown, expecting keyword or attribute, assuming attribute - style = "attribute error"; - } - } else if (context == "@mediaType") { - if (atMediaTypes.hasOwnProperty(word)) { - style = "attribute"; - } else if (word == "and") { - style = "operator"; - } else if (/^(only|not)$/.test(word)) { - style = "error"; // Only allowed in @media - } else { - // Unknown attribute or property, but expecting property (preceded - // by "and"). Should be in parentheses - style = "error"; - } - } else if (context == "@mediaType(") { - if (propertyKeywords.hasOwnProperty(word)) { - // do nothing, remains "property" - } else if (atMediaTypes.hasOwnProperty(word)) { - style = "error"; // Known property, should be in parentheses - } else if (word == "and") { - style = "operator"; - } else if (/^(only|not)$/.test(word)) { - style = "error"; // Only allowed in @media - } else { - style += " error"; - } - } else if (context == "@import") { - style = "tag"; - } else { - style = "error"; - } - } else if (style == "atom") { - if(!context || context == "@media{" || context == "block") { - style = "builtin"; - } else if (context == "propertyValue") { - if (!/^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/.test(stream.current())) { - style += " error"; - } - } else { - style = "error"; - } - } else if (context == "@media" && type == "{") { - style = "error"; - } - - // Push/pop context stack - if (type == "{") { - if (context == "@media" || context == "@mediaType") { - state.stack[state.stack.length-1] = "@media{"; - } - else { - var newContext = allowNested ? "block" : "rule"; - state.stack.push(newContext); - } - } - else if (type == "}") { - if (context == "interpolation") style = "operator"; - // Pop off end of array until { is reached - while(state.stack.length){ - var removed = state.stack.pop(); - if(removed.indexOf("{") > -1 || removed == "block" || removed == "rule"){ - break; - } - } - } - else if (type == "interpolation") state.stack.push("interpolation"); - else if (type == "@media") state.stack.push("@media"); - else if (type == "@import") state.stack.push("@import"); - else if (context == "@media" && /\b(keyword|attribute)\b/.test(style)) - state.stack[state.stack.length-1] = "@mediaType"; - else if (context == "@mediaType" && stream.current() == ",") - state.stack[state.stack.length-1] = "@media"; - else if (type == "(") { - if (context == "@media" || context == "@mediaType") { - // Make sure @mediaType is used to avoid error on { - state.stack[state.stack.length-1] = "@mediaType"; - state.stack.push("@mediaType("); - } - else state.stack.push("("); - } - else if (type == ")") { - // Pop off end of array until ( is reached - while(state.stack.length){ - var removed = state.stack.pop(); - if(removed.indexOf("(") > -1){ - break; - } - } - } - else if (type == ":" && state.lastToken == "property") state.stack.push("propertyValue"); - else if (context == "propertyValue" && type == ";") state.stack.pop(); - else if (context == "@import" && type == ";") state.stack.pop(); - - return state.lastToken = style; + override = style; + state.state = states[state.state](type, stream, state); + return override; }, indent: function(state, textAfter) { - var n = state.stack.length; - if (/^\}/.test(textAfter)) - n -= state.stack[n-1] == "propertyValue" ? 2 : 1; - return state.baseIndent + n * indentUnit; + var cx = state.context; + if (/^\}/.test(textAfter)) cx = cx.prev; + return cx.indent; }, electricChars: "}", @@ -313,12 +305,12 @@ CodeMirror.defineMode("css", function(config, parserConfig) { return keys; } - var atMediaTypes = keySet([ + var mediaTypes = keySet([ "all", "aural", "braille", "handheld", "print", "projection", "screen", "tty", "tv", "embossed" ]); - var atMediaFeatures = keySet([ + var mediaFeatures = keySet([ "width", "min-width", "max-width", "height", "min-height", "max-height", "device-width", "min-device-width", "max-device-width", "device-height", "min-device-height", "max-device-height", "aspect-ratio", @@ -545,67 +537,45 @@ CodeMirror.defineMode("css", function(config, parserConfig) { return ["comment", "comment"]; } + function tokenSGMLComment(stream, state) { + if (stream.skipTo("-->")) { + stream.match("-->"); + state.tokenize = null; + } else { + stream.skipToEnd(); + } + return ["comment", "comment"]; + } + CodeMirror.defineMIME("text/css", { - atMediaTypes: atMediaTypes, - atMediaFeatures: atMediaFeatures, + mediaTypes: mediaTypes, + mediaFeatures: mediaFeatures, propertyKeywords: propertyKeywords, colorKeywords: colorKeywords, valueKeywords: valueKeywords, - hooks: { + tokenHooks: { "<": function(stream, state) { - function tokenSGMLComment(stream, state) { - var dashes = 0, ch; - while ((ch = stream.next()) != null) { - if (dashes >= 2 && ch == ">") { - state.tokenize = null; - break; - } - dashes = (ch == "-") ? dashes + 1 : 0; - } - return ["comment", "comment"]; - } - if (stream.eat("!")) { - state.tokenize = tokenSGMLComment; - return tokenSGMLComment(stream, state); - } + if (!stream.match("!--")) return false; + state.tokenize = tokenSGMLComment; + return tokenSGMLComment(stream, state); }, "/": function(stream, state) { - if (stream.eat("*")) { - state.tokenize = tokenCComment; - return tokenCComment(stream, state); - } - return false; + if (!stream.eat("*")) return false; + state.tokenize = tokenCComment; + return tokenCComment(stream, state); } }, name: "css" }); CodeMirror.defineMIME("text/x-scss", { - atMediaTypes: atMediaTypes, - atMediaFeatures: atMediaFeatures, + mediaTypes: mediaTypes, + mediaFeatures: mediaFeatures, propertyKeywords: propertyKeywords, colorKeywords: colorKeywords, valueKeywords: valueKeywords, allowNested: true, - hooks: { - ":": function(stream) { - if (stream.match(/\s*{/)) { - return [null, "{"]; - } - return false; - }, - "$": function(stream) { - stream.match(/^[\w-]+/); - if (stream.peek() == ":") { - return ["variable", "variable-definition"]; - } - return ["variable", "variable"]; - }, - ",": function(stream, state) { - if (state.stack[state.stack.length - 1] == "propertyValue" && stream.match(/^ *\$/, false)) { - return ["operator", ";"]; - } - }, + tokenHooks: { "/": function(stream, state) { if (stream.eat("/")) { stream.skipToEnd(); @@ -617,13 +587,20 @@ CodeMirror.defineMode("css", function(config, parserConfig) { return ["operator", "operator"]; } }, + ":": function(stream) { + if (stream.match(/\s*{/)) + return [null, "{"]; + return false; + }, + "$": function(stream) { + stream.match(/^[\w-]+/); + if (stream.match(/^\s*:/, false)) + return ["variable-2", "variable-definition"]; + return ["variable-2", "variable"]; + }, "#": function(stream) { - if (stream.eat("{")) { - return ["operator", "interpolation"]; - } else { - stream.eatWhile(/[\w\\\-]/); - return ["atom", "hash"]; - } + if (!stream.eat("{")) return false; + return [null, "interpolation"]; } }, name: "css" diff --git a/mode/css/scss_test.js b/mode/css/scss_test.js index ec66473f29..6218974b12 100644 --- a/mode/css/scss_test.js +++ b/mode/css/scss_test.js @@ -1,5 +1,5 @@ (function() { - var mode = CodeMirror.getMode({tabSize: 1}, "text/x-scss"); + var mode = CodeMirror.getMode({indentUnit: 1}, "text/x-scss"); function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1), "scss"); } function IT(name) { test.indentation(name, mode, Array.prototype.slice.call(arguments, 1), "scss"); } @@ -65,13 +65,13 @@ "[tag p] { [tag a] { [property color]:[atom #000]; } }"); MT('interpolation_in_property', - "[tag foo] { [operator #{][variable-2 $hello][operator }:][number 2]; }"); + "[tag foo] { #{[variable-2 $hello]}:[number 2]; }"); MT('interpolation_in_selector', - "[tag foo][operator #{][variable-2 $hello][operator }] { [property color]:[atom #000]; }"); + "[tag foo]#{[variable-2 $hello]} { [property color]:[atom #000]; }"); MT('interpolation_error', - "[tag foo][operator #{][error foo][operator }] { [property color]:[atom #000]; }"); + "[tag foo]#{[error foo]} { [property color]:[atom #000]; }"); MT("divide_operator", "[tag foo] { [property width]:[number 4] [operator /] [number 2] }"); @@ -80,7 +80,7 @@ "[tag p] { [builtin #hello] { [property color]:[keyword red]; } }"); IT('mixin', - "@mixin container[1 (][2 $a: 10][1 , ][2 $b: 10][1 , ][2 $c: 10]) [1 {]}"); + "@mixin container[1 ($a: 10, $b: 10, $c: 10]) [1 {]}"); IT('nested', "foo [1 { bar ][2 { ][1 } ]}"); diff --git a/mode/css/test.js b/mode/css/test.js index 76b94327bc..2fa451a624 100644 --- a/mode/css/test.js +++ b/mode/css/test.js @@ -1,12 +1,8 @@ (function() { - var mode = CodeMirror.getMode({tabSize: 1}, "css"); + var mode = CodeMirror.getMode({indentUnit: 1}, "css"); function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); } function IT(name) { test.indentation(name, mode, Array.prototype.slice.call(arguments, 1)); } - // Requires at least one media query - MT("atMediaEmpty", - "[def @media] [error {] }"); - MT("atMediaMultiple", "[def @media] [keyword not] [attribute screen] [operator and] ([property color]), [keyword not] [attribute print] [operator and] ([property color]) { }"); @@ -58,7 +54,7 @@ // Soft error, because "foobarhello" is not a known property or type. MT("atMediaUnknownProperty", - "[def @media] [attribute screen] [operator and] ([property&error foobarhello]) { }"); + "[def @media] [attribute screen] [operator and] ([error foobarhello]) { }"); // Make sure nesting works with media queries MT("atMediaMaxWidthNested", @@ -125,6 +121,10 @@ MT("commentSGML", "[comment ]"); + MT("commentSGML2", + "[comment ] [tag div] {}"); + IT("tagSelector", "strong, em [1 { background][2 : rgba][3 (255, 255, 0, .2][2 )][1 ;]}"); diff --git a/test/mode_test.js b/test/mode_test.js index 4b63cf517c..08deab74b2 100644 --- a/test/mode_test.js +++ b/test/mode_test.js @@ -132,11 +132,10 @@ if (line == "" && mode.blankLine) mode.blankLine(state); /* Start copied code from CodeMirror.highlight */ while (!stream.eol()) { - var compare = mode.token(stream, state), substr = stream.current(); - if(compareIndentation) compare = mode.indent(state) || null; + var compare = mode.token(stream, state), substr = stream.current(); + if (compareIndentation) compare = mode.indent(state) || null; else if (compare && compare.indexOf(" ") > -1) compare = compare.split(' ').sort().join(' '); - - stream.start = stream.pos; + stream.start = stream.pos; if (pos && st[pos-2] == compare && !newLine) { st[pos-1] += substr; } else if (substr) { From e42edbc43e338b4024811de4c454b96da5002597 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Tue, 10 Dec 2013 15:58:50 +0100 Subject: [PATCH 0083/4131] [css mode] Refactor, step 3 (Less support) --- mode/css/css.js | 120 ++++++++++++++++++++------------- mode/css/index.html | 2 +- mode/css/less.html | 152 ++++++++++++++++++++++++++++++++++++++++++ mode/css/less_test.js | 48 +++++++++++++ mode/css/scss.html | 2 +- mode/css/scss_test.js | 18 +++-- mode/css/test.js | 56 ++-------------- mode/gfm/test.js | 2 +- mode/index.html | 2 +- test/index.html | 1 + 10 files changed, 298 insertions(+), 105 deletions(-) create mode 100644 mode/css/less.html create mode 100644 mode/css/less_test.js diff --git a/mode/css/css.js b/mode/css/css.js index b8081e0530..df4ab4d2c6 100644 --- a/mode/css/css.js +++ b/mode/css/css.js @@ -119,6 +119,16 @@ CodeMirror.defineMode("css", function(config, parserConfig) { // Parser + function wordAsValue(stream) { + var word = stream.current().toLowerCase(); + if (valueKeywords.hasOwnProperty(word)) + override = "atom"; + else if (colorKeywords.hasOwnProperty(word)) + override = "keyword"; + else + override = "variable"; + } + var states = {}; states.top = function(type, _stream, state) { @@ -135,14 +145,17 @@ CodeMirror.defineMode("css", function(config, parserConfig) { } else if (type == "word") { override = "tag"; } else if (type == "variable-definition") { - return pushContext(state, "maybeprop"); + return "maybeprop"; } else if (type == "interpolation") { return pushContext(state, "interpolation"); + } else if (type == ":") { + return "pseudo"; } else if (allowNested && type == "(") { return pushContext(state, "params"); } return state.context.type; }; + states.block = function(type, stream, state) { if (type == "word") { if (propertyKeywords.hasOwnProperty(stream.current().toLowerCase())) { @@ -164,10 +177,12 @@ CodeMirror.defineMode("css", function(config, parserConfig) { return states.top(type, stream, state); } }; + states.maybeprop = function(type, _stream, state) { if (type == ":") return pushContext(state, "prop"); else return state.context.type; }; + states.prop = function(type, stream, state) { if (type == ";") return popContext(state); if (type == "}" || type == "{") return popAndPass(type, stream, state); @@ -176,91 +191,71 @@ CodeMirror.defineMode("css", function(config, parserConfig) { if (type == "hash" && !/^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/.test(stream.current())) { override += " error"; } else if (type == "word") { - var word = stream.current().toLowerCase(); - if (valueKeywords.hasOwnProperty(word)) - override = "string-2"; - else if (colorKeywords.hasOwnProperty(word)) - override = "keyword"; - else - override = "variable-2"; + wordAsValue(stream); } else if (type == "interpolation") { return pushContext(state, "interpolation"); } return "prop"; }; + states.parens = function(type, stream, state) { if (type == "{" || type == "}") return popAndPass(type, stream, state); if (type == ")") return popContext(state); return "parens"; }; - states.media = function(type, stream, state) { - if (type == "(") return "media_parens"; - if (type == "}") return popAndPass(type, stream, state); - if (type == "{") return popContext(state) && pushContext(state, "top"); + + states.pseudo = function(type, stream, state) { if (type == "word") { - var word = stream.current(); - if (mediaTypes[word]) { - override = "attribute"; - return "mediatype"; - } else if (/^(only|not)$/.test(word)) { - override = "keyword"; - return "mediatype"; - } else if (word == "and" || mediaFeatures.hasOwnProperty(word)) { - override = "error"; - return "media"; - } else { - override = "attribute error"; - return "mediatype"; - } + override = "variable-2"; + return state.context.type; } - return "media"; + return pass(type, stream, state); }; - states.mediatype = function(type, stream, state) { - if (type == ",") return "media"; + + states.media = function(type, stream, state) { if (type == "(") return pushContext(state, "media_parens"); if (type == "}") return popAndPass(type, stream, state); - if (type == "{") return popContext(state) && pushContext(state, "top"); + if (type == "{") return popContext(state) && pushContext(state, allowNested ? "block" : "top"); + if (type == "word") { - var word = stream.current(); - if (mediaTypes.hasOwnProperty(word)) + var word = stream.current().toLowerCase(); + if (word == "only" || word == "not" || word == "and") + override = "keyword"; + else if (mediaTypes.hasOwnProperty(word)) override = "attribute"; - else if (word == "and") - override = "operator"; + else if (mediaFeatures.hasOwnProperty(word)) + override = "property"; else override = "error"; } - return "mediatype"; + return state.context.type; }; + states.media_parens = function(type, stream, state) { if (type == ")") return popContext(state); if (type == "{" || type == "}") return popAndPass(type, stream, state, 2); - if (type == "word") { - var word = stream.current().toLowerCase(); - if (propertyKeywords.hasOwnProperty(word)) - override = "property"; - else if (word == "and") - override = "operator"; - else - override = "error"; - } - return "media_parens"; + return states.media(type, stream, state); }; + states.at = function(type, stream, state) { if (type == ";") return popContext(state); if (type == "{" || type == "}") return popAndPass(type, stream, state); if (type == "word") override = "tag"; - else if (type == "hash") override = "atom"; + else if (type == "hash") override = "builtin"; return "at"; }; + states.interpolation = function(type, stream, state) { if (type == "}") return popContext(state); if (type == "{" || type == ";") return popAndPass(type, stream, state); if (type != "variable") override = "error"; return "interpolation"; }; + states.params = function(type, stream, state) { if (type == ")") return popContext(state); if (type == "{" || type == "}") return popAndPass(type, stream, state); + if (type == "word") wordAsValue(stream); return "params"; }; @@ -605,4 +600,37 @@ CodeMirror.defineMode("css", function(config, parserConfig) { }, name: "css" }); + + CodeMirror.defineMIME("text/x-less", { + mediaTypes: mediaTypes, + mediaFeatures: mediaFeatures, + propertyKeywords: propertyKeywords, + colorKeywords: colorKeywords, + valueKeywords: valueKeywords, + allowNested: true, + tokenHooks: { + "/": function(stream, state) { + if (stream.eat("/")) { + stream.skipToEnd(); + return ["comment", "comment"]; + } else if (stream.eat("*")) { + state.tokenize = tokenCComment; + return tokenCComment(stream, state); + } else { + return ["operator", "operator"]; + } + }, + "@": function(stream) { + if (stream.match(/^(media|import)\b/, false)) return false; + stream.eatWhile(/[\w\\\-]/); + if (stream.match(/^\s*:/, false)) + return ["variable-2", "variable-definition"]; + return ["variable-2", "variable"]; + }, + "&": function() { + return ["atom", "atom"]; + } + }, + name: "css" + }); })(); diff --git a/mode/css/index.html b/mode/css/index.html index 1d1865e2e3..80ef518e90 100644 --- a/mode/css/index.html +++ b/mode/css/index.html @@ -63,7 +63,7 @@

CSS mode

var editor = CodeMirror.fromTextArea(document.getElementById("code"), {}); -

MIME types defined: text/css.

+

MIME types defined: text/css, text/x-scss (demo), text/x-less (demo).

Parsing/Highlighting Tests: normal, verbose.

diff --git a/mode/css/less.html b/mode/css/less.html new file mode 100644 index 0000000000..1030ca43fe --- /dev/null +++ b/mode/css/less.html @@ -0,0 +1,152 @@ + + +CodeMirror: LESS mode + + + + + + + + + + +
+

LESS mode

+
+ + +

The LESS mode is a sub-mode of the CSS mode (defined in css.js.

+ +

Parsing/Highlighting Tests: normal, verbose.

+
diff --git a/mode/css/less_test.js b/mode/css/less_test.js new file mode 100644 index 0000000000..9b065f23d8 --- /dev/null +++ b/mode/css/less_test.js @@ -0,0 +1,48 @@ +(function() { + "use strict"; + + var mode = CodeMirror.getMode({indentUnit: 1}, "text/x-less"); + function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1), "less"); } + + MT("variable", + "[variable-2 @base]: [atom #f04615];", + "[qualifier .class] {", + " [property width]: [variable percentage]([number 0.5]); [comment // returns `50%`]", + " [property color]: [variable saturate]([variable-2 @base], [number 5%]);", + "}"); + + MT("amp", + "[qualifier .child], [qualifier .sibling] {", + " [qualifier .parent] [atom &] {", + " [property color]: [keyword black];", + " }", + " [atom &] + [atom &] {", + " [property color]: [keyword red];", + " }", + "}"); + + MT("mixin", + "[qualifier .mixin] ([variable dark]; [variable-2 @color]) {", + " [property color]: [variable darken]([variable-2 @color], [number 10%]);", + "}", + "[qualifier .mixin] ([variable light]; [variable-2 @color]) {", + " [property color]: [variable lighten]([variable-2 @color], [number 10%]);", + "}", + "[qualifier .mixin] ([variable-2 @_]; [variable-2 @color]) {", + " [property display]: [atom block];", + "}", + "[variable-2 @switch]: [variable light];", + "[qualifier .class] {", + " [qualifier .mixin]([variable-2 @switch]; [atom #888]);", + "}"); + + MT("nest", + "[qualifier .one] {", + " [def @media] ([property width]: [number 400px]) {", + " [property font-size]: [number 1.2em];", + " [def @media] [attribute print] [keyword and] [property color] {", + " [property color]: [keyword blue];", + " }", + " }", + "}"); +})(); diff --git a/mode/css/scss.html b/mode/css/scss.html index 72781c0dc3..0677d08fe1 100644 --- a/mode/css/scss.html +++ b/mode/css/scss.html @@ -150,7 +150,7 @@

SCSS mode

}); -

MIME types defined: text/scss.

+

The SCSS mode is a sub-mode of the CSS mode (defined in css.js.

Parsing/Highlighting Tests: normal, verbose.

diff --git a/mode/css/scss_test.js b/mode/css/scss_test.js index 6218974b12..ed5de83801 100644 --- a/mode/css/scss_test.js +++ b/mode/css/scss_test.js @@ -4,19 +4,19 @@ function IT(name) { test.indentation(name, mode, Array.prototype.slice.call(arguments, 1), "scss"); } MT('url_with_quotation', - "[tag foo] { [property background]:[string-2 url]([string test.jpg]) }"); + "[tag foo] { [property background]:[atom url]([string test.jpg]) }"); MT('url_with_double_quotes', - "[tag foo] { [property background]:[string-2 url]([string \"test.jpg\"]) }"); + "[tag foo] { [property background]:[atom url]([string \"test.jpg\"]) }"); MT('url_with_single_quotes', - "[tag foo] { [property background]:[string-2 url]([string \'test.jpg\']) }"); + "[tag foo] { [property background]:[atom url]([string \'test.jpg\']) }"); MT('string', "[def @import] [string \"compass/css3\"]"); MT('important_keyword', - "[tag foo] { [property background]:[string-2 url]([string \'test.jpg\']) [keyword !important] }"); + "[tag foo] { [property background]:[atom url]([string \'test.jpg\']) [keyword !important] }"); MT('variable', "[variable-2 $blue]:[atom #333]"); @@ -80,7 +80,7 @@ "[tag p] { [builtin #hello] { [property color]:[keyword red]; } }"); IT('mixin', - "@mixin container[1 ($a: 10, $b: 10, $c: 10]) [1 {]}"); + "[1 @mixin container ($a: 10, $b: 10, $c: 10) {]}"); IT('nested', "foo [1 { bar ][2 { ][1 } ]}"); @@ -90,4 +90,12 @@ IT('parentheses', "foo [1 { color][2 : darken][3 ($blue, 9%][2 )][1 ; ]}"); + + IT('vardef', + "$name[1 : 'val'];", + "tag [1 {]", + "[1 inner ][2 {]", + "[2 margin][3 : 3px][2 ;]", + "[2 ][1 }]", + "}"); })(); diff --git a/mode/css/test.js b/mode/css/test.js index 2fa451a624..cbfbef46cc 100644 --- a/mode/css/test.js +++ b/mode/css/test.js @@ -3,62 +3,18 @@ function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); } function IT(name) { test.indentation(name, mode, Array.prototype.slice.call(arguments, 1)); } - MT("atMediaMultiple", - "[def @media] [keyword not] [attribute screen] [operator and] ([property color]), [keyword not] [attribute print] [operator and] ([property color]) { }"); - - MT("atMediaCheckStack", - "[def @media] [attribute screen] { } [tag foo] { }"); - - MT("atMediaCheckStack", - "[def @media] [attribute screen] ([property color]) { } [tag foo] { }"); - - MT("atMediaPropertyOnly", - "[def @media] ([property color]) { } [tag foo] { }"); - - MT("atMediaCheckStackInvalidAttribute", - "[def @media] [attribute&error foobarhello] { [tag foo] { } }"); - - MT("atMediaCheckStackInvalidAttribute", - "[def @media] [attribute&error foobarhello] { } [tag foo] { }"); - - // Error, because "and" is only allowed immediately preceding a media expression - MT("atMediaInvalidAttribute", - "[def @media] [attribute&error foobarhello] { }"); - - // Error, because "and" is only allowed immediately preceding a media expression - MT("atMediaInvalidAnd", - "[def @media] [error and] [attribute screen] { }"); - - // Error, because "not" is only allowed as the first item in each media query - MT("atMediaInvalidNot", - "[def @media] [attribute screen] [error not] ([error not]) { }"); - - // Error, because "only" is only allowed as the first item in each media query - MT("atMediaInvalidOnly", - "[def @media] [attribute screen] [error only] ([error only]) { }"); - // Error, because "foobarhello" is neither a known type or property, but // property was expected (after "and"), and it should be in parenthese. MT("atMediaUnknownType", - "[def @media] [attribute screen] [operator and] [error foobarhello] { }"); - - // Error, because "color" is not a known type, but is a known property, and - // should be in parentheses. - MT("atMediaInvalidType", - "[def @media] [attribute screen] [operator and] [error color] { }"); - - // Error, because "print" is not a known property, but is a known type, - // and should not be in parenthese. - MT("atMediaInvalidProperty", - "[def @media] [attribute screen] [operator and] ([error print]) { }"); + "[def @media] [attribute screen] [keyword and] [error foobarhello] { }"); // Soft error, because "foobarhello" is not a known property or type. MT("atMediaUnknownProperty", - "[def @media] [attribute screen] [operator and] ([error foobarhello]) { }"); + "[def @media] [attribute screen] [keyword and] ([error foobarhello]) { }"); // Make sure nesting works with media queries MT("atMediaMaxWidthNested", - "[def @media] [attribute screen] [operator and] ([property max-width]: [number 25px]) { [tag foo] { } }"); + "[def @media] [attribute screen] [keyword and] ([property max-width]: [number 25px]) { [tag foo] { } }"); MT("tagSelector", "[tag foo] { }"); @@ -73,7 +29,7 @@ "[tag foo] { [property margin]: [number 0] } [tag bar] { }"); MT("tagStringNoQuotes", - "[tag foo] { [property font-family]: [variable-2 hello] [variable-2 world]; }"); + "[tag foo] { [property font-family]: [variable hello] [variable world]; }"); MT("tagStringDouble", "[tag foo] { [property font-family]: [string \"hello world\"]; }"); @@ -107,7 +63,7 @@ "[tag foo] { [property padding]: [number 5px]; }"); MT("tagVendor", - "[tag foo] { [meta -foo-][property box-sizing]: [meta -foo-][string-2 border-box]; }"); + "[tag foo] { [meta -foo-][property box-sizing]: [meta -foo-][atom border-box]; }"); MT("tagBogusProperty", "[tag foo] { [property&error barhelloworld]: [number 0]; }"); @@ -116,7 +72,7 @@ "[tag foo] { [property margin]: [number 0]; [property padding]: [number 0]; }"); MT("tagTwoPropertiesURL", - "[tag foo] { [property background]: [string-2 url]([string //example.com/foo.png]); [property padding]: [number 0]; }"); + "[tag foo] { [property background]: [atom url]([string //example.com/foo.png]); [property padding]: [number 0]; }"); MT("commentSGML", "[comment ]"); diff --git a/mode/gfm/test.js b/mode/gfm/test.js index 4cf46fe5a5..7d17517e18 100644 --- a/mode/gfm/test.js +++ b/mode/gfm/test.js @@ -114,7 +114,7 @@ MT("notALink", "[comment ```css]", - "[tag foo] {[property color][operator :][keyword black];}", + "[tag foo] {[property color]:[keyword black];}", "[comment ```][link http://www.example.com/]"); MT("notALink", diff --git a/mode/index.html b/mode/index.html index 81abc42d8c..e332f84f70 100644 --- a/mode/index.html +++ b/mode/index.html @@ -61,7 +61,7 @@

Language modes

  • JavaScript
  • Jinja2
  • Julia
  • -
  • LESS
  • +
  • LESS
  • LiveScript
  • Lua
  • Markdown (GitHub-flavour)
  • diff --git a/test/index.html b/test/index.html index bec6c0bd29..ac12b2274c 100644 --- a/test/index.html +++ b/test/index.html @@ -78,6 +78,7 @@

    Test Suite

    + From 6ad770675b70b08d0523e22aea1ef17161d3f8dc Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 12 Dec 2013 12:20:33 +0100 Subject: [PATCH 0084/4131] [css mode] Add a hintWords helper value --- addon/hint/show-hint.js | 1 - mode/css/css.js | 23 +++++++++++++---------- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/addon/hint/show-hint.js b/addon/hint/show-hint.js index 31e919dcbb..76f020cf0a 100644 --- a/addon/hint/show-hint.js +++ b/addon/hint/show-hint.js @@ -302,7 +302,6 @@ CodeMirror.registerHelper("hint", "fromList", function(cm, options) { var cur = cm.getCursor(), token = cm.getTokenAt(cur); - if (!/^[\w$_]*$/.test(token.string)) return null; var found = []; for (var i = 0; i < options.words.length; i++) { var word = options.words[i]; diff --git a/mode/css/css.js b/mode/css/css.js index df4ab4d2c6..2a211dc3c7 100644 --- a/mode/css/css.js +++ b/mode/css/css.js @@ -300,12 +300,12 @@ CodeMirror.defineMode("css", function(config, parserConfig) { return keys; } - var mediaTypes = keySet([ + var mediaTypes_ = [ "all", "aural", "braille", "handheld", "print", "projection", "screen", "tty", "tv", "embossed" - ]); + ], mediaTypes = keySet(mediaTypes_); - var mediaFeatures = keySet([ + var mediaFeatures_ = [ "width", "min-width", "max-width", "height", "min-height", "max-height", "device-width", "min-device-width", "max-device-width", "device-height", "min-device-height", "max-device-height", "aspect-ratio", @@ -314,9 +314,9 @@ CodeMirror.defineMode("css", function(config, parserConfig) { "max-color", "color-index", "min-color-index", "max-color-index", "monochrome", "min-monochrome", "max-monochrome", "resolution", "min-resolution", "max-resolution", "scan", "grid" - ]); + ], mediaFeatures = keySet(mediaFeatures_); - var propertyKeywords = keySet([ + var propertyKeywords_ = [ "align-content", "align-items", "align-self", "alignment-adjust", "alignment-baseline", "anchor-point", "animation", "animation-delay", "animation-direction", "animation-duration", "animation-iteration-count", @@ -404,9 +404,9 @@ CodeMirror.defineMode("css", function(config, parserConfig) { "stroke-miterlimit", "stroke-opacity", "stroke-width", "text-rendering", "baseline-shift", "dominant-baseline", "glyph-orientation-horizontal", "glyph-orientation-vertical", "kerning", "text-anchor", "writing-mode" - ]); + ], propertyKeywords = keySet(propertyKeywords_); - var colorKeywords = keySet([ + var colorKeywords_ = [ "aliceblue", "antiquewhite", "aqua", "aquamarine", "azure", "beige", "bisque", "black", "blanchedalmond", "blue", "blueviolet", "brown", "burlywood", "cadetblue", "chartreuse", "chocolate", "coral", "cornflowerblue", @@ -433,9 +433,9 @@ CodeMirror.defineMode("css", function(config, parserConfig) { "slateblue", "slategray", "snow", "springgreen", "steelblue", "tan", "teal", "thistle", "tomato", "turquoise", "violet", "wheat", "white", "whitesmoke", "yellow", "yellowgreen" - ]); + ], colorKeywords = keySet(colorKeywords_); - var valueKeywords = keySet([ + var valueKeywords_ = [ "above", "absolute", "activeborder", "activecaption", "afar", "after-white-space", "ahead", "alias", "all", "all-scroll", "alternate", "always", "amharic", "amharic-abegede", "antialiased", "appworkspace", @@ -518,7 +518,10 @@ CodeMirror.defineMode("css", function(config, parserConfig) { "visibleStroke", "visual", "w-resize", "wait", "wave", "wider", "window", "windowframe", "windowtext", "x-large", "x-small", "xor", "xx-large", "xx-small" - ]); + ], valueKeywords = keySet(valueKeywords_); + + var allWords = mediaTypes_.concat(mediaFeatures_).concat(propertyKeywords_).concat(colorKeywords_).concat(valueKeywords_); + CodeMirror.registerHelper("hintWords", "css", allWords); function tokenCComment(stream, state) { var maybeEnd = false, ch; From fad3f49c26d706105969cc2d80919766a855ebbe Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 12 Dec 2013 12:52:50 +0100 Subject: [PATCH 0085/4131] [css-hint addon] Rewrite to work with overhauled css mode --- addon/hint/css-hint.js | 62 ++++++++++++++++++++---------------------- doc/manual.html | 2 +- mode/css/css.js | 8 ++++-- 3 files changed, 35 insertions(+), 37 deletions(-) diff --git a/addon/hint/css-hint.js b/addon/hint/css-hint.js index 2b15300d0c..43bdf5de02 100644 --- a/addon/hint/css-hint.js +++ b/addon/hint/css-hint.js @@ -1,50 +1,46 @@ (function () { "use strict"; - function getHints(cm) { + var pseudoClasses = {link: 1, visited: 1, active: 1, hover: 1, focus: 1, + "first-letter": 1, "first-line": 1, "first-child": 1, + before: 1, after: 1, lang: 1}; + + CodeMirror.registerHelper("hint", "css", function(cm) { var cur = cm.getCursor(), token = cm.getTokenAt(cur); var inner = CodeMirror.innerMode(cm.getMode(), token.state); if (inner.mode.name != "css") return; - // If it's not a 'word-style' token, ignore the token. - if (!/^[\w$_-]*$/.test(token.string)) { - token = { - start: cur.ch, end: cur.ch, string: "", state: token.state, - type: null - }; - var stack = token.state.stack; - var lastToken = stack && stack.length > 0 ? stack[stack.length - 1] : ""; - if (token.string == ":" || lastToken.indexOf("property") == 0) - token.type = "variable"; - else if (token.string == "{" || lastToken.indexOf("rule") == 0) - token.type = "property"; + var word = token.string, start = token.start, end = token.end; + if (/[^\w$_-]/.test(word)) { + word = ""; start = end = cur.ch; } - if (!token.type) - return; - var spec = CodeMirror.resolveMode("text/css"); - var keywords = null; - if (token.type.indexOf("property") == 0) - keywords = spec.propertyKeywords; - else if (token.type.indexOf("variable") == 0) - keywords = spec.valueKeywords; - - if (!keywords) - return; var result = []; - for (var name in keywords) { - if (name.indexOf(token.string) == 0 /* > -1 */) - result.push(name); + function add(keywords) { + for (var name in keywords) + if (!word || name.indexOf(word) == 0) + result.push(name); } - return { + var st = token.state.state; + if (st == "pseudo" || token.type == "variable-3") { + add(pseudoClasses); + } else if (st == "block" || st == "maybeprop") { + add(spec.propertyKeywords); + } else if (st == "prop" || st == "parens" || st == "at" || st == "params") { + add(spec.valueKeywords); + add(spec.colorKeywords); + } else if (st == "media" || st == "media_parens") { + add(spec.mediaTypes); + add(spec.mediaFeatures); + } + + if (result.length) return { list: result, - from: CodeMirror.Pos(cur.line, token.start), - to: CodeMirror.Pos(cur.line, token.end) + from: CodeMirror.Pos(cur.line, start), + to: CodeMirror.Pos(cur.line, end) }; - } - - CodeMirror.registerHelper("hint", "css", getHints); + }); })(); diff --git a/doc/manual.html b/doc/manual.html index 0dc120ddf3..957ab347c5 100644 --- a/doc/manual.html +++ b/doc/manual.html @@ -2159,7 +2159,7 @@

    Addons

    the demo.
    hint/css-hint.js
    -
    A minimal hinting function for CSS code. +
    A hinting function for CSS, SCSS, or LESS code. Defines CodeMirror.hint.css.
    hint/python-hint.js
    diff --git a/mode/css/css.js b/mode/css/css.js index 2a211dc3c7..11394077ca 100644 --- a/mode/css/css.js +++ b/mode/css/css.js @@ -206,7 +206,7 @@ CodeMirror.defineMode("css", function(config, parserConfig) { states.pseudo = function(type, stream, state) { if (type == "word") { - override = "variable-2"; + override = "variable-3"; return state.context.type; } return pass(type, stream, state); @@ -601,7 +601,8 @@ CodeMirror.defineMode("css", function(config, parserConfig) { return [null, "interpolation"]; } }, - name: "css" + name: "css", + helperType: "scss" }); CodeMirror.defineMIME("text/x-less", { @@ -634,6 +635,7 @@ CodeMirror.defineMode("css", function(config, parserConfig) { return ["atom", "atom"]; } }, - name: "css" + name: "css", + helperType: "less" }); })(); From c1064c8d7b1c18547bfeeaece59b5992f6b64195 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 12 Dec 2013 14:20:28 +0100 Subject: [PATCH 0086/4131] [css mode] Fix bad context management Closes #2046 --- mode/css/css.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mode/css/css.js b/mode/css/css.js index 11394077ca..1723fe84ed 100644 --- a/mode/css/css.js +++ b/mode/css/css.js @@ -178,9 +178,9 @@ CodeMirror.defineMode("css", function(config, parserConfig) { } }; - states.maybeprop = function(type, _stream, state) { + states.maybeprop = function(type, stream, state) { if (type == ":") return pushContext(state, "prop"); - else return state.context.type; + return pass(type, stream, state); }; states.prop = function(type, stream, state) { @@ -280,7 +280,7 @@ CodeMirror.defineMode("css", function(config, parserConfig) { indent: function(state, textAfter) { var cx = state.context; - if (/^\}/.test(textAfter)) cx = cx.prev; + if (/^\}/.test(textAfter) && cx.prev) cx = cx.prev; return cx.indent; }, From b29f875bf71f2fcef9ce35f5b77c5d67adc2b5bf Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 12 Dec 2013 14:40:01 +0100 Subject: [PATCH 0087/4131] [css mode] Tweak indentation when opening @media block on new line Closes #2047 --- mode/css/css.js | 1 + 1 file changed, 1 insertion(+) diff --git a/mode/css/css.js b/mode/css/css.js index 1723fe84ed..478bc4132f 100644 --- a/mode/css/css.js +++ b/mode/css/css.js @@ -281,6 +281,7 @@ CodeMirror.defineMode("css", function(config, parserConfig) { indent: function(state, textAfter) { var cx = state.context; if (/^\}/.test(textAfter) && cx.prev) cx = cx.prev; + if (/^\{/.test(textAfter) && cx.type == "media") cx = cx.prev; return cx.indent; }, From febe3acfe42bc1f94279fe6dd81a93946d12fa32 Mon Sep 17 00:00:00 2001 From: eborden Date: Wed, 11 Dec 2013 11:44:31 -0500 Subject: [PATCH 0088/4131] [javascript-lint addon] Put JSHint options in a sub-object Passing options causes issues in jshint since lint options are also passed. These options cause bad option errors in the annotation list. --- addon/lint/lint.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addon/lint/lint.js b/addon/lint/lint.js index b502ee41f1..6121735d3f 100644 --- a/addon/lint/lint.js +++ b/addon/lint/lint.js @@ -112,7 +112,7 @@ if (options.async) options.getAnnotations(cm, updateLinting, options); else - updateLinting(cm, options.getAnnotations(cm.getValue(), options)); + updateLinting(cm, options.getAnnotations(cm.getValue(), options.options)); } function updateLinting(cm, annotationsNotSorted) { From d3c3a5a2b8df669ed12fe90df4d62a143c0a9d25 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 12 Dec 2013 14:47:16 +0100 Subject: [PATCH 0089/4131] [css mode] Fix tokenization of paren-wrapped values Closes #2048 --- mode/css/css.js | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/mode/css/css.js b/mode/css/css.js index 478bc4132f..265b5c9d48 100644 --- a/mode/css/css.js +++ b/mode/css/css.js @@ -69,14 +69,13 @@ CodeMirror.defineMode("css", function(config, parserConfig) { return function(stream, state) { var escaped = false, ch; while ((ch = stream.next()) != null) { - if (ch == quote && !escaped) + if (ch == quote && !escaped) { + if (nonInclusive) stream.backUp(1); break; + } escaped = !escaped && ch == "\\"; } - if (!escaped) { - if (nonInclusive) stream.backUp(1); - state.tokenize = null; - } + if (!escaped) state.tokenize = null; return ret("string", "string"); }; } From 0b17e247b036bcb484f36c9f966ea8dbbcb6fa72 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 12 Dec 2013 15:04:52 +0100 Subject: [PATCH 0090/4131] [css mode] Fix previous fix (d3c3a5a2b8df669ed12fe90df4d62a143c0a9d25) Issue #2048 --- mode/css/css.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/mode/css/css.js b/mode/css/css.js index 265b5c9d48..cfeafbd5e8 100644 --- a/mode/css/css.js +++ b/mode/css/css.js @@ -65,17 +65,17 @@ CodeMirror.defineMode("css", function(config, parserConfig) { } } - function tokenString(quote, nonInclusive) { + function tokenString(quote) { return function(stream, state) { var escaped = false, ch; while ((ch = stream.next()) != null) { if (ch == quote && !escaped) { - if (nonInclusive) stream.backUp(1); + if (quote == ")") stream.backUp(1); break; } escaped = !escaped && ch == "\\"; } - if (!escaped) state.tokenize = null; + if (ch == quote || !escaped && quote != ")") state.tokenize = null; return ret("string", "string"); }; } @@ -83,7 +83,7 @@ CodeMirror.defineMode("css", function(config, parserConfig) { function tokenParenthesized(stream, state) { stream.next(); // Must be '(' if (!stream.match(/\s*[\"\']/, false)) - state.tokenize = tokenString(")", true); + state.tokenize = tokenString(")"); else state.tokenize = null; return ret(null, "("); From a76bd4f2d28068f12aff0713dd0300a51eb8d3d3 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 12 Dec 2013 15:30:09 +0100 Subject: [PATCH 0091/4131] [css mode] Revise indentation model Issue #2049 --- mode/css/css.js | 40 +++++++++++++++++++++++----------------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/mode/css/css.js b/mode/css/css.js index cfeafbd5e8..d1a1def6f7 100644 --- a/mode/css/css.js +++ b/mode/css/css.js @@ -97,8 +97,8 @@ CodeMirror.defineMode("css", function(config, parserConfig) { this.prev = prev; } - function pushContext(state, type) { - state.context = new Context(type, state.context.indent + indentUnit, state.context); + function pushContext(state, stream, type) { + state.context = new Context(type, stream.indentation() + indentUnit, state.context); return type; } @@ -130,15 +130,15 @@ CodeMirror.defineMode("css", function(config, parserConfig) { var states = {}; - states.top = function(type, _stream, state) { + states.top = function(type, stream, state) { if (type == "{") { - return pushContext(state, "block"); + return pushContext(state, stream, "block"); } else if (type == "}" && state.context.prev) { return popContext(state); } else if (type == "@media") { - return pushContext(state, "media"); + return pushContext(state, stream, "media"); } else if (type && type.charAt(0) == "@") { - return pushContext(state, "at"); + return pushContext(state, stream, "at"); } else if (type == "hash") { override = "builtin"; } else if (type == "word") { @@ -146,11 +146,11 @@ CodeMirror.defineMode("css", function(config, parserConfig) { } else if (type == "variable-definition") { return "maybeprop"; } else if (type == "interpolation") { - return pushContext(state, "interpolation"); + return pushContext(state, stream, "interpolation"); } else if (type == ":") { return "pseudo"; } else if (allowNested && type == "(") { - return pushContext(state, "params"); + return pushContext(state, stream, "params"); } return state.context.type; }; @@ -178,21 +178,21 @@ CodeMirror.defineMode("css", function(config, parserConfig) { }; states.maybeprop = function(type, stream, state) { - if (type == ":") return pushContext(state, "prop"); + if (type == ":") return pushContext(state, stream, "prop"); return pass(type, stream, state); }; states.prop = function(type, stream, state) { if (type == ";") return popContext(state); if (type == "}" || type == "{") return popAndPass(type, stream, state); - if (type == "(") return pushContext(state, "parens"); + if (type == "(") return pushContext(state, stream, "parens"); if (type == "hash" && !/^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/.test(stream.current())) { override += " error"; } else if (type == "word") { wordAsValue(stream); } else if (type == "interpolation") { - return pushContext(state, "interpolation"); + return pushContext(state, stream, "interpolation"); } return "prop"; }; @@ -212,9 +212,9 @@ CodeMirror.defineMode("css", function(config, parserConfig) { }; states.media = function(type, stream, state) { - if (type == "(") return pushContext(state, "media_parens"); + if (type == "(") return pushContext(state, stream, "media_parens"); if (type == "}") return popAndPass(type, stream, state); - if (type == "{") return popContext(state) && pushContext(state, allowNested ? "block" : "top"); + if (type == "{") return popContext(state) && pushContext(state, stream, allowNested ? "block" : "top"); if (type == "word") { var word = stream.current().toLowerCase(); @@ -278,10 +278,16 @@ CodeMirror.defineMode("css", function(config, parserConfig) { }, indent: function(state, textAfter) { - var cx = state.context; - if (/^\}/.test(textAfter) && cx.prev) cx = cx.prev; - if (/^\{/.test(textAfter) && cx.type == "media") cx = cx.prev; - return cx.indent; + var cx = state.context, ch = textAfter && textAfter.charAt(0); + var indent = cx.indent; + if (cx.prev && + (ch == "}" && (cx.type == "block" || cx.type == "top" || cx.type == "interpolation") || + ch == ")" && (cx.type == "parens" || cx.type == "params" || cx.type == "media_parens") || + ch == "{" && (cx.type == "at" || cx.type == "media"))) { + indent = cx.indent - indentUnit; + cx = cx.prev; + } + return indent; }, electricChars: "}", From f943b027c8646a055835b6c23f5de655ed803f0d Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 12 Dec 2013 16:38:37 +0100 Subject: [PATCH 0092/4131] [javascript mode] Fix bug in parsing of array/iterator comprehension --- mode/javascript/javascript.js | 9 ++++----- mode/javascript/test.js | 36 ++++++++++++++++++++++++++++++++++- 2 files changed, 39 insertions(+), 6 deletions(-) diff --git a/mode/javascript/javascript.js b/mode/javascript/javascript.js index c49b873317..c113fcb433 100644 --- a/mode/javascript/javascript.js +++ b/mode/javascript/javascript.js @@ -15,7 +15,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { var jsKeywords = { "if": kw("if"), "while": A, "with": A, "else": B, "do": B, "try": B, "finally": B, - "return": C, "break": C, "continue": C, "new": C, "delete": C, "throw": C, + "return": C, "break": C, "continue": C, "new": C, "delete": C, "throw": C, "debugger": C, "var": kw("var"), "const": kw("var"), "let": kw("var"), "function": kw("function"), "catch": kw("catch"), "for": kw("for"), "switch": kw("switch"), "case": kw("case"), "default": kw("default"), @@ -304,7 +304,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { if (type == ";") return cont(); if (type == "if") return cont(pushlex("form"), expression, statement, poplex, maybeelse); if (type == "function") return cont(functiondef); - if (type == "for") return cont(pushlex("form"), forspec, poplex, statement, poplex); + if (type == "for") return cont(pushlex("form"), forspec, statement, poplex); if (type == "variable") return cont(pushlex("stat"), maybelabel); if (type == "switch") return cont(pushlex("form"), expression, pushlex("}", "switch"), expect("{"), block, poplex, poplex); @@ -370,7 +370,6 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { if (type == "[") return cont(pushlex("]"), maybeexpression, expect("]"), poplex, me); } function quasi(value) { - if (!value) debugger; if (value.slice(value.length - 2) != "${") return cont(); return cont(expression, continueQuasi); } @@ -474,7 +473,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { if (type == "keyword b" && value == "else") return cont(pushlex("form"), statement, poplex); } function forspec(type) { - if (type == "(") return cont(pushlex(")"), forspec1, expect(")")); + if (type == "(") return cont(pushlex(")"), forspec1, expect(")"), poplex); } function forspec1(type) { if (type == "var") return cont(vardef, expect(";"), forspec2); @@ -538,7 +537,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { return pass(expressionNoComma, maybeArrayComprehension); } function maybeArrayComprehension(type) { - if (type == "for") return pass(comprehension); + if (type == "for") return pass(comprehension, expect("]")); if (type == ",") return cont(commasep(expressionNoComma, "]")); return pass(commasep(expressionNoComma, "]")); } diff --git a/mode/javascript/test.js b/mode/javascript/test.js index 760152499e..8abd633542 100644 --- a/mode/javascript/test.js +++ b/mode/javascript/test.js @@ -63,10 +63,44 @@ MT("comprehension", "[keyword function] [variable f]() {", - " [[ [variable x] + [number 1] [keyword for] ([keyword var] [def x] [keyword in] [variable y]) [keyword if] [variable pred]([variable-2 x]) ]];", + " [[([variable x] + [number 1]) [keyword for] ([keyword var] [def x] [keyword in] [variable y]) [keyword if] [variable pred]([variable-2 x]) ]];", " ([variable u] [keyword for] ([keyword var] [def u] [keyword of] [variable generateValues]()) [keyword if] ([variable-2 u].[property color] === [string 'blue']));", "}"); MT("quasi", "[variable re][string-2 `fofdlakj${][variable x] + ([variable re][string-2 `foo`]) + [number 1][string-2 }fdsa`] + [number 2]"); + + MT("indent_statement", + "[keyword var] [variable x] = [number 10]", + "[variable x] += [variable y] +", + " [atom Infinity]", + "[keyword debugger];"); + + MT("indent_if", + "[keyword if] ([number 1])", + " [keyword break];", + "[keyword else] [keyword if] ([number 2])", + " [keyword continue];", + "[keyword else]", + " [number 10];", + "[keyword if] ([number 1]) {", + " [keyword break];", + "} [keyword else] [keyword if] ([number 2]) {", + " [keyword continue];", + "} [keyword else] {", + " [number 10];", + "}"); + + MT("indent_for", + "[keyword for] ([keyword var] [variable i] = [number 0];", + " [variable i] < [number 100];", + " [variable i]++)", + " [variable doSomething]([variable i]);", + "[keyword debugger];"); + + MT("indent_c_style", + "[keyword function] [variable foo]()", + "{", + " [keyword debugger];", + "}"); })(); From d09247c69a051868fd966b5b8b19e91bc998dc8c Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 12 Dec 2013 16:47:45 +0100 Subject: [PATCH 0093/4131] [test driver] Different approach to indentation tests All tests now check whether indentation from mode corresponds to the indentation in the test source. test.indentation is gone. --- mode/css/less_test.js | 2 +- mode/css/scss_test.js | 40 +++++++++------- mode/css/test.js | 55 +++++++++++++--------- mode/haml/haml.js | 4 -- mode/haml/test.js | 2 +- test/mode_test.js | 103 +++++++++++++++--------------------------- 6 files changed, 95 insertions(+), 111 deletions(-) diff --git a/mode/css/less_test.js b/mode/css/less_test.js index 9b065f23d8..ea64f91d12 100644 --- a/mode/css/less_test.js +++ b/mode/css/less_test.js @@ -1,7 +1,7 @@ (function() { "use strict"; - var mode = CodeMirror.getMode({indentUnit: 1}, "text/x-less"); + var mode = CodeMirror.getMode({indentUnit: 2}, "text/x-less"); function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1), "less"); } MT("variable", diff --git a/mode/css/scss_test.js b/mode/css/scss_test.js index ed5de83801..c51cb42bba 100644 --- a/mode/css/scss_test.js +++ b/mode/css/scss_test.js @@ -1,7 +1,6 @@ (function() { - var mode = CodeMirror.getMode({indentUnit: 1}, "text/x-scss"); + var mode = CodeMirror.getMode({indentUnit: 2}, "text/x-scss"); function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1), "scss"); } - function IT(name) { test.indentation(name, mode, Array.prototype.slice.call(arguments, 1), "scss"); } MT('url_with_quotation', "[tag foo] { [property background]:[atom url]([string test.jpg]) }"); @@ -79,23 +78,30 @@ MT('nested_structure_with_id_selector', "[tag p] { [builtin #hello] { [property color]:[keyword red]; } }"); - IT('mixin', - "[1 @mixin container ($a: 10, $b: 10, $c: 10) {]}"); + MT('indent_mixin', + "[def @mixin] [tag container] (", + " [variable-2 $a]: [number 10],", + " [variable-2 $b]: [number 10])", + "{}"); - IT('nested', - "foo [1 { bar ][2 { ][1 } ]}"); - - IT('comma', - "foo [1 { font-family][2 : verdana, sans-serif][1 ; ]}"); + MT('indent_nested', + "[tag foo] {", + " [tag bar] {", + " }", + "}"); - IT('parentheses', - "foo [1 { color][2 : darken][3 ($blue, 9%][2 )][1 ; ]}"); + MT('indent_parentheses', + "[tag foo] {", + " [property color]: [variable darken]([variable-2 $blue],", + " [number 9%]);", + "}"); - IT('vardef', - "$name[1 : 'val'];", - "tag [1 {]", - "[1 inner ][2 {]", - "[2 margin][3 : 3px][2 ;]", - "[2 ][1 }]", + MT('indent_vardef', + "[variable-2 $name]:", + " [string 'val'];", + "[tag tag] {", + " [tag inner] {", + " [property margin]: [number 3px];", + " }", "}"); })(); diff --git a/mode/css/test.js b/mode/css/test.js index cbfbef46cc..425c26ed91 100644 --- a/mode/css/test.js +++ b/mode/css/test.js @@ -1,7 +1,6 @@ (function() { - var mode = CodeMirror.getMode({indentUnit: 1}, "css"); + var mode = CodeMirror.getMode({indentUnit: 2}, "css"); function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); } - function IT(name) { test.indentation(name, mode, Array.prototype.slice.call(arguments, 1)); } // Error, because "foobarhello" is neither a known type or property, but // property was expected (after "and"), and it should be in parenthese. @@ -38,11 +37,11 @@ "[tag foo] { [property font-family]: [string 'hello world']; }"); MT("tagColorKeyword", - "[tag foo] {" + - "[property color]: [keyword black];" + - "[property color]: [keyword navy];" + - "[property color]: [keyword yellow];" + - "}"); + "[tag foo] {", + " [property color]: [keyword black];", + " [property color]: [keyword navy];", + " [property color]: [keyword yellow];", + "}"); MT("tagColorHex3", "[tag foo] { [property background]: [atom #fff]; }"); @@ -81,18 +80,32 @@ "[comment ] [tag div] {}"); - IT("tagSelector", - "strong, em [1 { background][2 : rgba][3 (255, 255, 0, .2][2 )][1 ;]}"); - - IT("atMedia", - "[1 @media { foo ][2 { ][1 } ]}"); - - IT("comma", - "foo [1 { font-family][2 : verdana, sans-serif][1 ; ]}"); - - IT("parentheses", - "foo [1 { background][2 : url][3 (\"bar\"][2 )][1 ; ]}"); - - IT("pseudo", - "foo:before [1 { ]}"); + MT("indent_tagSelector", + "[tag strong], [tag em] {", + " [property background]: [atom rgba](", + " [number 255], [number 255], [number 0], [number .2]", + " );", + "}"); + + MT("indent_atMedia", + "[def @media] {", + " [tag foo] {", + " [property color]:", + " [keyword yellow];", + " }", + "}"); + + MT("indent_comma", + "[tag foo] {", + " [property font-family]: [variable verdana],", + " [atom sans-serif];", + "}"); + + MT("indent_parentheses", + "[tag foo]:[variable-3 before] {", + " [property background]: [atom url](", + "[string blahblah]", + "[string etc]", + "[string ]) [keyword !important];", + "}"); })(); diff --git a/mode/haml/haml.js b/mode/haml/haml.js index 793308f6fb..5ea4ed12c8 100644 --- a/mode/haml/haml.js +++ b/mode/haml/haml.js @@ -141,10 +141,6 @@ style = null; } return style; - }, - - indent: function(state) { - return state.indented; } }; }, "htmlmixed", "ruby"); diff --git a/mode/haml/test.js b/mode/haml/test.js index b7178d40fb..163b09f8dd 100644 --- a/mode/haml/test.js +++ b/mode/haml/test.js @@ -1,5 +1,5 @@ (function() { - var mode = CodeMirror.getMode({tabSize: 4}, "haml"); + var mode = CodeMirror.getMode({tabSize: 4, indentUnit: 2}, "haml"); function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); } // Requires at least one media query diff --git a/test/mode_test.js b/test/mode_test.js index 08deab74b2..46174e1f78 100644 --- a/test/mode_test.js +++ b/test/mode_test.js @@ -59,13 +59,6 @@ return {tokens: tokens, plain: plain}; } - test.indentation = function(name, mode, tokens, modeName) { - var data = parseTokens(tokens); - return test((modeName || mode.name) + "_indent_" + name, function() { - return compare(data.plain, data.tokens, mode, true); - }); - }; - test.mode = function(name, mode, tokens, modeName) { var data = parseTokens(tokens); return test((modeName || mode.name) + "_" + name, function() { @@ -73,7 +66,11 @@ }); }; - function compare(text, expected, mode, compareIndentation) { + function esc(str) { + return str.replace('&', '&').replace('<', '<'); + } + + function compare(text, expected, mode) { var expectedOutput = []; for (var i = 0; i < expected.length; i += 2) { @@ -82,59 +79,48 @@ expectedOutput.push(sty, expected[i + 1]); } - var observedOutput = highlight(text, mode, compareIndentation); + var observedOutput = highlight(text, mode); - var pass, passStyle = ""; - pass = highlightOutputsEqual(expectedOutput, observedOutput); - passStyle = pass ? 'mt-pass' : 'mt-fail'; - - var s = ''; - if (pass) { - s += '
    '; - s += '
    ' + text.replace('&', '&').replace('<', '<') + '
    '; - s += '
    '; - s += prettyPrintOutputTable(observedOutput); - s += '
    '; - s += '
    '; - return s; - } else { - s += '
    '; - s += '
    ' + text.replace('&', '&').replace('<', '<') + '
    '; + var s = ""; + var diff = highlightOutputsDifferent(expectedOutput, observedOutput); + if (diff != null) { + s += '
    '; + s += '
    ' + esc(text) + '
    '; s += '
    '; s += 'expected:'; - s += prettyPrintOutputTable(expectedOutput); + s += prettyPrintOutputTable(expectedOutput, diff); s += 'observed:'; - s += prettyPrintOutputTable(observedOutput); + s += prettyPrintOutputTable(observedOutput, diff); s += '
    '; s += '
    '; - throw s; } + if (observedOutput.indentFailures) { + for (var i = 0; i < observedOutput.indentFailures.length; i++) + s += "
    " + esc(observedOutput.indentFailures[i]) + "
    "; + } + if (s) throw new Failure(s); } - /** - * Emulation of CodeMirror's internal highlight routine for testing. Multi-line - * input is supported. - * - * @param string to highlight - * - * @param mode the mode that will do the actual highlighting - * - * @return array of [style, token] pairs - */ - function highlight(string, mode, compareIndentation) { + function highlight(string, mode) { var state = mode.startState() var lines = string.replace(/\r\n/g,'\n').split('\n'); var st = [], pos = 0; for (var i = 0; i < lines.length; ++i) { var line = lines[i], newLine = true; + if (mode.indent) { + var ws = line.match(/^\s*/)[0]; + var indent = mode.indent(state, line.slice(ws.length)); + if (indent != CodeMirror.Pass && indent != ws.length) + (st.indentFailures || (st.indentFailures = [])).push( + "Indentation of line " + (i + 1) + " is " + indent + " (expected " + ws.length + ")"); + } var stream = new CodeMirror.StringStream(line); if (line == "" && mode.blankLine) mode.blankLine(state); /* Start copied code from CodeMirror.highlight */ while (!stream.eol()) { var compare = mode.token(stream, state), substr = stream.current(); - if (compareIndentation) compare = mode.indent(state) || null; - else if (compare && compare.indexOf(" ") > -1) compare = compare.split(' ').sort().join(' '); + if (compare && compare.indexOf(" ") > -1) compare = compare.split(' ').sort().join(' '); stream.start = stream.pos; if (pos && st[pos-2] == compare && !newLine) { st[pos-1] += substr; @@ -153,39 +139,22 @@ return st; } - /** - * Compare two arrays of output from highlight. - * - * @param o1 array of [style, token] pairs - * - * @param o2 array of [style, token] pairs - * - * @return boolean; true iff outputs equal - */ - function highlightOutputsEqual(o1, o2) { - if (o1.length != o2.length) return false; - for (var i = 0; i < o1.length; ++i) - if (o1[i] != o2[i]) return false; - return true; + function highlightOutputsDifferent(o1, o2) { + var minLen = Math.min(o1.length, o2.length); + for (var i = 0; i < minLen; ++i) + if (o1[i] != o2[i]) return i >> 1; + if (o1.length > minLen || o2.length > minLen) return minLen; } - /** - * Print tokens and corresponding styles in a table. Spaces in the token are - * replaced with 'interpunct' dots (·). - * - * @param output array of [style, token] pairs - * - * @return html string - */ - function prettyPrintOutputTable(output) { + function prettyPrintOutputTable(output, diffAt) { var s = ''; s += ''; for (var i = 0; i < output.length; i += 2) { var style = output[i], val = output[i+1]; s += - ''; } From 72f01e8cd33808cc56a85457949bfd5a49362656 Mon Sep 17 00:00:00 2001 From: Alexander Solovyov Date: Thu, 12 Dec 2013 23:30:47 +0200 Subject: [PATCH 0094/4131] [coffeescript mode] Allow single-quote-character strings to span lines Closes #2050 --- mode/coffeescript/coffeescript.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/mode/coffeescript/coffeescript.js b/mode/coffeescript/coffeescript.js index e8bfe48a24..0e9e6352f8 100644 --- a/mode/coffeescript/coffeescript.js +++ b/mode/coffeescript/coffeescript.js @@ -119,13 +119,13 @@ CodeMirror.defineMode("coffeescript", function(conf) { // Handle strings if (stream.match(stringPrefixes)) { - state.tokenize = tokenFactory(stream.current(), "string"); + state.tokenize = tokenFactory(stream.current(), false, "string"); return state.tokenize(stream, state); } // Handle regex literals if (stream.match(regexPrefixes)) { if (stream.current() != "/" || stream.match(/^.*\//, false)) { // prevent highlight of division - state.tokenize = tokenFactory(stream.current(), "string-2"); + state.tokenize = tokenFactory(stream.current(), true, "string-2"); return state.tokenize(stream, state); } else { stream.backUp(1); @@ -161,8 +161,7 @@ CodeMirror.defineMode("coffeescript", function(conf) { return ERRORCLASS; } - function tokenFactory(delimiter, outclass) { - var singleline = delimiter.length == 1; + function tokenFactory(delimiter, singleline, outclass) { return function(stream, state) { while (!stream.eol()) { stream.eatWhile(/[^'"\/\\]/); From b8e7854ada5c231c63e60ce0498fffbff65be46d Mon Sep 17 00:00:00 2001 From: Abe Fettig Date: Wed, 27 Nov 2013 12:16:05 -0500 Subject: [PATCH 0095/4131] [show-hint addon] Add completeOnSingleClick option ... to make a single-click pick a hint option instead of just selecting it. --- addon/hint/show-hint.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/addon/hint/show-hint.js b/addon/hint/show-hint.js index 76f020cf0a..1c60603ea2 100644 --- a/addon/hint/show-hint.js +++ b/addon/hint/show-hint.js @@ -235,7 +235,10 @@ CodeMirror.on(hints, "click", function(e) { var t = getHintElement(hints, e.target || e.srcElement); - if (t && t.hintId != null) widget.changeActive(t.hintId); + if (t && t.hintId != null) { + widget.changeActive(t.hintId); + if (options.completeOnSingleClick) widget.pick(); + } }); CodeMirror.on(hints, "mousedown", function() { From 0cf23eea94afbf735ada31a5f300e60f65425e77 Mon Sep 17 00:00:00 2001 From: hitsthings Date: Mon, 2 Dec 2013 10:50:04 +1100 Subject: [PATCH 0096/4131] Fix IE showing empty with 0 padding and resize-to-content Fixes #2011 in at least IE8+. When the resize-to-content styles are applied along with a removal of vertical padding on .CodeMirror-lines, IE would not display any content. Using `offsetWidth` instead of `clientWidth` fixes this for modern-ish IE. A more complex solution is needed to solve it for older browsers. --- lib/codemirror.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/codemirror.js b/lib/codemirror.js index 7b1b67dc0e..ec1bee3c28 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -450,7 +450,7 @@ window.CodeMirror = (function() { // updates. function updateDisplayInner(cm, changes, visible, forced) { var display = cm.display, doc = cm.doc; - if (!display.wrapper.clientWidth) { + if (!display.wrapper.offsetWidth) { display.showingFrom = display.showingTo = doc.first; display.viewOffset = 0; return; From 78435a5f1d61f8ba93386e8d865c4051b2e3c0f2 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Sun, 15 Dec 2013 13:43:09 +0100 Subject: [PATCH 0097/4131] [runmode addon] Add resolveMode and registerHelper shims Needed for some modes to load. Closes #2054 --- addon/runmode/runmode-standalone.js | 21 +++++++++++++-------- addon/runmode/runmode.node.js | 21 +++++++++++++-------- 2 files changed, 26 insertions(+), 16 deletions(-) diff --git a/addon/runmode/runmode-standalone.js b/addon/runmode/runmode-standalone.js index d117166c98..2866b252ee 100644 --- a/addon/runmode/runmode-standalone.js +++ b/addon/runmode/runmode-standalone.js @@ -69,17 +69,22 @@ CodeMirror.startState = function (mode, a1, a2) { var modes = CodeMirror.modes = {}, mimeModes = CodeMirror.mimeModes = {}; CodeMirror.defineMode = function (name, mode) { modes[name] = mode; }; CodeMirror.defineMIME = function (mime, spec) { mimeModes[mime] = spec; }; -CodeMirror.getMode = function (options, spec) { - if (typeof spec == "string" && mimeModes.hasOwnProperty(spec)) +CodeMirror.resolveMode = function(spec) { + if (typeof spec == "string" && mimeModes.hasOwnProperty(spec)) { spec = mimeModes[spec]; - if (typeof spec == "string") - var mname = spec, config = {}; - else if (spec != null) - var mname = spec.name, config = spec; - var mfactory = modes[mname]; + } else if (spec && typeof spec.name == "string" && mimeModes.hasOwnProperty(spec.name)) { + spec = mimeModes[spec.name]; + } + if (typeof spec == "string") return {name: spec}; + else return spec || {name: "null"}; +}; +CodeMirror.getMode = function (options, spec) { + spec = CodeMirror.resolveMode(spec); + var mfactory = modes[spec.name]; if (!mfactory) throw new Error("Unknown mode: " + spec); - return mfactory(options, config || {}); + return mfactory(options, spec); }; +CodeMirror.registerHelper = CodeMirror.registerGlobalHelper = Math.min; CodeMirror.runMode = function (string, modespec, callback, options) { var mode = CodeMirror.getMode({ indentUnit: 2 }, modespec); diff --git a/addon/runmode/runmode.node.js b/addon/runmode/runmode.node.js index 0f1088fa2e..304640fa62 100644 --- a/addon/runmode/runmode.node.js +++ b/addon/runmode/runmode.node.js @@ -76,17 +76,22 @@ exports.defineMode("null", function() { }); exports.defineMIME("text/plain", "null"); -exports.getMode = function(options, spec) { - if (typeof spec == "string" && mimeModes.hasOwnProperty(spec)) +exports.resolveMode = function(spec) { + if (typeof spec == "string" && mimeModes.hasOwnProperty(spec)) { spec = mimeModes[spec]; - if (typeof spec == "string") - var mname = spec, config = {}; - else if (spec != null) - var mname = spec.name, config = spec; - var mfactory = modes[mname]; + } else if (spec && typeof spec.name == "string" && mimeModes.hasOwnProperty(spec.name)) { + spec = mimeModes[spec.name]; + } + if (typeof spec == "string") return {name: spec}; + else return spec || {name: "null"}; +}; +exports.getMode = function(options, spec) { + spec = exports.resolveMode(mimeModes[spec]); + var mfactory = modes[spec.name]; if (!mfactory) throw new Error("Unknown mode: " + spec); - return mfactory(options, config || {}); + return mfactory(options, spec); }; +CodeMirror.registerHelper = CodeMirror.registerGlobalHelper = Math.min; exports.runMode = function(string, modespec, callback) { var mode = exports.getMode({indentUnit: 2}, modespec); From ea7397c17662607248a83f2769cfaea1100d2d8b Mon Sep 17 00:00:00 2001 From: Brandon Frohs Date: Mon, 16 Dec 2013 21:05:47 -0500 Subject: [PATCH 0098/4131] [markdown] Lists after atx headers should be highlighted Closes #2040 --- mode/markdown/markdown.js | 13 +++++++++---- mode/markdown/test.js | 5 +++++ 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/mode/markdown/markdown.js b/mode/markdown/markdown.js index 2469479ea0..c959242ac6 100644 --- a/mode/markdown/markdown.js +++ b/mode/markdown/markdown.js @@ -664,7 +664,15 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) { state.formatting = false; if (stream.sol()) { - if (stream.match(/^\s*$/, true)) { + var forceBlankLine = false; + if (stream.match(/^\s*$/, true) || state.header) { + forceBlankLine = true; + } + + // Reset state.header + state.header = 0; + + if (forceBlankLine) { state.prevLineHasContent = false; return blankLine(state); } else { @@ -675,9 +683,6 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) { // Reset state.escape state.escape = false; - // Reset state.header - state.header = 0; - // Reset state.taskList state.taskList = false; diff --git a/mode/markdown/test.js b/mode/markdown/test.js index 21ceab7650..bc5cc97380 100644 --- a/mode/markdown/test.js +++ b/mode/markdown/test.js @@ -276,6 +276,11 @@ "1. bar", "2. hello"); + // List after header + MT("listAfterHeader", + "[header&header1 # foo]", + "[variable-2 - bar]"); + // Formatting in lists (*) MT("listAsteriskFormatting", "[variable-2 * ][variable-2&em *foo*][variable-2 bar]", From 8f8da43cc78f41a399d44f78b3a876b8e34a56f8 Mon Sep 17 00:00:00 2001 From: Brandon Frohs Date: Mon, 16 Dec 2013 21:42:09 -0500 Subject: [PATCH 0099/4131] [markdown] Specify type of list when highlightFormatting is enabled Closes #2039 --- mode/gfm/test.js | 4 ++-- mode/markdown/markdown.js | 11 +++++++++-- mode/markdown/test.js | 4 ++-- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/mode/gfm/test.js b/mode/gfm/test.js index 7d17517e18..e5c3486ebd 100644 --- a/mode/gfm/test.js +++ b/mode/gfm/test.js @@ -16,8 +16,8 @@ "[comment&formatting&formatting-code-block ```]"); FT("taskList", - "[variable-2&formatting&formatting-list - ][meta&formatting&formatting-task [ ]]][variable-2 foo]", - "[variable-2&formatting&formatting-list - ][property&formatting&formatting-task [x]]][variable-2 foo]"); + "[variable-2&formatting&formatting-list&formatting-list-ul - ][meta&formatting&formatting-task [ ]]][variable-2 foo]", + "[variable-2&formatting&formatting-list&formatting-list-ul - ][property&formatting&formatting-task [x]]][variable-2 foo]"); MT("emInWordAsterisk", "foo[em *bar*]hello"); diff --git a/mode/markdown/markdown.js b/mode/markdown/markdown.js index c959242ac6..6370462772 100644 --- a/mode/markdown/markdown.js +++ b/mode/markdown/markdown.js @@ -165,7 +165,14 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) { return switchInline(stream, state, footnoteLink); } else if (stream.match(hrRE, true)) { return hr; - } else if ((!state.prevLineHasContent || prevLineIsList) && (stream.match(ulRE, true) || stream.match(olRE, true))) { + } else if ((!state.prevLineHasContent || prevLineIsList) && (stream.match(ulRE, false) || stream.match(olRE, false))) { + var listType = null; + if (stream.match(ulRE, true)) { + listType = 'ul'; + } else { + stream.match(olRE, true); + listType = 'ol'; + } state.indentation += 4; state.list = true; state.listDepth++; @@ -173,7 +180,7 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) { state.taskList = true; } state.f = state.inline; - if (modeCfg.highlightFormatting) state.formatting = "list"; + if (modeCfg.highlightFormatting) state.formatting = ["list", "list-" + listType]; return getType(state); } else if (modeCfg.fencedCodeBlocks && stream.match(/^```([\w+#]*)/, true)) { // try switching mode diff --git a/mode/markdown/test.js b/mode/markdown/test.js index bc5cc97380..96572025d8 100644 --- a/mode/markdown/test.js +++ b/mode/markdown/test.js @@ -33,9 +33,9 @@ "[atom&formatting&formatting-quote > ][atom foo]"); FT("formatting_list", - "[variable-2&formatting&formatting-list - ][variable-2 foo]"); + "[variable-2&formatting&formatting-list&formatting-list-ul - ][variable-2 foo]"); FT("formatting_list", - "[variable-2&formatting&formatting-list 1. ][variable-2 foo]"); + "[variable-2&formatting&formatting-list&formatting-list-ol 1. ][variable-2 foo]"); FT("formatting_link", "[link&formatting&formatting-link [][link foo][link&formatting&formatting-link ]]][string&formatting&formatting-link-string (][string http://example.com/][string&formatting&formatting-link-string )]"); From 4536d5a81db213a0b82f07f2bbde5b48602165ea Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Tue, 17 Dec 2013 18:19:36 +0100 Subject: [PATCH 0100/4131] [real-world uses] Add writeLaTeX --- doc/realworld.html | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/realworld.html b/doc/realworld.html index 156eacd097..b9e35f2dfc 100644 --- a/doc/realworld.html +++ b/doc/realworld.html @@ -128,6 +128,7 @@

    CodeMirror real-world uses

  • WebKit Web inspector
  • WeScheme (learning tool)
  • WordPress plugin
  • +
  • writeLaTeX (Collaborative LaTeX Editor)
  • XOSide (online editor)
  • XQuery tester
  • xsd2codemirror (convert XSD to CM XML completion info)
  • From 2f266c38a6ea69f7fff990dbd861b93f7689de22 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Wed, 18 Dec 2013 13:48:33 +0100 Subject: [PATCH 0101/4131] Don't close undo events by default in changeGeneration Closes #2059 --- doc/manual.html | 8 ++++++-- lib/codemirror.js | 9 +++++---- test/test.js | 15 +++++++++++++++ 3 files changed, 26 insertions(+), 6 deletions(-) diff --git a/doc/manual.html b/doc/manual.html index 957ab347c5..33953c11ea 100644 --- a/doc/manual.html +++ b/doc/manual.html @@ -935,10 +935,14 @@

    Content manipulation methods

    of changeGeneration, which allows multiple subsystems to track different notions of cleanness without interfering. -
    doc.changeGeneration() → integer
    +
    doc.changeGeneration(?closeEvent: boolean) → integer
    Returns a number that can later be passed to isClean to test whether - any edits were made (and not undone) in the meantime.
    + any edits were made (and not undone) in the meantime. + If closeEvent is true, the current history event + will be ‘closed’, meaning it can't be combined with further + changes (rapid typing or deleting events are typically + combined).
    doc.isClean(?generation: integer) → boolean
    Returns whether the document is currently clean — not modified since initialization or the last call diff --git a/lib/codemirror.js b/lib/codemirror.js index ec1bee3c28..abf17eed74 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -4984,10 +4984,11 @@ window.CodeMirror = (function() { clearHistory: function() {this.history = makeHistory(this.history.maxGeneration);}, markClean: function() { - this.cleanGeneration = this.changeGeneration(); + this.cleanGeneration = this.changeGeneration(true); }, - changeGeneration: function() { - this.history.lastOp = this.history.lastOrigin = null; + changeGeneration: function(forceSplit) { + if (forceSplit) + this.history.lastOp = this.history.lastOrigin = null; return this.history.generation; }, isClean: function (gen) { @@ -5291,10 +5292,10 @@ window.CodeMirror = (function() { anchorBefore: doc.sel.anchor, headBefore: doc.sel.head, anchorAfter: selAfter.anchor, headAfter: selAfter.head}; hist.done.push(cur); - hist.generation = ++hist.maxGeneration; while (hist.done.length > hist.undoDepth) hist.done.shift(); } + hist.generation = ++hist.maxGeneration; hist.lastTime = time; hist.lastOp = opId; hist.lastOrigin = change.origin; diff --git a/test/test.js b/test/test.js index 86b0bfe178..3ad8d35499 100644 --- a/test/test.js +++ b/test/test.js @@ -1479,6 +1479,21 @@ testCM("dirtyBit", function(cm) { eq(cm.isClean(), true); }); +testCM("changeGeneration", function(cm) { + cm.replaceSelection("x", null, "+insert"); + var softGen = cm.changeGeneration(); + cm.replaceSelection("x", null, "+insert"); + cm.undo(); + eq(cm.getValue(), ""); + is(!cm.isClean(softGen)); + cm.replaceSelection("x", null, "+insert"); + var hardGen = cm.changeGeneration(true); + cm.replaceSelection("x", null, "+insert"); + cm.undo(); + eq(cm.getValue(), "x"); + is(cm.isClean(hardGen)); +}); + testCM("addKeyMap", function(cm) { function sendKey(code) { cm.triggerOnKeyDown({type: "keydown", keyCode: code, From d13582f3d8867fb39a9c154bfd4d60a17e213667 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Wed, 18 Dec 2013 14:06:53 +0100 Subject: [PATCH 0102/4131] [run-mode addon] Add hideFirstChars to stand-alone shims Issue #2054 --- addon/runmode/runmode-standalone.js | 10 ++++++++-- addon/runmode/runmode.node.js | 10 ++++++++-- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/addon/runmode/runmode-standalone.js b/addon/runmode/runmode-standalone.js index 2866b252ee..fcb3db35c8 100644 --- a/addon/runmode/runmode-standalone.js +++ b/addon/runmode/runmode-standalone.js @@ -10,6 +10,7 @@ function splitLines(string){ return string.split(/\r?\n|\r/); }; function StringStream(string) { this.pos = this.start = 0; this.string = string; + this.lineStart = 0; } StringStream.prototype = { eol: function() {return this.pos >= this.string.length;}, @@ -41,7 +42,7 @@ StringStream.prototype = { if (found > -1) {this.pos = found; return true;} }, backUp: function(n) {this.pos -= n;}, - column: function() {return this.start;}, + column: function() {return this.start - this.lineStart;}, indentation: function() {return 0;}, match: function(pattern, consume, caseInsensitive) { if (typeof pattern == "string") { @@ -58,7 +59,12 @@ StringStream.prototype = { return match; } }, - current: function(){return this.string.slice(this.start, this.pos);} + current: function(){return this.string.slice(this.start, this.pos);}, + hideFirstChars: function(n, inner) { + this.lineStart += n; + try { return inner(); } + finally { this.lineStart -= n; } + } }; CodeMirror.StringStream = StringStream; diff --git a/addon/runmode/runmode.node.js b/addon/runmode/runmode.node.js index 304640fa62..99f72ef02e 100644 --- a/addon/runmode/runmode.node.js +++ b/addon/runmode/runmode.node.js @@ -5,6 +5,7 @@ function splitLines(string){ return string.split(/\r?\n|\r/); }; function StringStream(string) { this.pos = this.start = 0; this.string = string; + this.lineStart = 0; } StringStream.prototype = { eol: function() {return this.pos >= this.string.length;}, @@ -36,7 +37,7 @@ StringStream.prototype = { if (found > -1) {this.pos = found; return true;} }, backUp: function(n) {this.pos -= n;}, - column: function() {return this.start;}, + column: function() {return this.start - this.lineStart;}, indentation: function() {return 0;}, match: function(pattern, consume, caseInsensitive) { if (typeof pattern == "string") { @@ -53,7 +54,12 @@ StringStream.prototype = { return match; } }, - current: function(){return this.string.slice(this.start, this.pos);} + current: function(){return this.string.slice(this.start, this.pos);}, + hideFirstChars: function(n, inner) { + this.lineStart += n; + try { return inner(); } + finally { this.lineStart -= n; } + } }; exports.StringStream = StringStream; From e3d64baf825459668f1c68e30ed11a40091df515 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Fri, 20 Dec 2013 17:22:49 +0100 Subject: [PATCH 0103/4131] [runmode addon] Fix broken node.js version Issue #2054 --- addon/runmode/runmode.node.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addon/runmode/runmode.node.js b/addon/runmode/runmode.node.js index 99f72ef02e..691af8b360 100644 --- a/addon/runmode/runmode.node.js +++ b/addon/runmode/runmode.node.js @@ -97,7 +97,7 @@ exports.getMode = function(options, spec) { if (!mfactory) throw new Error("Unknown mode: " + spec); return mfactory(options, spec); }; -CodeMirror.registerHelper = CodeMirror.registerGlobalHelper = Math.min; +exports.registerHelper = exports.registerGlobalHelper = Math.min; exports.runMode = function(string, modespec, callback) { var mode = exports.getMode({indentUnit: 2}, modespec); From 51234f9f35024f6c4f1abcf4a19b8df693826c09 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 26 Dec 2013 21:24:25 +0100 Subject: [PATCH 0104/4131] [runmode addon] Support a state option to provide a custom stating state --- addon/runmode/runmode-standalone.js | 2 +- addon/runmode/runmode.js | 2 +- addon/runmode/runmode.node.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/addon/runmode/runmode-standalone.js b/addon/runmode/runmode-standalone.js index fcb3db35c8..9ebde8b054 100644 --- a/addon/runmode/runmode-standalone.js +++ b/addon/runmode/runmode-standalone.js @@ -133,7 +133,7 @@ CodeMirror.runMode = function (string, modespec, callback, options) { }; } - var lines = splitLines(string), state = CodeMirror.startState(mode); + var lines = splitLines(string), state = (options && options.state) || CodeMirror.startState(mode); for (var i = 0, e = lines.length; i < e; ++i) { if (i) callback("\n"); var stream = new CodeMirror.StringStream(lines[i]); diff --git a/addon/runmode/runmode.js b/addon/runmode/runmode.js index 7aafa2ad8f..2cafa811f8 100644 --- a/addon/runmode/runmode.js +++ b/addon/runmode/runmode.js @@ -43,7 +43,7 @@ CodeMirror.runMode = function(string, modespec, callback, options) { }; } - var lines = CodeMirror.splitLines(string), state = CodeMirror.startState(mode); + var lines = CodeMirror.splitLines(string), state = (options && options.state) || CodeMirror.startState(mode); for (var i = 0, e = lines.length; i < e; ++i) { if (i) callback("\n"); var stream = new CodeMirror.StringStream(lines[i]); diff --git a/addon/runmode/runmode.node.js b/addon/runmode/runmode.node.js index 691af8b360..e8bccb0cf2 100644 --- a/addon/runmode/runmode.node.js +++ b/addon/runmode/runmode.node.js @@ -101,7 +101,7 @@ exports.registerHelper = exports.registerGlobalHelper = Math.min; exports.runMode = function(string, modespec, callback) { var mode = exports.getMode({indentUnit: 2}, modespec); - var lines = splitLines(string), state = exports.startState(mode); + var lines = splitLines(string), state = (options && options.state) || exports.startState(mode); for (var i = 0, e = lines.length; i < e; ++i) { if (i) callback("\n"); var stream = new exports.StringStream(lines[i]); From 4e9d808ff6c31475c5b85ab2de72328245343d75 Mon Sep 17 00:00:00 2001 From: Peter Kroon Date: Thu, 19 Dec 2013 21:03:42 +0100 Subject: [PATCH 0105/4131] Added builtin values And put string in alphabetical order. - varying - xml - bit --- mode/sql/sql.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mode/sql/sql.js b/mode/sql/sql.js index 3be68caa1a..53e06bab93 100644 --- a/mode/sql/sql.js +++ b/mode/sql/sql.js @@ -326,7 +326,7 @@ CodeMirror.defineMode("sql", function(config, parserConfig) { name: "sql", client: set("appinfo arraysize autocommit autoprint autorecovery autotrace blockterminator break btitle cmdsep colsep compatibility compute concat copycommit copytypecheck define describe echo editfile embedded escape exec execute feedback flagger flush heading headsep instance linesize lno loboffset logsource long longchunksize markup native newpage numformat numwidth pagesize pause pno recsep recsepchar release repfooter repheader serveroutput shiftinout show showmode size spool sqlblanklines sqlcase sqlcode sqlcontinue sqlnumber sqlpluscompatibility sqlprefix sqlprompt sqlterminator suffix tab term termout time timing trimout trimspool ttitle underline verify version wrap"), keywords: set("abort accept access add all alter and any array arraylen as asc assert assign at attributes audit authorization avg base_table begin between binary_integer body boolean by case cast char char_base check close cluster clusters colauth column comment commit compress connect connected constant constraint crash create current currval cursor data_base database date dba deallocate debugoff debugon decimal declare default definition delay delete desc digits dispose distinct do drop else elsif enable end entry escape exception exception_init exchange exclusive exists exit external fast fetch file for force form from function generic goto grant group having identified if immediate in increment index indexes indicator initial initrans insert interface intersect into is key level library like limited local lock log logging long loop master maxextents maxtrans member minextents minus mislabel mode modify multiset new next no noaudit nocompress nologging noparallel not nowait number_base object of off offline on online only open option or order out package parallel partition pctfree pctincrease pctused pls_integer positive positiven pragma primary prior private privileges procedure public raise range raw read rebuild record ref references refresh release rename replace resource restrict return returning reverse revoke rollback row rowid rowlabel rownum rows run savepoint schema segment select separate session set share snapshot some space split sql start statement storage subtype successful synonym tabauth table tables tablespace task terminate then to trigger truncate type union unique unlimited unrecoverable unusable update use using validate value values variable view views when whenever where while with work"), - builtin: set("bfile blob character clob dec float int integer mlslabel natural naturaln nchar nclob number numeric nvarchar2 real rowtype signtype smallint string varchar varchar2 abs acos add_months ascii asin atan atan2 average bfilename ceil chartorowid chr concat convert cos cosh count decode deref dual dump dup_val_on_index empty error exp false floor found glb greatest hextoraw initcap instr instrb isopen last_day least lenght lenghtb ln lower lpad ltrim lub make_ref max min mod months_between new_time next_day nextval nls_charset_decl_len nls_charset_id nls_charset_name nls_initcap nls_lower nls_sort nls_upper nlssort no_data_found notfound null nvl others power rawtohex reftohex round rowcount rowidtochar rpad rtrim sign sin sinh soundex sqlcode sqlerrm sqrt stddev substr substrb sum sysdate tan tanh to_char to_date to_label to_multi_byte to_number to_single_byte translate true trunc uid upper user userenv variance vsize"), + builtin: set("abs acos add_months ascii asin atan atan2 average bfile bfilename bit blob ceil character chartorowid chr clob concat convert cos cosh count dec decode deref dual dump dup_val_on_index empty error exp false float floor found glb greatest hextoraw initcap instr instrb int integer isopen last_day least lenght lenghtb ln lower lpad ltrim lub make_ref max min mlslabel mod months_between natural naturaln nchar nclob new_time next_day nextval nls_charset_decl_len nls_charset_id nls_charset_name nls_initcap nls_lower nls_sort nls_upper nlssort no_data_found notfound null number numeric nvarchar2 nvl others power rawtohex real reftohex round rowcount rowidtochar rowtype rpad rtrim sign signtype sin sinh smallint soundex sqlcode sqlerrm sqrt stddev string substr substrb sum sysdate tan tanh to_char text to_date to_label to_multi_byte to_number to_single_byte translate true trunc uid upper user userenv varchar varchar2 variance varying vsize xml"), operatorChars: /^[*+\-%<>!=~]/, dateSQL: set("date time timestamp"), support: set("doubleQuote nCharCast zerolessFloat binaryNumber hexNumber") From b6efcb93982269cfe1707563a45bb4f11886b421 Mon Sep 17 00:00:00 2001 From: Travis Heppe Date: Wed, 27 Nov 2013 14:46:08 -0800 Subject: [PATCH 0106/4131] [vim keymap] Add support for , and --- keymap/vim.js | 44 ++++++++++++++++++++++++++++++++++++++++++++ test/vim_test.js | 27 +++++++++++++++++++++++++++ 2 files changed, 71 insertions(+) diff --git a/keymap/vim.js b/keymap/vim.js index 164d51b1a4..efb4de48ae 100644 --- a/keymap/vim.js +++ b/keymap/vim.js @@ -84,6 +84,7 @@ { 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', @@ -247,6 +248,12 @@ 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, @@ -1636,6 +1643,43 @@ markPos = markPos ? markPos : cm.getCursor(); cm.setCursor(markPos); }, + scroll: function(cm, actionArgs, vim) { + if (vim.visualMode) { + return; + } + var repeat = actionArgs.repeat || 1; + var lineHeight = cm.defaultTextHeight(); + var top = cm.getScrollInfo().top; + var delta = lineHeight * repeat; + var newPos = actionArgs.forward ? top + delta : top - delta; + var cursor = cm.getCursor(); + var cursorCoords = cm.charCoords(cursor, 'local'); + if (actionArgs.forward) { + if (newPos > cursorCoords.top) { + cursor.line += (newPos - cursorCoords.top) / lineHeight; + cursor.line = Math.ceil(cursor.line); + cm.setCursor(cursor); + cursorCoords = cm.charCoords(cursor, 'local'); + cm.scrollTo(null, cursorCoords.top); + } else { + // Cursor stays within bounds. Just reposition the scroll window. + cm.scrollTo(null, newPos); + } + } else { + var newBottom = newPos + cm.getScrollInfo().clientHeight; + if (newBottom < cursorCoords.bottom) { + cursor.line -= (cursorCoords.bottom - newBottom) / lineHeight; + cursor.line = Math.floor(cursor.line); + cm.setCursor(cursor); + cursorCoords = cm.charCoords(cursor, 'local'); + cm.scrollTo( + null, cursorCoords.bottom - cm.getScrollInfo().clientHeight); + } else { + // Cursor stays within bounds. Just reposition the scroll window. + cm.scrollTo(null, newPos); + } + } + }, scrollToCursor: function(cm, actionArgs) { var lineNum = cm.getCursor().line; var charCoords = cm.charCoords({line: lineNum, ch: 0}, 'local'); diff --git a/test/vim_test.js b/test/vim_test.js index c65b5cad03..1a5cc3ee3f 100644 --- a/test/vim_test.js +++ b/test/vim_test.js @@ -2003,6 +2003,33 @@ testVim('zt==z', function(cm, vim, helpers){ eq(zVals[2], zVals[5]); }); +var scrollMotionSandbox = + '\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n' + '\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n' + '\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n' + '\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n'; +testVim('scrollMotion', function(cm, vim, helpers){ + var prevCursor, prevScrollInfo; + cm.setCursor(0, 0); + // ctrl-y at the top of the file should have no effect. + helpers.doKeys(''); + eq(0, cm.getCursor().line); + prevScrollInfo = cm.getScrollInfo(); + helpers.doKeys(''); + eq(1, cm.getCursor().line); + eq(true, prevScrollInfo.top < cm.getScrollInfo().top); + // Jump to the end of the sandbox. + cm.setCursor(1000, 0); + prevCursor = cm.getCursor(); + // ctrl-e at the bottom of the file should have no effect. + helpers.doKeys(''); + eq(prevCursor.line, cm.getCursor().line); + prevScrollInfo = cm.getScrollInfo(); + helpers.doKeys(''); + eq(prevCursor.line - 1, cm.getCursor().line); + eq(true, prevScrollInfo.top > cm.getScrollInfo().top); +}, { value: scrollMotionSandbox}); + var squareBracketMotionSandbox = ''+ '({\n'+//0 ' ({\n'+//11 From d99da21fe85ac965b8ddc57b5daaa21104d650c9 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 26 Dec 2013 21:55:17 +0100 Subject: [PATCH 0107/4131] Fix problems introduced by new rule for indenting empty lines --- addon/edit/closetag.js | 4 ++-- lib/codemirror.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/addon/edit/closetag.js b/addon/edit/closetag.js index 106448d3d7..60e204bcf2 100644 --- a/addon/edit/closetag.js +++ b/addon/edit/closetag.js @@ -67,8 +67,8 @@ cm.replaceSelection(">" + (doIndent ? "\n\n" : "") + "", {head: curPos, anchor: curPos}); if (doIndent) { - cm.indentLine(pos.line + 1); - cm.indentLine(pos.line + 2); + cm.indentLine(pos.line + 1, null, true); + cm.indentLine(pos.line + 2, null); } } diff --git a/lib/codemirror.js b/lib/codemirror.js index abf17eed74..d66bfc4670 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -2932,7 +2932,7 @@ window.CodeMirror = (function() { }), indentSelection: operation(null, function(how) { var sel = this.doc.sel; - if (posEq(sel.from, sel.to)) return indentLine(this, sel.from.line, how); + if (posEq(sel.from, sel.to)) return indentLine(this, sel.from.line, how, true); var e = sel.to.line - (sel.to.ch ? 0 : 1); for (var i = sel.from.line; i <= e; ++i) indentLine(this, i, how); }), From 7bf3a0018c4248127c9939a6b48b8651f5088204 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 26 Dec 2013 21:57:10 +0100 Subject: [PATCH 0108/4131] [hardwrap addon] Prevent null-use error in corner case Closes #2070 --- addon/wrap/hardwrap.js | 1 + 1 file changed, 1 insertion(+) diff --git a/addon/wrap/hardwrap.js b/addon/wrap/hardwrap.js index 9260c75bbb..1faa3d84a6 100644 --- a/addon/wrap/hardwrap.js +++ b/addon/wrap/hardwrap.js @@ -36,6 +36,7 @@ var killTrailing = options.killTrailingSpace !== false; var changes = [], curLine = "", curNo = from.line; var lines = cm.getRange(from, to, false); + if (!lines.length) return; var leadingSpace = lines[0].match(/^[ \t]*/)[0]; for (var i = 0; i < lines.length; ++i) { From ed7f8d083f52e7b58827d46410278a8688e7aa74 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 26 Dec 2013 22:03:26 +0100 Subject: [PATCH 0109/4131] [sql mode] Don't return CodeMirror.Pass when in top context Issue #2064 --- mode/sql/sql.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mode/sql/sql.js b/mode/sql/sql.js index 53e06bab93..946e7b38fa 100644 --- a/mode/sql/sql.js +++ b/mode/sql/sql.js @@ -177,7 +177,7 @@ CodeMirror.defineMode("sql", function(config, parserConfig) { indent: function(state, textAfter) { var cx = state.context; - if (!cx) return CodeMirror.Pass; + if (!cx) return 0; if (cx.align) return cx.col + (textAfter.charAt(0) == cx.type ? 0 : 1); else return cx.indent + config.indentUnit; }, From d50ced613d1383e7e2f6ebe04217d71804493aea Mon Sep 17 00:00:00 2001 From: Peter Kroon Date: Mon, 23 Dec 2013 21:19:43 +0100 Subject: [PATCH 0110/4131] [matchbrackets addon] Fix typos --- addon/edit/matchbrackets.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addon/edit/matchbrackets.js b/addon/edit/matchbrackets.js index 9d9b3882f7..465b6ccaa9 100644 --- a/addon/edit/matchbrackets.js +++ b/addon/edit/matchbrackets.js @@ -54,7 +54,7 @@ var one = cm.markText(found.from, Pos(found.from.line, found.from.ch + 1), {className: style}); var two = found.to && cm.markText(found.to, Pos(found.to.line, found.to.ch + 1), {className: style}); // Kludge to work around the IE bug from issue #1193, where text - // input stops going to the textare whever this fires. + // input stops going to the textarea whenever this fires. if (ie_lt8 && cm.state.focused) cm.display.input.focus(); var clear = function() { cm.operation(function() { one.clear(); two && two.clear(); }); From 6fac052cc36082d1dadfa01f76755374b3c92a20 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Fri, 27 Dec 2013 16:29:18 +0100 Subject: [PATCH 0111/4131] [gfm mode] Fix exponential running time in regexp --- mode/gfm/gfm.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mode/gfm/gfm.js b/mode/gfm/gfm.js index 492cbc463a..10d5e05c06 100644 --- a/mode/gfm/gfm.js +++ b/mode/gfm/gfm.js @@ -75,7 +75,7 @@ CodeMirror.defineMode("gfm", function(config, modeConfig) { return "link"; } } - if (stream.match(/^((?:[a-z][\w-]+:(?:\/{1,3}|[a-z0-9%])|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}\/)(?:[^\s()<>]+|\([^\s()<>]*\))+(?:\([^\s()<>]*\)|[^\s`!()\[\]{};:'".,<>?«»“”‘’]))/i) && + if (stream.match(/^((?:[a-z][\w-]+:(?:\/{1,3}|[a-z0-9%])|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}\/)(?:[^\s()<>]|\([^\s()<>]*\))+(?:\([^\s()<>]*\)|[^\s`!()\[\]{};:'".,<>?«»“”‘’]))/i) && stream.string.slice(stream.start - 2, stream.start) != "](") { // URLs // Taken from http://daringfireball.net/2010/07/improved_regex_for_matching_urls From 4f90bd87f1c5a20d0a40719169a02841202bdf38 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Fri, 27 Dec 2013 16:33:16 +0100 Subject: [PATCH 0112/4131] Clear input field when disableInput flag is cleared Issue #2060 --- lib/codemirror.js | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/codemirror.js b/lib/codemirror.js index d66bfc4670..086f84151e 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -244,6 +244,7 @@ window.CodeMirror = (function() { var map = keyMap[cm.options.keyMap], style = map.style; cm.display.wrapper.className = cm.display.wrapper.className.replace(/\s*cm-keymap-\S+/g, "") + (style ? " cm-keymap-" + style : ""); + if (cm.state.disableInput && !map.disableInput) resetInput(cm, true); cm.state.disableInput = map.disableInput; } From f5b8e1000dcd3d2e080ee5fd845eb333eefc04a5 Mon Sep 17 00:00:00 2001 From: Travis Heppe Date: Fri, 20 Dec 2013 17:29:31 -0800 Subject: [PATCH 0113/4131] [test driver] Clean up test selection --- test/doc_test.js | 2 +- test/driver.js | 49 ++++++++++++++++++------------------------------ test/index.html | 40 +++++++++++++++++++++++---------------- test/vim_test.js | 2 +- 4 files changed, 44 insertions(+), 49 deletions(-) diff --git a/test/doc_test.js b/test/doc_test.js index 3e04e155b3..f0f40e76e0 100644 --- a/test/doc_test.js +++ b/test/doc_test.js @@ -57,7 +57,7 @@ run.apply(null, editors); successful = true; } finally { - if ((debug && !successful) || verbose) { + if (!successful || verbose) { place.style.visibility = "visible"; } else { for (var i = 0; i < editors.length; ++i) diff --git a/test/driver.js b/test/driver.js index 5befa77278..10088ab1ed 100644 --- a/test/driver.js +++ b/test/driver.js @@ -1,4 +1,4 @@ -var tests = [], debug = null, debugUsed = new Array(), allNames = []; +var tests = [], filters = [], allNames = []; function Failure(why) {this.message = why;} Failure.prototype.toString = function() { return this.message; }; @@ -32,7 +32,7 @@ function testCM(name, run, opts, expectedFail) { run(cm); successful = true; } finally { - if ((debug && !successful) || verbose) { + if (!successful || verbose) { place.style.visibility = "visible"; } else { place.removeChild(cm.getWrapperElement()); @@ -42,39 +42,23 @@ function testCM(name, run, opts, expectedFail) { } function runTests(callback) { - if (debug) { - if (indexOf(debug, "verbose") === 0) { - verbose = true; - debug.splice(0, 1); - } - if (debug.length < 1) { - debug = null; - } - } var totalTime = 0; function step(i) { if (i === tests.length){ running = false; return callback("done"); - } + } var test = tests[i], expFail = test.expectedFail, startTime = +new Date; - if (debug !== null) { - var debugIndex = indexOf(debug, test.name); - if (debugIndex !== -1) { - // Remove from array for reporting incorrect tests later - debug.splice(debugIndex, 1); - } else { - var wildcardName = test.name.split("_")[0] + "_*"; - debugIndex = indexOf(debug, wildcardName); - if (debugIndex !== -1) { - // Remove from array for reporting incorrect tests later - debug.splice(debugIndex, 1); - debugUsed.push(wildcardName); - } else { - debugIndex = indexOf(debugUsed, wildcardName); - if (debugIndex == -1) return step(i + 1); + if (filters.length) { + for (var j = 0; j < filters.length; j++) { + if (test.name.match(filters[j])) { + break; } } + if (j == filters.length) { + callback("skipped", test.name, message); + return step(i + 1); + } } var threw = false; try { @@ -127,13 +111,16 @@ function is(a, msg) { } function countTests() { - if (!debug) return tests.length; + if (!filters.length) return tests.length; var sum = 0; for (var i = 0; i < tests.length; ++i) { var name = tests[i].name; - if (indexOf(debug, name) != -1 || - indexOf(debug, name.split("_")[0] + "_*") != -1) - ++sum; + for (var j = 0; j < filters.length; j++) { + if (name.match(filters[j])) { + ++sum; + break; + } + } } return sum; } diff --git a/test/index.html b/test/index.html index ac12b2274c..0a10f3c945 100644 --- a/test/index.html +++ b/test/index.html @@ -109,10 +109,11 @@

    Test Suite

    progressTotal = document.getElementById("progress_total").childNodes[0]; var count = 0, failed = 0, + skipped = 0, bad = "", running = false, // Flag that states tests are running - quit = false, // Flag to quit tests ASAP - verbose = false; // Adds message for *every* test to output + quit = false, // Flag to quit tests ASAP + verbose = false; // Adds message for *every* test to output function runHarness(){ if (running) { @@ -121,19 +122,26 @@

    Test Suite

    setTimeout(function(){runHarness();}, 500); return; } + filters = []; + verbose = false; if (window.location.hash.substr(1)){ - debug = window.location.hash.substr(1).split(","); - } else { - debug = null; + var strings = window.location.hash.substr(1).split(","); + while (strings.length) { + var s = strings.shift(); + if (s === "verbose") { + verbose = true; + } else { + filters.push(new RegExp(decodeURIComponent(s, 'i'))); + } + } } quit = false; running = true; setStatus("Loading tests..."); count = 0; failed = 0; + skipped = 0; bad = ""; - verbose = false; - debugUsed = Array(); totalTests = countTests(); progressTotal.nodeValue = " of " + totalTests; progressRan.nodeValue = count; @@ -166,12 +174,16 @@

    Test Suite

    } function displayTest(type, name, customMessage) { var message = "???"; - if (type != "done") ++count; + if (type != "done" && type != "skipped") ++count; progress.style.width = (count * (progress.parentNode.clientWidth - 2) / totalTests) + "px"; progressRan.nodeValue = count; if (type == "ok") { message = "Test '" + name + "' succeeded"; if (!verbose) customMessage = false; + } else if (type == "skipped") { + message = "Test '" + name + "' skipped"; + ++skipped; + if (!verbose) customMessage = false; } else if (type == "expected") { message = "Test '" + name + "' failed as expected"; if (!verbose) customMessage = false; @@ -189,15 +201,11 @@

    Test Suite

    } else { type += " ok"; message = "All passed"; + if (skipped) { + message += " (" + skipped + " skipped)"; + } } - if (debug && debug.length) { - var bogusTests = totalTests - count; - message += " — " + bogusTests + " nonexistent test" + - (bogusTests > 1 ? "s" : "") + " requested by location.hash: " + - "`" + debug.join("`, `") + "`"; - } else { - progressTotal.nodeValue = ''; - } + progressTotal.nodeValue = ''; customMessage = true; // Hack to avoid adding to output } if (verbose && !customMessage) customMessage = message; diff --git a/test/vim_test.js b/test/vim_test.js index 1a5cc3ee3f..28d492178c 100644 --- a/test/vim_test.js +++ b/test/vim_test.js @@ -195,7 +195,7 @@ function testVim(name, run, opts, expectedFail) { run(cm, vim, helpers); successful = true; } finally { - if ((debug && !successful) || verbose) { + if (!successful || verbose) { place.style.visibility = "visible"; } else { place.removeChild(cm.getWrapperElement()); From 9228a29bc0d6fb5ada1a2186dd9a27dffecb6af6 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Fri, 27 Dec 2013 17:27:31 +0100 Subject: [PATCH 0114/4131] Clean up f5b8e1000dcd3d2e080ee5fd845eb333eefc04a5 --- test/driver.js | 5 +++++ test/index.html | 7 +++---- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/test/driver.js b/test/driver.js index 10088ab1ed..13952dcc65 100644 --- a/test/driver.js +++ b/test/driver.js @@ -124,3 +124,8 @@ function countTests() { } return sum; } + +function parseTestFilter(s) { + if (/_\*$/.test(s)) return new RegExp("^" + s.slice(0, s.length - 2), "i"); + else return new RegExp(s, "i"); +} diff --git a/test/index.html b/test/index.html index 0a10f3c945..8177038e30 100644 --- a/test/index.html +++ b/test/index.html @@ -128,11 +128,10 @@

    Test Suite

    var strings = window.location.hash.substr(1).split(","); while (strings.length) { var s = strings.shift(); - if (s === "verbose") { + if (s === "verbose") verbose = true; - } else { - filters.push(new RegExp(decodeURIComponent(s, 'i'))); - } + else + filters.push(parseTestFilter(decodeURIComponent(s)));; } } quit = false; From b226604b1395621c69a1326a8ef12cdf02694778 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Fri, 27 Dec 2013 21:18:16 +0100 Subject: [PATCH 0115/4131] [sql mode] Another indentation tweak Issue #2065 --- mode/sql/sql.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/mode/sql/sql.js b/mode/sql/sql.js index 946e7b38fa..903fa6740a 100644 --- a/mode/sql/sql.js +++ b/mode/sql/sql.js @@ -178,8 +178,9 @@ CodeMirror.defineMode("sql", function(config, parserConfig) { indent: function(state, textAfter) { var cx = state.context; if (!cx) return 0; - if (cx.align) return cx.col + (textAfter.charAt(0) == cx.type ? 0 : 1); - else return cx.indent + config.indentUnit; + var closing = textAfter.charAt(0) == cx.type; + if (cx.align) return cx.col + (closing ? 0 : 1); + else return cx.indent + (closing ? 0 : config.indentUnit); }, blockCommentStart: "/*", From 4b5195fbe5776435e64e3ef4e925f34859ac1d93 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Fri, 27 Dec 2013 21:21:48 +0100 Subject: [PATCH 0116/4131] [hardwrap demo] Remove debugging code Closes #2080 --- demo/hardwrap.html | 2 -- 1 file changed, 2 deletions(-) diff --git a/demo/hardwrap.html b/demo/hardwrap.html index 6cfd9c87c2..d3f085ad43 100644 --- a/demo/hardwrap.html +++ b/demo/hardwrap.html @@ -61,9 +61,7 @@

    Hard-wrapping Demo

    } }); var wait, options = {column: 60}; -var done = false; editor.on("change", function(cm, change) { -if (done) return; done = true; clearTimeout(wait); wait = setTimeout(function() { cm.wrapParagraphsInRange(change.from, CodeMirror.changeEnd(change), options); From 14877c387fe0cedff2189c421b1a39de882e3bbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Haso=C5=88?= Date: Fri, 27 Dec 2013 12:50:33 +0100 Subject: [PATCH 0117/4131] [gherkin mode] Improve, add localizations --- mode/gherkin/gherkin.js | 95 +++++++++++++++++++---------------------- 1 file changed, 45 insertions(+), 50 deletions(-) diff --git a/mode/gherkin/gherkin.js b/mode/gherkin/gherkin.js index dadb58362b..784afc50ce 100644 --- a/mode/gherkin/gherkin.js +++ b/mode/gherkin/gherkin.js @@ -18,31 +18,40 @@ CodeMirror.defineMode("gherkin", function () { startState: function () { return { lineNumber: 0, - tableHeaderLine: null, + tableHeaderLine: false, allowFeature: true, allowBackground: false, allowScenario: false, allowSteps: false, allowPlaceholders: false, - inMultilineArgument: false, + allowMultilineArgument: false, inMultilineString: false, - inMultilineTable: false + inMultilineTable: false, + inKeywordLine: false }; }, token: function (stream, state) { if (stream.sol()) { state.lineNumber++; + state.inKeywordLine = false; + if (state.inMultilineTable) { + state.tableHeaderLine = false; + if (!stream.match(/\s*\|/, false)) { + state.allowMultilineArgument = false; + state.inMultilineTable = false; + } + } } + stream.eatSpace(); - // INSIDE OF MULTILINE ARGUMENTS - if (state.inMultilineArgument) { + if (state.allowMultilineArgument) { // STRING if (state.inMultilineString) { if (stream.match('"""')) { state.inMultilineString = false; - state.inMultilineArgument = false; + state.allowMultilineArgument = false; } else { stream.match(/.*/); } @@ -51,19 +60,11 @@ CodeMirror.defineMode("gherkin", function () { // TABLE if (state.inMultilineTable) { - // New table, assume first row is headers - if (state.tableHeaderLine === null) { - state.tableHeaderLine = state.lineNumber; - } - if (stream.match(/\|\s*/)) { - if (stream.eol()) { - state.inMultilineTable = false; - } return "bracket"; } else { stream.match(/[^\|]*/); - return state.tableHeaderLine === state.lineNumber ? "property" : "string"; + return state.tableHeaderLine ? "property" : "string"; } } @@ -75,15 +76,10 @@ CodeMirror.defineMode("gherkin", function () { } else if (stream.match("|")) { // Table state.inMultilineTable = true; + state.tableHeaderLine = true; return "bracket"; - } else { - // Or abort - state.inMultilineArgument = false; - state.tableHeaderLine = null; } - - return null; } // LINE COMMENT @@ -91,76 +87,75 @@ CodeMirror.defineMode("gherkin", function () { return "comment"; // TAG - } else if (stream.match(/@\S+/)) { - return "def"; + } else if (!state.inKeywordLine && stream.match(/@\S+/)) { + return "tag"; // FEATURE - } else if (state.allowFeature && stream.match(/Feature:/)) { + } else if (!state.inKeywordLine && state.allowFeature && stream.match(/(機能|功能|フィーチャ|기능|โครงหลัก|ความสามารถ|ความต้องการทางธุรกิจ|ಹೆಚ್ಚಳ|గుణము|ਮੁਹਾਂਦਰਾ|ਨਕਸ਼ ਨੁਹਾਰ|ਖਾਸੀਅਤ|रूप लेख|وِیژگی|خاصية|תכונה|Функціонал|Функция|Функционалност|Функционал|Үзенчәлеклелек|Свойство|Особина|Мөмкинлек|Могућност|Λειτουργία|Δυνατότητα|Właściwość|Vlastnosť|Trajto|Tính năng|Savybė|Pretty much|Požiadavka|Požadavek|Potrzeba biznesowa|Özellik|Osobina|Ominaisuus|Omadus|OH HAI|Mogućnost|Mogucnost|Jellemző|Hwæt|Hwaet|Funzionalità|Funktionalitéit|Funktionalität|Funkcja|Funkcionalnost|Funkcionalitāte|Funkcia|Fungsi|Functionaliteit|Funcționalitate|Funcţionalitate|Functionalitate|Funcionalitat|Funcionalidade|Fonctionnalité|Fitur|Fīča|Feature|Eiginleiki|Egenskap|Egenskab|Característica|Caracteristica|Business Need|Aspekt|Arwedd|Ahoy matey!|Ability):/)) { state.allowScenario = true; state.allowBackground = true; state.allowPlaceholders = false; state.allowSteps = false; + state.allowMultilineArgument = false; + state.inKeywordLine = true; return "keyword"; // BACKGROUND - } else if (state.allowBackground && stream.match("Background:")) { + } else if (!state.inKeywordLine && state.allowBackground && stream.match(/(背景|배경|แนวคิด|ಹಿನ್ನೆಲೆ|నేపథ్యం|ਪਿਛੋਕੜ|पृष्ठभूमि|زمینه|الخلفية|רקע|Тарих|Предыстория|Предистория|Позадина|Передумова|Основа|Контекст|Кереш|Υπόβαθρο|Założenia|Yo\-ho\-ho|Tausta|Taust|Situācija|Rerefons|Pozadina|Pozadie|Pozadí|Osnova|Latar Belakang|Kontext|Konteksts|Kontekstas|Kontekst|Háttér|Hannergrond|Grundlage|Geçmiş|Fundo|Fono|First off|Dis is what went down|Dasar|Contexto|Contexte|Context|Contesto|Cenário de Fundo|Cenario de Fundo|Cefndir|Bối cảnh|Bakgrunnur|Bakgrunn|Bakgrund|Baggrund|Background|B4|Antecedents|Antecedentes|Ær|Aer|Achtergrond):/)) { state.allowPlaceholders = false; state.allowSteps = true; state.allowBackground = false; + state.allowMultilineArgument = false; + state.inKeywordLine = true; return "keyword"; // SCENARIO OUTLINE - } else if (state.allowScenario && stream.match("Scenario Outline:")) { + } else if (!state.inKeywordLine && state.allowScenario && stream.match(/(場景大綱|场景大纲|劇本大綱|剧本大纲|テンプレ|シナリオテンプレート|シナリオテンプレ|シナリオアウトライン|시나리오 개요|สรุปเหตุการณ์|โครงสร้างของเหตุการณ์|ವಿವರಣೆ|కథనం|ਪਟਕਥਾ ਰੂਪ ਰੇਖਾ|ਪਟਕਥਾ ਢਾਂਚਾ|परिदृश्य रूपरेखा|سيناريو مخطط|الگوی سناریو|תבנית תרחיש|Сценарийның төзелеше|Сценарий структураси|Структура сценарію|Структура сценария|Структура сценарија|Скица|Рамка на сценарий|Концепт|Περιγραφή Σεναρίου|Wharrimean is|Template Situai|Template Senario|Template Keadaan|Tapausaihio|Szenariogrundriss|Szablon scenariusza|Swa hwær swa|Swa hwaer swa|Struktura scenarija|Structură scenariu|Structura scenariu|Skica|Skenario konsep|Shiver me timbers|Senaryo taslağı|Schema dello scenario|Scenariomall|Scenariomal|Scenario Template|Scenario Outline|Scenario Amlinellol|Scenārijs pēc parauga|Scenarijaus šablonas|Reckon it's like|Raamstsenaarium|Plang vum Szenario|Plan du Scénario|Plan du scénario|Osnova scénáře|Osnova Scenára|Náčrt Scenáru|Náčrt Scénáře|Náčrt Scenára|MISHUN SRSLY|Menggariskan Senario|Lýsing Dæma|Lýsing Atburðarásar|Konturo de la scenaro|Koncept|Khung tình huống|Khung kịch bản|Forgatókönyv vázlat|Esquema do Cenário|Esquema do Cenario|Esquema del escenario|Esquema de l'escenari|Esbozo do escenario|Delineação do Cenário|Delineacao do Cenario|All y'all|Abstrakt Scenario|Abstract Scenario):/)) { state.allowPlaceholders = true; state.allowSteps = true; + state.allowMultilineArgument = false; + state.inKeywordLine = true; return "keyword"; // EXAMPLES - } else if (state.allowScenario && stream.match("Examples:")) { + } else if (state.allowScenario && stream.match(/(例子|例|サンプル|예|ชุดของเหตุการณ์|ชุดของตัวอย่าง|ಉದಾಹರಣೆಗಳು|ఉదాహరణలు|ਉਦਾਹਰਨਾਂ|उदाहरण|نمونه ها|امثلة|דוגמאות|Үрнәкләр|Сценарији|Примеры|Примери|Приклади|Мисоллар|Мисаллар|Σενάρια|Παραδείγματα|You'll wanna|Voorbeelden|Variantai|Tapaukset|Se þe|Se the|Se ðe|Scenarios|Scenariji|Scenarijai|Przykłady|Primjeri|Primeri|Příklady|Príklady|Piemēri|Példák|Pavyzdžiai|Paraugs|Örnekler|Juhtumid|Exemplos|Exemples|Exemple|Exempel|EXAMPLZ|Examples|Esempi|Enghreifftiau|Ekzemploj|Eksempler|Ejemplos|Dữ liệu|Dead men tell no tales|Dæmi|Contoh|Cenários|Cenarios|Beispiller|Beispiele|Atburðarásir):/)) { state.allowPlaceholders = false; state.allowSteps = true; state.allowBackground = false; - state.inMultilineArgument = true; + state.allowMultilineArgument = true; return "keyword"; // SCENARIO - } else if (state.allowScenario && stream.match(/Scenario:/)) { + } else if (!state.inKeywordLine && state.allowScenario && stream.match(/(場景|场景|劇本|剧本|シナリオ|시나리오|เหตุการณ์|ಕಥಾಸಾರಾಂಶ|సన్నివేశం|ਪਟਕਥਾ|परिदृश्य|سيناريو|سناریو|תרחיש|Сценарій|Сценарио|Сценарий|Пример|Σενάριο|Tình huống|The thing of it is|Tapaus|Szenario|Swa|Stsenaarium|Skenario|Situai|Senaryo|Senario|Scenaro|Scenariusz|Scenariu|Scénario|Scenario|Scenarijus|Scenārijs|Scenarij|Scenarie|Scénář|Scenár|Primer|MISHUN|Kịch bản|Keadaan|Heave to|Forgatókönyv|Escenario|Escenari|Cenário|Cenario|Awww, look mate|Atburðarás):/)) { state.allowPlaceholders = false; state.allowSteps = true; state.allowBackground = false; + state.allowMultilineArgument = false; + state.inKeywordLine = true; return "keyword"; // STEPS - } else if (state.allowSteps && stream.match(/(Given|When|Then|And|But)/)) { + } else if (!state.inKeywordLine && state.allowSteps && stream.match(/(那麼|那么|而且|當|当|并且|同時|同时|前提|假设|假設|假定|假如|但是|但し|並且|もし|ならば|ただし|しかし|かつ|하지만|조건|먼저|만일|만약|단|그리고|그러면|และ |เมื่อ |แต่ |ดังนั้น |กำหนดให้ |ಸ್ಥಿತಿಯನ್ನು |ಮತ್ತು |ನೀಡಿದ |ನಂತರ |ಆದರೆ |మరియు |చెప్పబడినది |కాని |ఈ పరిస్థితిలో |అప్పుడు |ਪਰ |ਤਦ |ਜੇਕਰ |ਜਿਵੇਂ ਕਿ |ਜਦੋਂ |ਅਤੇ |यदि |परन्तु |पर |तब |तदा |तथा |जब |चूंकि |किन्तु |कदा |और |अगर |و |هنگامی |متى |لكن |عندما |ثم |بفرض |با فرض |اما |اذاً |آنگاه |כאשר |וגם |בהינתן |אזי |אז |אבל |Якщо |Һәм |Унда |Тоді |Тогда |То |Также |Та |Пусть |Припустимо, що |Припустимо |Онда |Но |Нехай |Нәтиҗәдә |Лекин |Ләкин |Коли |Когда |Когато |Када |Кад |К тому же |І |И |Задато |Задати |Задате |Если |Допустим |Дано |Дадено |Вә |Ва |Бирок |Әмма |Әйтик |Әгәр |Аммо |Али |Але |Агар |А також |А |Τότε |Όταν |Και |Δεδομένου |Αλλά |Þurh |Þegar |Þa þe |Þá |Þa |Zatati |Zakładając |Zadato |Zadate |Zadano |Zadani |Zadan |Za předpokladu |Za predpokladu |Youse know when youse got |Youse know like when |Yna |Yeah nah |Y'know |Y |Wun |Wtedy |When y'all |When |Wenn |WEN |wann |Ve |Và |Und |Un |ugeholl |Too right |Thurh |Thì |Then y'all |Then |Tha the |Tha |Tetapi |Tapi |Tak |Tada |Tad |Stel |Soit |Siis |Și |Şi |Si |Sed |Se |Så |Quando |Quand |Quan |Pryd |Potom |Pokud |Pokiaľ |Però |Pero |Pak |Oraz |Onda |Ond |Oletetaan |Og |Och |O zaman |Niin |Nhưng |När |Når |Mutta |Men |Mas |Maka |Majd |Mając |Mais |Maar |mä |Ma |Lorsque |Lorsqu'|Logo |Let go and haul |Kun |Kuid |Kui |Kiedy |Khi |Ketika |Kemudian |Keď |Když |Kaj |Kai |Kada |Kad |Jeżeli |Jeśli |Ja |It's just unbelievable |Ir |I CAN HAZ |I |Ha |Givun |Givet |Given y'all |Given |Gitt |Gegeven |Gegeben seien |Gegeben sei |Gdy |Gangway! |Fakat |Étant donnés |Etant donnés |Étant données |Etant données |Étant donnée |Etant donnée |Étant donné |Etant donné |Et |És |Entonces |Entón |Então |Entao |En |Eğer ki |Ef |Eeldades |E |Ðurh |Duota |Dun |Donitaĵo |Donat |Donada |Do |Diyelim ki |Diberi |Dengan |Den youse gotta |DEN |De |Dato |Dați fiind |Daţi fiind |Dati fiind |Dati |Date fiind |Date |Data |Dat fiind |Dar |Dann |dann |Dan |Dados |Dado |Dadas |Dada |Ða ðe |Ða |Cuando |Cho |Cando |Când |Cand |Cal |But y'all |But at the end of the day I reckon |BUT |But |Buh |Blimey! |Biết |Bet |Bagi |Aye |awer |Avast! |Atunci |Atesa |Atès |Apabila |Anrhegedig a |Angenommen |And y'all |And |AN |An |an |Amikor |Amennyiben |Ama |Als |Alors |Allora |Ali |Aleshores |Ale |Akkor |Ak |Adott |Ac |Aber |A zároveň |A tiež |A taktiež |A také |A |a |7 |\* )/)) { + state.inStep = true; + state.allowPlaceholders = true; + state.allowMultilineArgument = true; + state.inKeywordLine = true; return "keyword"; // INLINE STRING - } else if (!state.inMultilineArgument && stream.match(/"/)) { - stream.match(/.*?"/); + } else if (stream.match(/"[^"]*"?/)) { return "string"; - // MULTILINE ARGUMENTS - } else if (state.allowSteps && stream.eat(":")) { - if (stream.match(/\s*$/)) { - state.inMultilineArgument = true; - return "keyword"; - } else { - return null; - } - - } else if (state.allowSteps && stream.match("<")) { - if (stream.match(/.*?>/)) { - return "property"; - } else { - return null; - } + // PLACEHOLDER + } else if (state.allowPlaceholders && stream.match(/<[^>]*>?/)) { + return "attribute"; // Fall through } else { - stream.eatWhile(/[^":<]/); + stream.next(); + stream.eatWhile(/[^@"<#]/); + return null; } - - return null; } }; }); From db1753be3764e6c6ce46b74a4cdd0f2d9c90a1ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Haso=C5=88?= Date: Fri, 27 Dec 2013 22:53:32 +0100 Subject: [PATCH 0118/4131] [gherkin] Renamed tokens for placeholder and table header --- mode/gherkin/gherkin.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mode/gherkin/gherkin.js b/mode/gherkin/gherkin.js index 784afc50ce..685b373df7 100644 --- a/mode/gherkin/gherkin.js +++ b/mode/gherkin/gherkin.js @@ -64,7 +64,7 @@ CodeMirror.defineMode("gherkin", function () { return "bracket"; } else { stream.match(/[^\|]*/); - return state.tableHeaderLine ? "property" : "string"; + return state.tableHeaderLine ? "header" : "string"; } } @@ -148,7 +148,7 @@ CodeMirror.defineMode("gherkin", function () { // PLACEHOLDER } else if (state.allowPlaceholders && stream.match(/<[^>]*>?/)) { - return "attribute"; + return "variable"; // Fall through } else { From 74910aebed399821cb030421762fa145bbeb52ae Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Sun, 29 Dec 2013 15:37:01 +0100 Subject: [PATCH 0119/4131] [markdown mode] Fix HTML embedding, add innerMode method Closes #2083 Issue #2084 --- mode/markdown/markdown.js | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/mode/markdown/markdown.js b/mode/markdown/markdown.js index 6370462772..b4322d1ca2 100644 --- a/mode/markdown/markdown.js +++ b/mode/markdown/markdown.js @@ -197,14 +197,11 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) { function htmlBlock(stream, state) { var style = htmlMode.token(stream, state.htmlState); - if (htmlFound && style === 'tag' && state.htmlState.type !== 'openTag' && !state.htmlState.context) { + if ((htmlFound && !state.htmlState.tagName && !state.htmlState.context) || + (state.md_inside && stream.current().indexOf(">") > -1)) { state.f = inlineNormal; state.block = blockNormal; - } - if (state.md_inside && stream.current().indexOf(">")!=-1) { - state.f = inlineNormal; - state.block = blockNormal; - state.htmlState.context = undefined; + state.htmlState = null; } return style; } @@ -421,13 +418,14 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) { } if (ch === '<' && stream.match(/^\w/, false)) { - if (stream.string.indexOf(">")!=-1) { + if (stream.string.indexOf(">") != -1) { var atts = stream.string.substring(1,stream.string.indexOf(">")); if (/markdown\s*=\s*('|"){0,1}1('|"){0,1}/.test(atts)) { state.md_inside = true; } } stream.backUp(1); + state.htmlState = CodeMirror.startState(htmlMode); return switchBlock(stream, state, htmlBlock); } @@ -601,7 +599,7 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) { return savedInlineRE[endChar]; } - return { + var mode = { startState: function() { return { f: blockNormal, @@ -610,7 +608,7 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) { thisLineHasContent: false, block: blockNormal, - htmlState: CodeMirror.startState(htmlMode), + htmlState: null, indentation: 0, inline: inlineNormal, @@ -641,7 +639,7 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) { thisLineHasContent: s.thisLineHasContent, block: s.block, - htmlState: CodeMirror.copyState(htmlMode, s.htmlState), + htmlState: s.htmlState && CodeMirror.copyState(htmlMode, s.htmlState), indentation: s.indentation, localMode: s.localMode, @@ -671,10 +669,7 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) { state.formatting = false; if (stream.sol()) { - var forceBlankLine = false; - if (stream.match(/^\s*$/, true) || state.header) { - forceBlankLine = true; - } + var forceBlankLine = stream.match(/^\s*$/, true) || state.header; // Reset state.header state.header = 0; @@ -712,11 +707,17 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) { return state.f(stream, state); }, + innerMode: function(state) { + if (state.block == htmlBlock) return {state: state.htmlState, mode: htmlMode}; + if (state.block == local) return {state: state.localState, mode: state.localMode}; + return {state: state, mode: mode}; + }, + blankLine: blankLine, getType: getType }; - + return mode; }, "xml"); CodeMirror.defineMIME("text/x-markdown", "markdown"); From a2d531380d71279f95a8293bbb36f2ae40ee55c1 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Sun, 29 Dec 2013 16:46:48 +0100 Subject: [PATCH 0120/4131] [indentwrap demo] Fix inherited text-indent messing up tabs Issue #2085 --- demo/indentwrap.html | 1 + 1 file changed, 1 insertion(+) diff --git a/demo/indentwrap.html b/demo/indentwrap.html index 6c1fc596e1..efdba5d59e 100644 --- a/demo/indentwrap.html +++ b/demo/indentwrap.html @@ -9,6 +9,7 @@
    +
    addModeClass: boolean
    +
    When enabled (off by default), an extra CSS class will be + added to each token, indicating the + (inner) mode that produced it, prefixed + with "cm-m-". For example, tokens from the XML mode + will get the cm-m-xml class.
    +
    maxHighlightLength: number
    When highlighting long lines, in order to stay responsive, the editor will give up and simply style the rest of the line as diff --git a/lib/codemirror.js b/lib/codemirror.js index bc5da913ce..2d2fb0b45c 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -195,6 +195,10 @@ window.CodeMirror = (function() { function loadMode(cm) { cm.doc.mode = CodeMirror.getMode(cm.options, cm.doc.modeOption); + resetModeState(cm); + } + + function resetModeState(cm) { cm.doc.iter(function(line) { if (line.stateAfter) line.stateAfter = null; if (line.styles) line.styles = null; @@ -3312,7 +3316,7 @@ window.CodeMirror = (function() { option("indentWithTabs", false); option("smartIndent", true); option("tabSize", 4, function(cm) { - loadMode(cm); + resetModeState(cm); clearCaches(cm); regChange(cm); }, true); @@ -3372,12 +3376,13 @@ window.CodeMirror = (function() { option("cursorHeight", 1); option("workTime", 100); option("workDelay", 100); - option("flattenSpans", true); + option("flattenSpans", true, resetModeState, true); + option("addModeClass", false, resetModeState, true); option("pollInterval", 100); option("undoDepth", 40, function(cm, val){cm.doc.history.undoDepth = val;}); option("historyEventDelay", 500); option("viewportMargin", 10, function(cm){cm.refresh();}, true); - option("maxHighlightLength", 10000, function(cm){loadMode(cm); cm.refresh();}, true); + option("maxHighlightLength", 10000, resetModeState, true); option("crudeMeasuringFrom", 10000); option("moveInputWithCursor", true, function(cm, val) { if (!val) cm.display.inputDiv.style.top = cm.display.inputDiv.style.left = 0; @@ -4381,6 +4386,10 @@ window.CodeMirror = (function() { } else { style = mode.token(stream, state); } + if (cm.options.addModeClass) { + var mName = CodeMirror.innerMode(mode, state).mode.name; + if (mName) style = "m-" + (style ? mName + " " + style : mName); + } if (!flattenSpans || curStyle != style) { if (curStart < stream.start) f(stream.start, curStyle); curStart = stream.start; curStyle = style; @@ -4452,7 +4461,7 @@ window.CodeMirror = (function() { } } - var styleToClassCache = {}; + var styleToClassCache = {}, styleToClassCacheWithMode = {}; function interpretTokenStyle(style, builder) { if (!style) return null; for (;;) { @@ -4465,8 +4474,9 @@ window.CodeMirror = (function() { else if (!(new RegExp("(?:^|\s)" + lineClass[2] + "(?:$|\s)")).test(builder[prop])) builder[prop] += " " + lineClass[2]; } - return styleToClassCache[style] || - (styleToClassCache[style] = "cm-" + style.replace(/ +/g, " cm-")); + var cache = builder.cm.options.addModeClass ? styleToClassCacheWithMode : styleToClassCache; + return cache[style] || + (cache[style] = "cm-" + style.replace(/ +/g, " cm-")); } function buildLineContent(cm, realLine, measure, copyWidgets) { From 337e435328b920af0f74c9c707df9b4326b210b1 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 6 Jan 2014 13:23:36 +0100 Subject: [PATCH 0138/4131] Add a disableInput option, change vim keymap to use it. --- keymap/vim.js | 5 ++++- lib/codemirror.js | 5 ++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/keymap/vim.js b/keymap/vim.js index c83f6f08ae..78b83e5116 100644 --- a/keymap/vim.js +++ b/keymap/vim.js @@ -331,12 +331,14 @@ CodeMirror.defineOption('vimMode', false, function(cm, val) { if (val) { cm.setOption('keyMap', 'vim'); + cm.setOption('disableInput', true); CodeMirror.signal(cm, "vim-mode-change", {mode: "normal"}); cm.on('beforeSelectionChange', beforeSelectionChange); maybeInitVimState(cm); CodeMirror.on(cm.getInputField(), 'paste', getOnPasteFn(cm)); } else if (cm.state.vim) { cm.setOption('keyMap', 'default'); + cm.setOption('disableInput', false); cm.off('beforeSelectionChange', beforeSelectionChange); CodeMirror.off(cm.getInputField(), 'paste', getOnPasteFn(cm)); cm.state.vim = null; @@ -1749,6 +1751,7 @@ cm.setCursor(motions.moveToFirstNonWhiteSpaceCharacter(cm)); } cm.setOption('keyMap', 'vim-insert'); + cm.setOption('disableInput', false); if (actionArgs && actionArgs.replace) { // Handle Replace-mode as a special case of insert mode. cm.toggleOverwrite(true); @@ -3509,7 +3512,6 @@ var cmToVimKeymap = { 'nofallthrough': true, - 'disableInput': true, 'style': 'fat-cursor' }; function bindKeys(keys, modifier) { @@ -3556,6 +3558,7 @@ cm.setCursor(cm.getCursor().line, cm.getCursor().ch-1, true); vim.insertMode = false; cm.setOption('keyMap', 'vim'); + cm.setOption('disableInput', true); cm.toggleOverwrite(false); // exit replace mode if we were in it. CodeMirror.signal(cm, "vim-mode-change", {mode: "normal"}); } diff --git a/lib/codemirror.js b/lib/codemirror.js index 2d2fb0b45c..0bff9eccf4 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -248,8 +248,6 @@ window.CodeMirror = (function() { var map = keyMap[cm.options.keyMap], style = map.style; cm.display.wrapper.className = cm.display.wrapper.className.replace(/\s*cm-keymap-\S+/g, "") + (style ? " cm-keymap-" + style : ""); - if (cm.state.disableInput && !map.disableInput) resetInput(cm, true); - cm.state.disableInput = map.disableInput; } function themeChanged(cm) { @@ -1487,7 +1485,7 @@ window.CodeMirror = (function() { // supported or compatible enough yet to rely on.) function readInput(cm) { var input = cm.display.input, prevInput = cm.display.prevInput, doc = cm.doc, sel = doc.sel; - if (!cm.state.focused || hasSelection(input) || isReadOnly(cm) || cm.state.disableInput) return false; + if (!cm.state.focused || hasSelection(input) || isReadOnly(cm) || cm.options.disableInput) return false; if (cm.state.pasteIncoming && cm.state.fakedLastChar) { input.value = input.value.substring(0, input.value.length - 1); cm.state.fakedLastChar = false; @@ -3369,6 +3367,7 @@ window.CodeMirror = (function() { if (!val) resetInput(cm, true); } }); + option("disableInput", false, function(cm, val) {if (!val) resetInput(cm, true);}, true); option("dragDrop", true); option("cursorBlinkRate", 530); From 58113e8a8945cfd8f6310240c5b86564d59b0e07 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 6 Jan 2014 13:28:58 +0100 Subject: [PATCH 0139/4131] Adjust addons to respect disableInput --- addon/comment/continuecomment.js | 2 +- addon/edit/closebrackets.js | 8 +++++--- addon/edit/closetag.js | 5 +++-- addon/edit/continuelist.js | 2 ++ lib/codemirror.js | 4 +++- 5 files changed, 14 insertions(+), 7 deletions(-) diff --git a/addon/comment/continuecomment.js b/addon/comment/continuecomment.js index 94e5a3760f..a3370a6072 100644 --- a/addon/comment/continuecomment.js +++ b/addon/comment/continuecomment.js @@ -5,7 +5,7 @@ function continueComment(cm) { var pos = cm.getCursor(), token = cm.getTokenAt(pos); - if (token.type != "comment") return CodeMirror.Pass; + if (token.type != "comment" || cm.getOption("disableInput")) return CodeMirror.Pass; var mode = CodeMirror.innerMode(cm.getMode(), token.state).mode; var insert; diff --git a/addon/edit/closebrackets.js b/addon/edit/closebrackets.js index 88718b7729..0575222be6 100644 --- a/addon/edit/closebrackets.js +++ b/addon/edit/closebrackets.js @@ -28,7 +28,7 @@ var map = { name : "autoCloseBrackets", Backspace: function(cm) { - if (cm.somethingSelected()) return CodeMirror.Pass; + if (cm.somethingSelected() || cm.getOption("disableInput")) return CodeMirror.Pass; var cur = cm.getCursor(), around = charsAround(cm, cur); if (around && pairs.indexOf(around) % 2 == 0) cm.replaceRange("", CodeMirror.Pos(cur.line, cur.ch - 1), CodeMirror.Pos(cur.line, cur.ch + 1)); @@ -49,7 +49,8 @@ else cm.execCommand("goCharRight"); } map["'" + left + "'"] = function(cm) { - if (left == "'" && cm.getTokenAt(cm.getCursor()).type == "comment") + if (left == "'" && cm.getTokenAt(cm.getCursor()).type == "comment" || + cm.getOption("disableInput")) return CodeMirror.Pass; if (cm.somethingSelected()) return surround(cm); if (left == right && maybeOverwrite(cm) != CodeMirror.Pass) return; @@ -70,7 +71,8 @@ function buildExplodeHandler(pairs) { return function(cm) { var cur = cm.getCursor(), around = charsAround(cm, cur); - if (!around || pairs.indexOf(around) % 2 != 0) return CodeMirror.Pass; + if (!around || pairs.indexOf(around) % 2 != 0 || cm.getOption("disableInput")) + return CodeMirror.Pass; cm.operation(function() { var newPos = CodeMirror.Pos(cur.line + 1, 0); cm.replaceSelection("\n\n", {anchor: newPos, head: newPos}, "+input"); diff --git a/addon/edit/closetag.js b/addon/edit/closetag.js index 60e204bcf2..cad776a783 100644 --- a/addon/edit/closetag.js +++ b/addon/edit/closetag.js @@ -43,7 +43,7 @@ function autoCloseGT(cm) { var pos = cm.getCursor(), tok = cm.getTokenAt(pos); var inner = CodeMirror.innerMode(cm.getMode(), tok.state), state = inner.state; - if (inner.mode.name != "xml" || !state.tagName) return CodeMirror.Pass; + if (inner.mode.name != "xml" || !state.tagName || cm.getOption("disableInput")) return CodeMirror.Pass; var opt = cm.getOption("autoCloseTags"), html = inner.mode.configuration == "html"; var dontCloseTags = (typeof opt == "object" && opt.dontCloseTags) || (html && htmlDontClose); @@ -76,7 +76,8 @@ var pos = cm.getCursor(), tok = cm.getTokenAt(pos); var inner = CodeMirror.innerMode(cm.getMode(), tok.state), state = inner.state; if (tok.type == "string" || tok.string.charAt(0) != "<" || - tok.start != pos.ch - 1 || inner.mode.name != "xml") + tok.start != pos.ch - 1 || inner.mode.name != "xml" || + cm.getOption("disableInput")) return CodeMirror.Pass; var tagName = state.context && state.context.tagName; diff --git a/addon/edit/continuelist.js b/addon/edit/continuelist.js index 826d17d716..190b41dcbe 100644 --- a/addon/edit/continuelist.js +++ b/addon/edit/continuelist.js @@ -5,6 +5,8 @@ unorderedBullets = '*+-'; CodeMirror.commands.newlineAndIndentContinueMarkdownList = function(cm) { + if (cm.getOption("disableInput")) return CodeMirror.Pass; + var pos = cm.getCursor(), inList = cm.getStateAfter(pos.line).list !== false, match; diff --git a/lib/codemirror.js b/lib/codemirror.js index 0bff9eccf4..c728d97c45 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -3582,7 +3582,9 @@ window.CodeMirror = (function() { indentAuto: function(cm) {cm.indentSelection("smart");}, indentMore: function(cm) {cm.indentSelection("add");}, indentLess: function(cm) {cm.indentSelection("subtract");}, - insertTab: function(cm) {cm.replaceSelection("\t", "end", "+input");}, + insertTab: function(cm) { + cm.replaceSelection("\t", "end", "+input"); + }, defaultTab: function(cm) { if (cm.somethingSelected()) cm.indentSelection("add"); else cm.replaceSelection("\t", "end", "+input"); From ad2fccb4fd38344441593201f7491e15ef2d2255 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 6 Jan 2014 13:48:23 +0100 Subject: [PATCH 0140/4131] [anyword-hint addon] Optimize Issue #2109 --- addon/hint/anyword-hint.js | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/addon/hint/anyword-hint.js b/addon/hint/anyword-hint.js index 36ff618e09..67eaa0f617 100644 --- a/addon/hint/anyword-hint.js +++ b/addon/hint/anyword-hint.js @@ -13,22 +13,20 @@ var curWord = start != end && curLine.slice(start, end); var list = [], seen = {}; - function scan(dir) { + var re = new RegExp(word.source, "g"); + for (var dir = -1; dir <= 1; dir += 2) { var line = cur.line, end = Math.min(Math.max(line + dir * range, editor.firstLine()), editor.lastLine()) + dir; for (; line != end; line += dir) { var text = editor.getLine(line), m; - var re = new RegExp(word.source, "g"); while (m = re.exec(text)) { if (line == cur.line && m[0] === curWord) continue; - if ((!curWord || m[0].indexOf(curWord) == 0) && !seen.hasOwnProperty(m[0])) { + if ((!curWord || m[0].indexOf(curWord) == 0) && !Object.prototype.hasOwnProperty.call(seen, m[0])) { seen[m[0]] = true; list.push(m[0]); } } } } - scan(-1); - scan(1); return {list: list, from: CodeMirror.Pos(cur.line, start), to: CodeMirror.Pos(cur.line, end)}; }); })(); From 22dd7235e352b2e1caf3fe9b1656989d5983b968 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 6 Jan 2014 14:28:52 +0100 Subject: [PATCH 0141/4131] Use lastIndexOf(a, 0) to check starts-with in hint addons Issue #2109 --- addon/hint/anyword-hint.js | 2 +- addon/hint/css-hint.js | 2 +- addon/hint/javascript-hint.js | 2 +- addon/hint/pig-hint.js | 2 +- addon/hint/python-hint.js | 2 +- addon/hint/xml-hint.js | 10 +++++----- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/addon/hint/anyword-hint.js b/addon/hint/anyword-hint.js index 67eaa0f617..a144768c81 100644 --- a/addon/hint/anyword-hint.js +++ b/addon/hint/anyword-hint.js @@ -20,7 +20,7 @@ var text = editor.getLine(line), m; while (m = re.exec(text)) { if (line == cur.line && m[0] === curWord) continue; - if ((!curWord || m[0].indexOf(curWord) == 0) && !Object.prototype.hasOwnProperty.call(seen, m[0])) { + if ((!curWord || m[0].lastIndexOf(curWord, 0) == 0) && !Object.prototype.hasOwnProperty.call(seen, m[0])) { seen[m[0]] = true; list.push(m[0]); } diff --git a/addon/hint/css-hint.js b/addon/hint/css-hint.js index 43bdf5de02..6789c458ba 100644 --- a/addon/hint/css-hint.js +++ b/addon/hint/css-hint.js @@ -20,7 +20,7 @@ var result = []; function add(keywords) { for (var name in keywords) - if (!word || name.indexOf(word) == 0) + if (!word || name.lastIndexOf(word, 0) == 0) result.push(name); } diff --git a/addon/hint/javascript-hint.js b/addon/hint/javascript-hint.js index c66b0a7a5b..c347c206ec 100644 --- a/addon/hint/javascript-hint.js +++ b/addon/hint/javascript-hint.js @@ -87,7 +87,7 @@ function getCompletions(token, context, keywords, options) { var found = [], start = token.string; function maybeAdd(str) { - if (str.indexOf(start) == 0 && !arrayContains(found, str)) found.push(str); + if (str.lastIndexOf(start, 0) == 0 && !arrayContains(found, str)) found.push(str); } function gatherCompletions(obj) { if (typeof obj == "string") forEach(stringProps, maybeAdd); diff --git a/addon/hint/pig-hint.js b/addon/hint/pig-hint.js index 7ef336cecf..6c0c523774 100644 --- a/addon/hint/pig-hint.js +++ b/addon/hint/pig-hint.js @@ -84,7 +84,7 @@ function getCompletions(token, context) { var found = [], start = token.string; function maybeAdd(str) { - if (str.indexOf(start) == 0 && !arrayContains(found, str)) found.push(str); + if (str.lastIndexOf(start, 0) == 0 && !arrayContains(found, str)) found.push(str); } function gatherCompletions(obj) { diff --git a/addon/hint/python-hint.js b/addon/hint/python-hint.js index ace1941bd6..248284e8c5 100644 --- a/addon/hint/python-hint.js +++ b/addon/hint/python-hint.js @@ -62,7 +62,7 @@ function getCompletions(token, context) { var found = [], start = token.string; function maybeAdd(str) { - if (str.indexOf(start) == 0 && !arrayContains(found, str)) found.push(str); + if (str.lastIndexOf(start, 0) == 0 && !arrayContains(found, str)) found.push(str); } function gatherCompletions(_obj) { diff --git a/addon/hint/xml-hint.js b/addon/hint/xml-hint.js index a721743449..69f2b771fe 100644 --- a/addon/hint/xml-hint.js +++ b/addon/hint/xml-hint.js @@ -20,13 +20,13 @@ var cx = inner.state.context, curTag = cx && tags[cx.tagName]; var childList = cx ? curTag && curTag.children : tags["!top"]; if (childList) { - for (var i = 0; i < childList.length; ++i) if (!prefix || childList[i].indexOf(prefix) == 0) + for (var i = 0; i < childList.length; ++i) if (!prefix || childList[i].lastIndexOf(prefix, 0) == 0) result.push("<" + childList[i]); } else { - for (var name in tags) if (tags.hasOwnProperty(name) && name != "!top" && (!prefix || name.indexOf(prefix) == 0)) + for (var name in tags) if (tags.hasOwnProperty(name) && name != "!top" && (!prefix || name.lastIndexOf(prefix, 0) == 0)) result.push("<" + name); } - if (cx && (!prefix || ("/" + cx.tagName).indexOf(prefix) == 0)) + if (cx && (!prefix || ("/" + cx.tagName).lastIndexOf(prefix, 0) == 0)) result.push(""); } else { // Attribute completion @@ -46,14 +46,14 @@ } replaceToken = true; } - for (var i = 0; i < atValues.length; ++i) if (!prefix || atValues[i].indexOf(prefix) == 0) + for (var i = 0; i < atValues.length; ++i) if (!prefix || atValues[i].lastIndexOf(prefix, 0) == 0) result.push(quote + atValues[i] + quote); } else { // An attribute name if (token.type == "attribute") { prefix = token.string; replaceToken = true; } - for (var attr in attrs) if (attrs.hasOwnProperty(attr) && (!prefix || attr.indexOf(prefix) == 0)) + for (var attr in attrs) if (attrs.hasOwnProperty(attr) && (!prefix || attr.lastIndexOf(prefix, 0) == 0)) result.push(attr); } } From d73e38fdbf43508267b257a595cd962e8572415a Mon Sep 17 00:00:00 2001 From: AtomicPages LLC Date: Sun, 5 Jan 2014 14:41:57 -0800 Subject: [PATCH 0142/4131] [pastel-on-dark theme] Add --- demo/theme.html | 2 ++ theme/pastel-on-dark.css | 49 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+) create mode 100644 theme/pastel-on-dark.css diff --git a/demo/theme.html b/demo/theme.html index a6e2b2da09..e36e62eaa3 100644 --- a/demo/theme.html +++ b/demo/theme.html @@ -23,6 +23,7 @@ + @@ -88,6 +89,7 @@

    Theme Demo

    + diff --git a/theme/pastel-on-dark.css b/theme/pastel-on-dark.css new file mode 100644 index 0000000000..df95699a01 --- /dev/null +++ b/theme/pastel-on-dark.css @@ -0,0 +1,49 @@ +/** + * Pastel On Dark theme ported from ACE editor + * @license MIT + * @copyright AtomicPages LLC 2014 + * @author Dennis Thompson, AtomicPages LLC + * @version 1.1 + * @source https://github.com/atomicpages/codemirror-pastel-on-dark-theme + */ + +.cm-s-pastel-on-dark.CodeMirror { + background: #2c2827; + color: #8F938F; + line-height: 1.5; + font-family: consolas, Courier, monospace; + font-size: 14px; +} +.cm-s-pastel-on-dark div.CodeMirror-selected { background: rgba(221,240,255,0.2) !important; } +.cm-s-pastel-on-dark .CodeMirror-gutters { + background: #34302f; + border-right: 0px; + padding: 0 3px; +} +.cm-s-pastel-on-dark .CodeMirror-linenumber { color: #8F938F; } +.cm-s-pastel-on-dark .CodeMirror-cursor { border-left: 1px solid #A7A7A7 !important; } +.cm-s-pastel-on-dark span.cm-comment { color: #A6C6FF; } +.cm-s-pastel-on-dark span.cm-atom { color: #DE8E30; } +.cm-s-pastel-on-dark span.cm-number { color: #CCCCCC; } +.cm-s-pastel-on-dark span.cm-property { color: #8F938F; } +.cm-s-pastel-on-dark span.cm-attribute { color: #a6e22e; } +.cm-s-pastel-on-dark span.cm-keyword { color: #AEB2F8; } +.cm-s-pastel-on-dark span.cm-string { color: #66A968; } +.cm-s-pastel-on-dark span.cm-variable { color: #AEB2F8; } +.cm-s-pastel-on-dark span.cm-variable-2 { color: #BEBF55; } +.cm-s-pastel-on-dark span.cm-variable-3 { color: #DE8E30; } +.cm-s-pastel-on-dark span.cm-def { color: #757aD8; } +.cm-s-pastel-on-dark span.cm-bracket { color: #f8f8f2; } +.cm-s-pastel-on-dark span.cm-tag { color: #C1C144; } +.cm-s-pastel-on-dark span.cm-link { color: #ae81ff; } +.cm-s-pastel-on-dark span.cm-qualifier,.cm-s-pastel-on-dark span.cm-builtin { color: #C1C144; } +.cm-s-pastel-on-dark span.cm-error { + background: #757aD8; + color: #f8f8f0; +} +.cm-s-pastel-on-dark .CodeMirror-activeline-background { background: rgba(255, 255, 255, 0.031) !important; } +.cm-s-pastel-on-dark .CodeMirror-matchingbracket { + border: 1px solid rgba(255,255,255,0.25); + color: #8F938F !important; + margin: -1px -1px 0 -1px; +} From a8440788cdbfc79f998a84b8320d047936dda60c Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 6 Jan 2014 20:11:54 +0100 Subject: [PATCH 0143/4131] [multiplex addon] Support end: null to mean switch back at end of line Issue #2111 --- addon/mode/multiplex.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/addon/mode/multiplex.js b/addon/mode/multiplex.js index 32cc579c3a..614ab1add3 100644 --- a/addon/mode/multiplex.js +++ b/addon/mode/multiplex.js @@ -47,7 +47,11 @@ CodeMirror.multiplexingMode = function(outer /*, others */) { return outerToken; } else { var curInner = state.innerActive, oldContent = stream.string; - var found = indexOf(oldContent, curInner.close, stream.pos); + if (!curInner.close && stream.sol()) { + state.innerActive = state.inner = null; + return this.token(stream, state); + } + var found = curInner.close ? indexOf(oldContent, curInner.close, stream.pos) : -1; if (found == stream.pos) { stream.match(curInner.close); state.innerActive = state.inner = null; @@ -56,8 +60,6 @@ CodeMirror.multiplexingMode = function(outer /*, others */) { if (found > -1) stream.string = oldContent.slice(0, found); var innerToken = curInner.mode.token(stream, state.inner); if (found > -1) stream.string = oldContent; - var cur = stream.current(), found = cur.indexOf(curInner.close); - if (found > -1) stream.backUp(cur.length - found); if (curInner.innerStyle) { if (innerToken) innerToken = innerToken + ' ' + curInner.innerStyle; From c1b518e91e93c5812093810dfb5d049971d1a926 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Tue, 7 Jan 2014 12:50:19 +0100 Subject: [PATCH 0144/4131] [hardwrap addon] Make methods return true when they made a change --- addon/wrap/hardwrap.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/addon/wrap/hardwrap.js b/addon/wrap/hardwrap.js index 1faa3d84a6..3023ca5b8e 100644 --- a/addon/wrap/hardwrap.js +++ b/addon/wrap/hardwrap.js @@ -36,7 +36,7 @@ var killTrailing = options.killTrailingSpace !== false; var changes = [], curLine = "", curNo = from.line; var lines = cm.getRange(from, to, false); - if (!lines.length) return; + if (!lines.length) return false; var leadingSpace = lines[0].match(/^[ \t]*/)[0]; for (var i = 0; i < lines.length; ++i) { @@ -79,17 +79,18 @@ cm.replaceRange(change.text, change.from, change.to); } }); + return changes.length > 0; } CodeMirror.defineExtension("wrapParagraph", function(pos, options) { options = options || {}; if (!pos) pos = this.getCursor(); var para = findParagraph(this, pos, options); - wrapRange(this, Pos(para.from, 0), Pos(para.to - 1), options); + return wrapRange(this, Pos(para.from, 0), Pos(para.to - 1), options); }); CodeMirror.defineExtension("wrapRange", function(from, to, options) { - wrapRange(this, from, to, options || {}); + return wrapRange(this, from, to, options || {}); }); CodeMirror.defineExtension("wrapParagraphsInRange", function(from, to, options) { @@ -100,9 +101,11 @@ paras.push(para); line = para.to; } + var madeChange = false; if (paras.length) cm.operation(function() { for (var i = paras.length - 1; i >= 0; --i) - wrapRange(cm, Pos(paras[i].from, 0), Pos(paras[i].to - 1), options); + madeChange = madeChange || wrapRange(cm, Pos(paras[i].from, 0), Pos(paras[i].to - 1), options); }); + return madeChange; }); })(); From bc5bc136b16b2df4ea3285f2bb6fd3f5a711afd4 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 6 Jan 2014 20:54:32 +0100 Subject: [PATCH 0145/4131] [xml mode] Fix bug with value-less attributes Closes #2112 --- mode/xml/xml.js | 1 - 1 file changed, 1 deletion(-) diff --git a/mode/xml/xml.js b/mode/xml/xml.js index bf1fd14a4e..c75200ec7b 100644 --- a/mode/xml/xml.js +++ b/mode/xml/xml.js @@ -254,7 +254,6 @@ CodeMirror.defineMode("xml", function(config, parserConfig) { function attrEqState(type, stream, state) { if (type == "equals") return attrValueState; if (!Kludges.allowMissing) setStyle = "error"; - else if (type == "word") { setStyle = "attribute"; return attrState; } return attrState(type, stream, state); } function attrValueState(type, stream, state) { From 232d819c4b17bdd6ca372fac4d32b1d101c5d0bd Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Wed, 8 Jan 2014 09:50:19 +0100 Subject: [PATCH 0146/4131] [mbo theme] Fix searching style --- theme/mbo.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/theme/mbo.css b/theme/mbo.css index 93fe3ee24c..bb52e6d17f 100644 --- a/theme/mbo.css +++ b/theme/mbo.css @@ -30,7 +30,7 @@ .cm-s-mbo .CodeMirror-matchingtag {background: #4e4e4e;} -div.CodeMirror span.CodeMirror-searching { +.cm-s-mbo span.cm-searching { background-color: none; background: none; box-shadow: 0 0 0 1px #ffffec; From 83df2a9ef5a4f68eefd0e1e01f5c7417c32196d7 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Wed, 8 Jan 2014 11:40:10 +0100 Subject: [PATCH 0147/4131] Apply some IE workarounds to IE11 as well. Despite the 'I am not IE!' user-agent string, it seems to have inherited a lot of the old bugs. Closes #2118 --- index.html | 2 +- lib/codemirror.js | 35 ++++++++++++++++++----------------- 2 files changed, 19 insertions(+), 18 deletions(-) diff --git a/index.html b/index.html index f9a93897fb..914bb7867d 100644 --- a/index.html +++ b/index.html @@ -133,7 +133,7 @@

    Features

  • Programmable gutters
  • Making ranges of text styled, read-only, or atomic
  • Bi-directional text support -
  • Many other methods and addons... +
  • Many other methods and addons... diff --git a/lib/codemirror.js b/lib/codemirror.js index c728d97c45..728b7faef4 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -10,10 +10,11 @@ window.CodeMirror = (function() { // IE11 currently doesn't count as 'ie', since it has almost none of // the same bugs as earlier versions. Use ie_gt10 to handle // incompatibilities in that version. - var ie = /MSIE \d/.test(navigator.userAgent); - var ie_lt8 = ie && (document.documentMode == null || document.documentMode < 8); - var ie_lt9 = ie && (document.documentMode == null || document.documentMode < 9); + var old_ie = /MSIE \d/.test(navigator.userAgent); + var ie_lt8 = old_ie && (document.documentMode == null || document.documentMode < 8); + var ie_lt9 = old_ie && (document.documentMode == null || document.documentMode < 9); var ie_gt10 = /Trident\/([7-9]|\d{2,})\./.test(navigator.userAgent); + var ie = old_ie || ie_gt10; var webkit = /WebKit\//.test(navigator.userAgent); var qtwebkit = webkit && /Qt\/\d+\.\d+/.test(navigator.userAgent); var chrome = /Chrome\//.test(navigator.userAgent); @@ -35,7 +36,7 @@ window.CodeMirror = (function() { if (opera_version && opera_version >= 15) { opera = false; webkit = true; } // Some browsers use the wrong event properties to signal cmd/ctrl on OS X var flipCtrlCmd = mac && (qtwebkit || opera && (opera_version == null || opera_version < 12.11)); - var captureMiddleClick = gecko || (ie && !ie_lt9); + var captureMiddleClick = gecko || (old_ie && !ie_lt9); // Optimize some code when these features are not used var sawReadOnlySpans = false, sawCollapsedSpans = false; @@ -75,7 +76,7 @@ window.CodeMirror = (function() { // Override magic textarea content restore that IE sometimes does // on our hidden textarea on reload - if (ie) setTimeout(bind(resetInput, this, true), 20); + if (old_ie) setTimeout(bind(resetInput, this, true), 20); registerEventHandlers(this); // IE throws unspecified error in certain cases, when @@ -1057,7 +1058,7 @@ window.CodeMirror = (function() { // doesn't work when wrapping is on, but in that case the // situation is slightly better, since IE does cache line-wrapping // information and only recomputes per-line. - if (ie && !ie_lt8 && !cm.options.lineWrapping && pre.childNodes.length > 100) { + if (old_ie && !ie_lt8 && !cm.options.lineWrapping && pre.childNodes.length > 100) { var fragment = document.createDocumentFragment(); var chunk = 10, n = pre.childNodes.length; for (var i = 0, chunks = Math.ceil(n / chunk); i < chunks; ++i) { @@ -1563,7 +1564,7 @@ window.CodeMirror = (function() { function registerEventHandlers(cm) { var d = cm.display; on(d.scroller, "mousedown", operation(cm, onMouseDown)); - if (ie) + if (old_ie) on(d.scroller, "dblclick", operation(cm, function(e) { if (signalDOMEvent(cm, e)) return; var pos = posFromMouse(cm, e); @@ -1682,8 +1683,8 @@ window.CodeMirror = (function() { // Needed to handle Tab key in KHTML if (khtml) on(d.sizer, "mouseup", function() { - if (document.activeElement == d.input) d.input.blur(); - focusInput(cm); + if (document.activeElement == d.input) d.input.blur(); + focusInput(cm); }); } @@ -1841,7 +1842,7 @@ window.CodeMirror = (function() { } var move = operation(cm, function(e) { - if (!ie && !e_button(e)) done(e); + if (!old_ie && !e_button(e)) done(e); else extend(e); }); var up = operation(cm, done); @@ -1986,7 +1987,7 @@ window.CodeMirror = (function() { // know one. These don't have to be accurate -- the result of them // being wrong would just be a slight flicker on the first wheel // scroll (if it is large enough). - if (ie) wheelPixelsPerUnit = -.53; + if (old_ie) wheelPixelsPerUnit = -.53; else if (gecko) wheelPixelsPerUnit = 15; else if (chrome) wheelPixelsPerUnit = -.7; else if (safari) wheelPixelsPerUnit = -1/3; @@ -2140,7 +2141,7 @@ window.CodeMirror = (function() { var cm = this; if (!cm.state.focused) onFocus(cm); if (signalDOMEvent(cm, e) || cm.options.onKeyEvent && cm.options.onKeyEvent(cm, addStop(e))) return; - if (ie && e.keyCode == 27) e.returnValue = false; + if (old_ie && e.keyCode == 27) e.returnValue = false; var code = e.keyCode; // IE does strange things with escape. cm.doc.sel.shift = code == 16 || e.shiftKey; @@ -2231,7 +2232,7 @@ window.CodeMirror = (function() { // Try to detect the user choosing select-all if (display.input.selectionStart != null) { - if (!ie || ie_lt9) prepareSelectAllHack(); + if (!old_ie || ie_lt9) prepareSelectAllHack(); clearTimeout(detectingSelectAll); var i = 0, poll = function(){ if (display.prevInput == "\u200b" && display.input.selectionStart == 0) @@ -2243,7 +2244,7 @@ window.CodeMirror = (function() { } } - if (ie && !ie_lt9) prepareSelectAllHack(); + if (old_ie && !ie_lt9) prepareSelectAllHack(); if (captureMiddleClick) { e_stop(e); var mouseup = function() { @@ -4494,7 +4495,7 @@ window.CodeMirror = (function() { builder.measure = line == realLine && measure; builder.pos = 0; builder.addToken = builder.measure ? buildTokenMeasure : buildToken; - if ((ie || webkit) && cm.getOption("lineWrapping")) + if ((old_ie || webkit) && cm.getOption("lineWrapping")) builder.addToken = buildTokenSplitSpaces(builder.addToken); var next = insertLineContent(line, builder, getLineStyles(cm, line)); if (measure && line == realLine && !builder.measuredSomething) { @@ -4513,7 +4514,7 @@ window.CodeMirror = (function() { // Work around problem with the reported dimensions of single-char // direction spans on IE (issue #1129). See also the comment in // cursorCoords. - if (measure && (ie || ie_gt10) && (order = getOrder(line))) { + if (measure && ie && (order = getOrder(line))) { var l = order.length - 1; if (order[l].from == order[l].to) --l; var last = order[l], prev = order[l - 1]; @@ -4595,7 +4596,7 @@ window.CodeMirror = (function() { // In IE single-space nodes wrap differently than spaces // embedded in larger text nodes, except when set to // white-space: normal (issue #1268). - if (ie && wrapping && ch == " " && i && !/\s/.test(text.charAt(i - 1)) && + if (old_ie && wrapping && ch == " " && i && !/\s/.test(text.charAt(i - 1)) && i < text.length - 1 && !/\s/.test(text.charAt(i + 1))) span.style.whiteSpace = "normal"; builder.pos += ch.length; From d84acac4f92b14b46c16f157bdf8243ce314b2b5 Mon Sep 17 00:00:00 2001 From: zziuni Date: Thu, 19 Dec 2013 17:22:48 +0900 Subject: [PATCH 0148/4131] [sql hint] support multi-queries on the table alias Now, Sql-hint assume one query to search for table of alias. It support multi-queries for alias. --- addon/hint/sql-hint.js | 75 ++++++++++++++++++++++++++++++++---------- 1 file changed, 58 insertions(+), 17 deletions(-) diff --git a/addon/hint/sql-hint.js b/addon/hint/sql-hint.js index 95f6b50a15..d00781cff9 100644 --- a/addon/hint/sql-hint.js +++ b/addon/hint/sql-hint.js @@ -3,6 +3,10 @@ var tables; var keywords; + var CONS = { + QUERY_DIV: ";", + ALIAS_KEYWORD: "AS" + }; function getKeywords(editor) { var mode = editor.doc.modeOption; @@ -34,11 +38,10 @@ var string = token.string.substr(1); var prevCur = CodeMirror.Pos(cur.line, token.start); var table = editor.getTokenAt(prevCur).string; - var columns = tables[table]; - if(!columns) { + if( !tables.hasOwnProperty( table ) ){ table = findTableByAlias(table, editor); } - columns = tables[table]; + var columns = tables[table]; if(!columns) { return; } @@ -46,32 +49,72 @@ function(w) {return "." + w;}); } - function eachWord(line, f) { - var words = line.text.split(" "); - for(var i = 0; i < words.length; i++) { - f(words[i]); + function eachWord(lineText, f) { + if( !lineText ){return;} + var excepted = /[,;]/g; + var words = lineText.split( " " ); + for( var i = 0; i < words.length; i++ ){ + f( words[i]?words[i].replace( excepted, '' ) : '' ); } } - // Tries to find possible table name from alias. + function convertCurToNumber( cur ){ + // max characters of a line is 999,999. + return cur.line + cur.ch / Math.pow( 10, 6 ); + } + + function convertNumberToCur( num ){ + return CodeMirror.Pos(Math.floor( num ), +num.toString().split( '.' ).pop()); + } + function findTableByAlias(alias, editor) { + var doc = editor.doc; + var fullQuery = doc.getValue(); var aliasUpperCase = alias.toUpperCase(); var previousWord = ""; var table = ""; + var separator = []; + var validRange = { + start: CodeMirror.Pos( 0, 0 ), + end: CodeMirror.Pos( editor.lastLine(), editor.getLineHandle( editor.lastLine() ).length ) + }; - editor.eachLine(function(line) { - eachWord(line, function(word) { + //add separator + var indexOfSeparator = fullQuery.indexOf( CONS.QUERY_DIV ); + while( indexOfSeparator != -1 ){ + separator.push( doc.posFromIndex(indexOfSeparator)); + indexOfSeparator = fullQuery.indexOf( CONS.QUERY_DIV, indexOfSeparator+1); + } + separator.unshift( CodeMirror.Pos( 0, 0 ) ); + separator.push( CodeMirror.Pos( editor.lastLine(), editor.getLineHandle( editor.lastLine() ).text.length ) ); + + //find valieRange + var prevItem = 0; + var current = convertCurToNumber( editor.getCursor() ); + for( var i=0; i< separator.length; i++){ + var _v = convertCurToNumber( separator[i] ); + if( current > prevItem && current <= _v ){ + validRange = { start: convertNumberToCur( prevItem ), end: convertNumberToCur( _v ) }; + break; + } + prevItem = _v; + } + + var query = doc.getRange(validRange.start, validRange.end, false); + + for(var i=0; i < query.length; i++){ + var lineText = query[i]; + eachWord( lineText, function( word ){ var wordUpperCase = word.toUpperCase(); - if(wordUpperCase === aliasUpperCase) { - if(tables.hasOwnProperty(previousWord)) { + if( wordUpperCase === aliasUpperCase && tables.hasOwnProperty( previousWord ) ){ table = previousWord; - } } - if(wordUpperCase !== "AS") { + if( wordUpperCase !== CONS.ALIAS_KEYWORD ){ previousWord = word; } }); - }); + if( table ){ break; } + } return table; } @@ -80,9 +123,7 @@ keywords = keywords || getKeywords(editor); var cur = editor.getCursor(); var token = editor.getTokenAt(cur); - var result = []; - var search = token.string.trim(); addMatches(result, search, keywords, From eacf20f8bf113c546cf06ec9d1dea40bb3818dd3 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 9 Jan 2014 23:36:36 +0100 Subject: [PATCH 0149/4131] Fix measuring of extending characters, include all extending code points Issue #2125 Issue #2115 --- lib/codemirror.js | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/lib/codemirror.js b/lib/codemirror.js index 728b7faef4..ad29f175a8 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -1294,7 +1294,7 @@ window.CodeMirror = (function() { if (bidi ? to == from || to == moveVisually(lineObj, from, 1) : to - from <= 1) { var ch = x < fromX || x - fromX <= toX - x ? from : to; var xDiff = x - (ch == from ? fromX : toX); - while (isExtendingChar.test(lineObj.text.charAt(ch))) ++ch; + while (isExtendingChar(lineObj.text.charAt(ch))) ++ch; var pos = PosWithInfo(lineNo, ch, ch == from ? fromOutside : toOutside, xDiff < 0 ? -1 : xDiff ? 1 : 0); return pos; @@ -4581,13 +4581,12 @@ window.CodeMirror = (function() { function buildTokenMeasure(builder, text, style, startStyle, endStyle) { var wrapping = builder.cm.options.lineWrapping; for (var i = 0; i < text.length; ++i) { - var ch = text.charAt(i), start = i == 0; - if (ch >= "\ud800" && ch < "\udbff" && i < text.length - 1) { - ch = text.slice(i, i + 2); - ++i; - } else if (i && wrapping && spanAffectsWrapping(text, i)) { + var start = i == 0, to = i + 1; + while (to < text.length && isExtendingChar(text.charAt(to))) ++to; + var ch = text.slice(i, to); + i = to - 1; + if (i && wrapping && spanAffectsWrapping(text, i)) builder.pre.appendChild(elt("wbr")); - } var old = builder.measure[builder.pos]; var span = builder.measure[builder.pos] = buildToken(builder, ch, style, @@ -5604,7 +5603,8 @@ window.CodeMirror = (function() { return true; } - var isExtendingChar = /[\u0300-\u036F\u0483-\u0487\u0488-\u0489\u0591-\u05BD\u05BF\u05C1-\u05C2\u05C4-\u05C5\u05C7\u0610-\u061A\u064B-\u065F\u0670\u06D6-\u06DC\u06DF-\u06E4\u06E7-\u06E8\u06EA-\u06ED\uA66F\u1DC0-\u1DFF\u20D0-\u20FF\uA670-\uA672\uA674-\uA67D\uA69F\udc00-\udfff\uFE20-\uFE2F]/; + var extendingChars = /[\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\ufb1e\ufe00-\ufe0f\ufe20-\ufe26\uff9e\uff9f]/; + function isExtendingChar(ch) { return ch.charCodeAt(0) >= 768 && extendingChars.test(ch); } // DOM UTILITIES @@ -5831,7 +5831,7 @@ window.CodeMirror = (function() { function moveInLine(line, pos, dir, byUnit) { if (!byUnit) return pos + dir; do pos += dir; - while (pos > 0 && isExtendingChar.test(line.text.charAt(pos))); + while (pos > 0 && isExtendingChar(line.text.charAt(pos))); return pos; } @@ -5866,7 +5866,7 @@ window.CodeMirror = (function() { function moveLogically(line, start, dir, byUnit) { var target = start + dir; - if (byUnit) while (target > 0 && isExtendingChar.test(line.text.charAt(target))) target += dir; + if (byUnit) while (target > 0 && isExtendingChar(line.text.charAt(target))) target += dir; return target < 0 || target > line.text.length ? null : target; } From 51f61299a8d5649e35be7812a2db586f3777c1e7 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Fri, 10 Jan 2014 09:22:06 +0100 Subject: [PATCH 0150/4131] Re-add continuing surrogate pair codes to extendingChars --- lib/codemirror.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/codemirror.js b/lib/codemirror.js index ad29f175a8..d2930ed270 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -5603,7 +5603,7 @@ window.CodeMirror = (function() { return true; } - var extendingChars = /[\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\ufb1e\ufe00-\ufe0f\ufe20-\ufe26\uff9e\uff9f]/; + var extendingChars = /[\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 isExtendingChar(ch) { return ch.charCodeAt(0) >= 768 && extendingChars.test(ch); } // DOM UTILITIES From 95eeb53e2a5bd91c36b0e086be64102bcb45f45d Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Fri, 10 Jan 2014 09:57:32 +0100 Subject: [PATCH 0151/4131] [javascript mode] Style operators Closes #2123 --- mode/javascript/javascript.js | 6 +++--- mode/javascript/test.js | 36 +++++++++++++++++------------------ 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/mode/javascript/javascript.js b/mode/javascript/javascript.js index c113fcb433..1985c6bbf5 100644 --- a/mode/javascript/javascript.js +++ b/mode/javascript/javascript.js @@ -83,7 +83,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { } else if (/[\[\]{}\(\),;\:\.]/.test(ch)) { return ret(ch); } else if (ch == "=" && stream.eat(">")) { - return ret("=>"); + return ret("=>", "operator"); } else if (ch == "0" && stream.eat(/x/i)) { stream.eatWhile(/[\da-f]/i); return ret("number", "number"); @@ -104,7 +104,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { return ret("regexp", "string-2"); } else { stream.eatWhile(isOperatorChar); - return ret("operator", null, stream.current()); + return ret("operator", "operator", stream.current()); } } else if (ch == "`") { state.tokenize = tokenQuasi; @@ -114,7 +114,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { return ret("error", "error"); } else if (isOperatorChar.test(ch)) { stream.eatWhile(isOperatorChar); - return ret("operator", null, stream.current()); + return ret("operator", "operator", stream.current()); } else { stream.eatWhile(/[\w\$_]/); var word = stream.current(), known = keywords.propertyIsEnumerable(word) && keywords[word]; diff --git a/mode/javascript/test.js b/mode/javascript/test.js index 8abd633542..cbb936d963 100644 --- a/mode/javascript/test.js +++ b/mode/javascript/test.js @@ -3,15 +3,15 @@ function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); } MT("locals", - "[keyword function] [variable foo]([def a], [def b]) { [keyword var] [def c] = [number 10]; [keyword return] [variable-2 a] + [variable-2 c] + [variable d]; }"); + "[keyword function] [variable foo]([def a], [def b]) { [keyword var] [def c] [operator =] [number 10]; [keyword return] [variable-2 a] [operator +] [variable-2 c] [operator +] [variable d]; }"); MT("comma-and-binop", - "[keyword function](){ [keyword var] [def x] = [number 1] + [number 2], [def y]; }"); + "[keyword function](){ [keyword var] [def x] [operator =] [number 1] [operator +] [number 2], [def y]; }"); MT("destructuring", "([keyword function]([def a], [[[def b], [def c] ]]) {", - " [keyword let] {[def d], [property foo]: [def c]=[number 10], [def x]} = [variable foo]([variable-2 a]);", - " [[[variable-2 c], [variable y] ]] = [variable-2 c];", + " [keyword let] {[def d], [property foo]: [def c][operator =][number 10], [def x]} [operator =] [variable foo]([variable-2 a]);", + " [[[variable-2 c], [variable y] ]] [operator =] [variable-2 c];", "})();"); MT("class", @@ -19,13 +19,13 @@ " [[ [string-2 /expr/] ]]: [number 24],", " [property constructor]([def x], [def y]) {", " [keyword super]([string 'something']);", - " [keyword this].[property x] = [variable-2 x];", + " [keyword this].[property x] [operator =] [variable-2 x];", " }", "}"); MT("module", "[keyword module] [string 'foo'] {", - " [keyword export] [keyword let] [def x] = [number 42];", + " [keyword export] [keyword let] [def x] [operator =] [number 42];", " [keyword export] [keyword *] [keyword from] [string 'somewhere'];", "}"); @@ -38,7 +38,7 @@ MT("const", "[keyword function] [variable f]() {", - " [keyword const] [[ [def a], [def b] ]] = [[ [number 1], [number 2] ]];", + " [keyword const] [[ [def a], [def b] ]] [operator =] [[ [number 1], [number 2] ]];", "}"); MT("for/of", @@ -46,14 +46,14 @@ MT("generator", "[keyword function*] [variable repeat]([def n]) {", - " [keyword for]([keyword var] [def i] = [number 0]; [variable-2 i] < [variable-2 n]; ++[variable-2 i])", + " [keyword for]([keyword var] [def i] [operator =] [number 0]; [variable-2 i] [operator <] [variable-2 n]; [operator ++][variable-2 i])", " [keyword yield] [variable-2 i];", "}"); MT("fatArrow", - "[variable array].[property filter]([def a] => [variable-2 a] + [number 1]);", + "[variable array].[property filter]([def a] [operator =>] [variable-2 a] [operator +] [number 1]);", "[variable a];", // No longer in scope - "[keyword let] [variable f] = ([[ [def a], [def b] ]], [def c]) => [variable-2 a] + [variable-2 c];", + "[keyword let] [variable f] [operator =] ([[ [def a], [def b] ]], [def c]) [operator =>] [variable-2 a] [operator +] [variable-2 c];", "[variable c];"); MT("spread", @@ -63,16 +63,16 @@ MT("comprehension", "[keyword function] [variable f]() {", - " [[([variable x] + [number 1]) [keyword for] ([keyword var] [def x] [keyword in] [variable y]) [keyword if] [variable pred]([variable-2 x]) ]];", - " ([variable u] [keyword for] ([keyword var] [def u] [keyword of] [variable generateValues]()) [keyword if] ([variable-2 u].[property color] === [string 'blue']));", + " [[([variable x] [operator +] [number 1]) [keyword for] ([keyword var] [def x] [keyword in] [variable y]) [keyword if] [variable pred]([variable-2 x]) ]];", + " ([variable u] [keyword for] ([keyword var] [def u] [keyword of] [variable generateValues]()) [keyword if] ([variable-2 u].[property color] [operator ===] [string 'blue']));", "}"); MT("quasi", - "[variable re][string-2 `fofdlakj${][variable x] + ([variable re][string-2 `foo`]) + [number 1][string-2 }fdsa`] + [number 2]"); + "[variable re][string-2 `fofdlakj${][variable x] [operator +] ([variable re][string-2 `foo`]) [operator +] [number 1][string-2 }fdsa`] [operator +] [number 2]"); MT("indent_statement", - "[keyword var] [variable x] = [number 10]", - "[variable x] += [variable y] +", + "[keyword var] [variable x] [operator =] [number 10]", + "[variable x] [operator +=] [variable y] [operator +]", " [atom Infinity]", "[keyword debugger];"); @@ -92,9 +92,9 @@ "}"); MT("indent_for", - "[keyword for] ([keyword var] [variable i] = [number 0];", - " [variable i] < [number 100];", - " [variable i]++)", + "[keyword for] ([keyword var] [variable i] [operator =] [number 0];", + " [variable i] [operator <] [number 100];", + " [variable i][operator ++])", " [variable doSomething]([variable i]);", "[keyword debugger];"); From 8a9142ac6dfd34e6cfc16dc6075dd4f1672ecc8a Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Tue, 14 Jan 2014 14:14:12 +0100 Subject: [PATCH 0152/4131] [markdown mode] Fix bug in innerMode Closes #2139 --- mode/markdown/markdown.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mode/markdown/markdown.js b/mode/markdown/markdown.js index 2a5e71fdd3..da2ba93fea 100644 --- a/mode/markdown/markdown.js +++ b/mode/markdown/markdown.js @@ -732,7 +732,7 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) { innerMode: function(state) { if (state.block == htmlBlock) return {state: state.htmlState, mode: htmlMode}; - if (state.block == local) return {state: state.localState, mode: state.localMode}; + if (state.localState) return {state: state.localState, mode: state.localMode}; return {state: state, mode: mode}; }, From b8beead7d21e761263fd89d8c2adfc3b3a5ba2a6 Mon Sep 17 00:00:00 2001 From: Yunchi Luo Date: Wed, 15 Jan 2014 23:28:40 -0500 Subject: [PATCH 0153/4131] [vim] Expose context (or mode) to the Vim API and add :nmap + :vmap. Also fixed a bug in context matching. --- keymap/vim.js | 55 ++++++++++++++++++++++++++++++------------------ test/vim_test.js | 20 ++++++++++++++++++ 2 files changed, 55 insertions(+), 20 deletions(-) diff --git a/keymap/vim.js b/keymap/vim.js index 78b83e5116..75b4e454d0 100644 --- a/keymap/vim.js +++ b/keymap/vim.js @@ -572,9 +572,9 @@ maybeInitVimState_: maybeInitVimState, InsertModeKey: InsertModeKey, - map: function(lhs, rhs) { + map: function(lhs, rhs, ctx) { // Add user defined key bindings. - exCommandDispatcher.map(lhs, rhs); + exCommandDispatcher.map(lhs, rhs, ctx); }, defineEx: function(name, prefix, func){ if (name.indexOf(prefix) !== 0) { @@ -856,11 +856,17 @@ } else { // Find the best match in the list of matchedCommands. var context = vim.visualMode ? 'visual' : 'normal'; - var bestMatch = matchedCommands[0]; // Default to first in the list. + var bestMatch; // Default to first in the list. for (var i = 0; i < matchedCommands.length; i++) { - if (matchedCommands[i].context == context) { - bestMatch = matchedCommands[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); @@ -2957,14 +2963,16 @@ // pair of commands that have a shared prefix, at least one of their // shortNames must not match the prefix of the other command. var defaultExCommandMap = [ - { name: 'map', type: 'builtIn' }, - { name: 'write', shortName: 'w', type: 'builtIn' }, - { name: 'undo', shortName: 'u', type: 'builtIn' }, - { name: 'redo', shortName: 'red', type: 'builtIn' }, - { name: 'sort', shortName: 'sor', type: 'builtIn'}, - { name: 'substitute', shortName: 's', type: 'builtIn'}, - { name: 'nohlsearch', shortName: 'noh', type: 'builtIn'}, - { name: 'delmarks', shortName: 'delm', type: 'builtin'} + { name: 'map' }, + { name: 'nmap', shortName: 'nm' }, + { name: 'vmap', shortName: 'vm' }, + { name: 'write', shortName: 'w' }, + { name: 'undo', shortName: 'u' }, + { name: 'redo', shortName: 'red' }, + { name: 'sort', shortName: 'sor' }, + { name: 'substitute', shortName: 's' }, + { name: 'nohlsearch', shortName: 'noh' }, + { name: 'delmarks', shortName: 'delm' } ]; Vim.ExCommandDispatcher = function() { this.buildCommandMap_(); @@ -3099,8 +3107,9 @@ this.commandMap_[key] = command; } }, - map: function(lhs, rhs) { + map: function(lhs, rhs, ctx) { if (lhs != ':' && lhs.charAt(0) == ':') { + if (ctx) { throw Error('Mode not supported for ex mappings'); } var commandName = lhs.substring(1); if (rhs != ':' && rhs.charAt(0) == ':') { // Ex to Ex mapping @@ -3120,17 +3129,21 @@ } else { if (rhs != ':' && rhs.charAt(0) == ':') { // Key to Ex mapping. - defaultKeymap.unshift({ + var mapping = { keys: parseKeyString(lhs), type: 'keyToEx', - exArgs: { input: rhs.substring(1) }}); + exArgs: { input: rhs.substring(1) }}; + if (ctx) { mapping.context = ctx; } + defaultKeymap.unshift(mapping); } else { // Key to key mapping - defaultKeymap.unshift({ + var mapping = { keys: parseKeyString(lhs), type: 'keyToKey', toKeys: parseKeyString(rhs) - }); + }; + if (ctx) { mapping.context = ctx; } + defaultKeymap.unshift(mapping); } } } @@ -3152,7 +3165,7 @@ } var exCommands = { - map: function(cm, params) { + map: function(cm, params, ctx) { var mapArgs = params.args; if (!mapArgs || mapArgs.length < 2) { if (cm) { @@ -3160,8 +3173,10 @@ } return; } - exCommandDispatcher.map(mapArgs[0], mapArgs[1], cm); + exCommandDispatcher.map(mapArgs[0], mapArgs[1], ctx); }, + nmap: function(cm, params) { this.map(cm, params, 'normal'); }, + vmap: function(cm, params) { this.map(cm, params, 'visual'); }, move: function(cm, params) { commandDispatcher.processCommand(cm, cm.state.vim, { type: 'motion', diff --git a/test/vim_test.js b/test/vim_test.js index 28d492178c..7184cb25ab 100644 --- a/test/vim_test.js +++ b/test/vim_test.js @@ -2401,6 +2401,26 @@ testVim('ex_map_key2ex', function(cm, vim, helpers) { eq(written, true); eq(actualCm, cm); }); +testVim('ex_map_key2key_visual_api', function(cm, vim, helpers) { + CodeMirror.Vim.map('b', ':w', 'visual'); + var tmp = CodeMirror.commands.save; + var written = false; + var actualCm; + CodeMirror.commands.save = function(cm) { + written = true; + actualCm = cm; + }; + // Mapping should not work in normal mode. + helpers.doKeys('b'); + eq(written, false); + // Mapping should work in visual mode. + helpers.doKeys('v', 'b'); + eq(written, true); + eq(actualCm, cm); + + CodeMirror.commands.save = tmp; +}); + // Testing registration of functions as ex-commands and mapping to -keys testVim('ex_api_test', function(cm, vim, helpers) { var res=false; From 54e25895f8b3d3b9253b5649080d5c5c18dfb8be Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 16 Jan 2014 12:48:09 +0100 Subject: [PATCH 0154/4131] [css mode] Properly parse @font-face declarations Closes #2131 --- mode/css/css.js | 31 ++++++++++++++++++++++++++++++- mode/css/test.js | 8 ++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/mode/css/css.js b/mode/css/css.js index 2af14db55d..369bb385ea 100644 --- a/mode/css/css.js +++ b/mode/css/css.js @@ -10,6 +10,7 @@ CodeMirror.defineMode("css", function(config, parserConfig) { propertyKeywords = parserConfig.propertyKeywords || {}, colorKeywords = parserConfig.colorKeywords || {}, valueKeywords = parserConfig.valueKeywords || {}, + fontProperties = parserConfig.fontProperties || {}, allowNested = parserConfig.allowNested; var type, override; @@ -137,6 +138,8 @@ CodeMirror.defineMode("css", function(config, parserConfig) { return popContext(state); } else if (type == "@media") { return pushContext(state, stream, "media"); + } else if (type == "@font-face") { + return "font_face_before"; } else if (type && type.charAt(0) == "@") { return pushContext(state, stream, "at"); } else if (type == "hash") { @@ -243,6 +246,24 @@ CodeMirror.defineMode("css", function(config, parserConfig) { return states.media(type, stream, state); }; + states.font_face_before = function(type, stream, state) { + if (type == "{") + return pushContext(state, stream, "font_face"); + return pass(type, stream, state); + }; + + states.font_face = function(type, stream, state) { + if (type == "}") return popContext(state); + if (type == "word") { + if (!fontProperties.hasOwnProperty(stream.current().toLowerCase())) + override = "error"; + else + override = "property"; + return "maybeprop"; + } + return "font_face"; + }; + states.at = function(type, stream, state) { if (type == ";") return popContext(state); if (type == "{" || type == "}") return popAndPass(type, stream, state); @@ -288,7 +309,7 @@ CodeMirror.defineMode("css", function(config, parserConfig) { var cx = state.context, ch = textAfter && textAfter.charAt(0); var indent = cx.indent; if (cx.prev && - (ch == "}" && (cx.type == "block" || cx.type == "top" || cx.type == "interpolation") || + (ch == "}" && (cx.type == "block" || cx.type == "top" || cx.type == "interpolation" || cx.type == "font_face") || ch == ")" && (cx.type == "parens" || cx.type == "params" || cx.type == "media_parens") || ch == "{" && (cx.type == "at" || cx.type == "media"))) { indent = cx.indent - indentUnit; @@ -533,6 +554,11 @@ CodeMirror.defineMode("css", function(config, parserConfig) { "xx-large", "xx-small" ], valueKeywords = keySet(valueKeywords_); + var fontProperties_ = [ + "font-family", "src", "unicode-range", "font-variant", "font-feature-settings", + "font-stretch", "font-weight", "font-style" + ], fontProperties = keySet(fontProperties_); + var allWords = mediaTypes_.concat(mediaFeatures_).concat(propertyKeywords_).concat(colorKeywords_).concat(valueKeywords_); CodeMirror.registerHelper("hintWords", "css", allWords); @@ -564,6 +590,7 @@ CodeMirror.defineMode("css", function(config, parserConfig) { propertyKeywords: propertyKeywords, colorKeywords: colorKeywords, valueKeywords: valueKeywords, + fontProperties: fontProperties, tokenHooks: { "<": function(stream, state) { if (!stream.match("!--")) return false; @@ -585,6 +612,7 @@ CodeMirror.defineMode("css", function(config, parserConfig) { propertyKeywords: propertyKeywords, colorKeywords: colorKeywords, valueKeywords: valueKeywords, + fontProperties: fontProperties, allowNested: true, tokenHooks: { "/": function(stream, state) { @@ -624,6 +652,7 @@ CodeMirror.defineMode("css", function(config, parserConfig) { propertyKeywords: propertyKeywords, colorKeywords: colorKeywords, valueKeywords: valueKeywords, + fontProperties: fontProperties, allowNested: true, tokenHooks: { "/": function(stream, state) { diff --git a/mode/css/test.js b/mode/css/test.js index 425c26ed91..b3f47767e6 100644 --- a/mode/css/test.js +++ b/mode/css/test.js @@ -108,4 +108,12 @@ "[string etc]", "[string ]) [keyword !important];", "}"); + + MT("font_face", + "[def @font-face] {", + " [property font-family]: [string 'myfont'];", + " [error nonsense]: [string 'abc'];", + " [property src]: [atom url]([string http://blah]),", + " [atom url]([string http://foo]);", + "}"); })(); From 086e985bd63a55561498678ab5d3233b457de8e8 Mon Sep 17 00:00:00 2001 From: Miraculix87 Date: Fri, 10 Jan 2014 20:52:52 +0100 Subject: [PATCH 0155/4131] Update midnight.css Added missing semicolon --- theme/midnight.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/theme/midnight.css b/theme/midnight.css index 66126322bd..468d87daf9 100644 --- a/theme/midnight.css +++ b/theme/midnight.css @@ -1,7 +1,7 @@ /* Based on the theme at http://bonsaiden.github.com/JavaScript-Garden */ /**/ -.cm-s-midnight span.CodeMirror-matchhighlight { background: #494949 } +.cm-s-midnight span.CodeMirror-matchhighlight { background: #494949; } .cm-s-midnight.CodeMirror-focused span.CodeMirror-matchhighlight { background: #314D67 !important; } /**/ From 31b884c12701c04c27093c0875c7450c497ab3bb Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 16 Jan 2014 12:57:57 +0100 Subject: [PATCH 0156/4131] [hardwrap addon] Return wrapped range, rather than a boolean --- addon/wrap/hardwrap.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addon/wrap/hardwrap.js b/addon/wrap/hardwrap.js index 3023ca5b8e..b56ebe2c39 100644 --- a/addon/wrap/hardwrap.js +++ b/addon/wrap/hardwrap.js @@ -36,7 +36,7 @@ var killTrailing = options.killTrailingSpace !== false; var changes = [], curLine = "", curNo = from.line; var lines = cm.getRange(from, to, false); - if (!lines.length) return false; + if (!lines.length) return null; var leadingSpace = lines[0].match(/^[ \t]*/)[0]; for (var i = 0; i < lines.length; ++i) { @@ -79,7 +79,7 @@ cm.replaceRange(change.text, change.from, change.to); } }); - return changes.length > 0; + return {from: from, to: cm.clipPos(Pos(curNo))}; } CodeMirror.defineExtension("wrapParagraph", function(pos, options) { From 1cb34abb860a4f534fb61d150b7f489183c10a5a Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 16 Jan 2014 13:03:25 +0100 Subject: [PATCH 0157/4131] [hardwrap addon] Return more precise range info --- addon/wrap/hardwrap.js | 6 +++--- demo/hardwrap.html | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/addon/wrap/hardwrap.js b/addon/wrap/hardwrap.js index b56ebe2c39..f6d99212a8 100644 --- a/addon/wrap/hardwrap.js +++ b/addon/wrap/hardwrap.js @@ -56,7 +56,7 @@ findBreakPoint(curLine, column, wrapOn, killTrailing); // If this isn't broken, or is broken at a different point, remove old break if (!firstBreak || firstBreak.from != oldLen || firstBreak.to != oldLen + spaceInserted) { - changes.push({text: spaceInserted ? " " : "", + changes.push({text: [spaceInserted ? " " : ""], from: Pos(curNo, oldLen), to: Pos(curNo + 1, spaceTrimmed.length)}); } else { @@ -66,7 +66,7 @@ } while (curLine.length > column) { var bp = findBreakPoint(curLine, column, wrapOn, killTrailing); - changes.push({text: "\n" + leadingSpace, + changes.push({text: ["", leadingSpace], from: Pos(curNo, bp.from), to: Pos(curNo, bp.to)}); curLine = leadingSpace + curLine.slice(bp.to); @@ -79,7 +79,7 @@ cm.replaceRange(change.text, change.from, change.to); } }); - return {from: from, to: cm.clipPos(Pos(curNo))}; + return changes.length ? {from: changes[0].from, to: CodeMirror.changeEnd(changes[changes.length - 1])} : null; } CodeMirror.defineExtension("wrapParagraph", function(pos, options) { diff --git a/demo/hardwrap.html b/demo/hardwrap.html index d3f085ad43..598bf957df 100644 --- a/demo/hardwrap.html +++ b/demo/hardwrap.html @@ -64,7 +64,7 @@

    Hard-wrapping Demo

    editor.on("change", function(cm, change) { clearTimeout(wait); wait = setTimeout(function() { - cm.wrapParagraphsInRange(change.from, CodeMirror.changeEnd(change), options); + console.log(cm.wrapParagraphsInRange(change.from, CodeMirror.changeEnd(change), options)); }, 200); }); From 32ae45d862d71efb9dfde934b29cf8fe99fe3d04 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 16 Jan 2014 13:05:55 +0100 Subject: [PATCH 0158/4131] [less mode] Don't treat @font-face as a variable Issue #2131 --- mode/css/css.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mode/css/css.js b/mode/css/css.js index 369bb385ea..c28d3e0a3b 100644 --- a/mode/css/css.js +++ b/mode/css/css.js @@ -667,7 +667,7 @@ CodeMirror.defineMode("css", function(config, parserConfig) { } }, "@": function(stream) { - if (stream.match(/^(media|import)\b/, false)) return false; + if (stream.match(/^(font-face|media|import)\b/, false)) return false; stream.eatWhile(/[\w\\\-]/); if (stream.match(/^\s*:/, false)) return ["variable-2", "variable-definition"]; From c3c4d4801ca61e1db351f97770a3a9a22f81d277 Mon Sep 17 00:00:00 2001 From: mats cronqvist Date: Sat, 11 Jan 2014 12:19:24 +0100 Subject: [PATCH 0159/4131] [erlang] - better indenter --- mode/erlang/erlang.js | 481 ++++++++++++++++++++++++++--------------- mode/erlang/index.html | 11 +- 2 files changed, 308 insertions(+), 184 deletions(-) diff --git a/mode/erlang/erlang.js b/mode/erlang/erlang.js index af8953c33b..bc3bdce860 100644 --- a/mode/erlang/erlang.js +++ b/mode/erlang/erlang.js @@ -1,45 +1,24 @@ -// block; "begin", "case", "fun", "if", "receive", "try": closed by "end" -// block internal; "after", "catch", "of" -// guard; "when", closed by "->" -// "->" opens a clause, closed by ";" or "." -// "<<" opens a binary, closed by ">>" -// "," appears in arglists, lists, tuples and terminates lines of code -// "." resets indentation to 0 -// obsolete; "cond", "let", "query" +/*jshint unused:true, eqnull:true, curly:true, bitwise:true */ +/*jshint undef:true, latedef:true, trailing:true */ +/*global CodeMirror:true */ + +// erlang mode. +// tokenizer -> token types -> CodeMirror styles +// tokenizer maintains a parse stack +// indenter uses the parse stack + +// TODO indenter: +// bit syntax +// old guard/bif/conversion clashes (e.g. "float/1") +// type/spec/opaque CodeMirror.defineMIME("text/x-erlang", "erlang"); CodeMirror.defineMode("erlang", function(cmCfg) { + "use strict"; - function rval(state,_stream,type) { - // distinguish between "." as terminator and record field operator - state.in_record = (type == "record"); - - // erlang -> CodeMirror tag - switch (type) { - case "atom": return "atom"; - case "attribute": return "attribute"; - case "boolean": return "special"; - case "builtin": return "builtin"; - case "comment": return "comment"; - case "fun": return "meta"; - case "function": return "tag"; - case "guard": return "property"; - case "keyword": return "keyword"; - case "macro": return "variable-2"; - case "number": return "number"; - case "operator": return "operator"; - case "record": return "bracket"; - case "string": return "string"; - case "type": return "def"; - case "variable": return "variable"; - case "error": return "error"; - case "separator": return null; - case "open_paren": return null; - case "close_paren": return null; - default: return null; - } - } +///////////////////////////////////////////////////////////////////////////// +// constants var typeWords = [ "-type", "-spec", "-export_type", "-opaque"]; @@ -48,23 +27,23 @@ CodeMirror.defineMode("erlang", function(cmCfg) { "after","begin","catch","case","cond","end","fun","if", "let","of","query","receive","try","when"]; - var separatorRE = /[\->\.,:;]/; + var separatorRE = /[\->,;]/; var separatorWords = [ - "->",";",":",".",","]; + "->",";",","]; - var operatorWords = [ + var operatorAtomWords = [ "and","andalso","band","bnot","bor","bsl","bsr","bxor", "div","not","or","orelse","rem","xor"]; - var symbolRE = /[\+\-\*\/<>=\|:!]/; - var symbolWords = [ - "+","-","*","/",">",">=","<","=<","=:=","==","=/=","/=","||","<-","!"]; + var operatorSymbolRE = /[\+\-\*\/<>=\|:!]/; + var operatorSymbolWords = [ + "=","+","-","*","/",">",">=","<","=<","=:=","==","=/=","/=","||","<-","!"]; - var openParenRE = /[<\(\[\{]/; + var openParenRE = /[<\(\[\{]/; var openParenWords = [ "<<","(","[","{"]; - var closeParenRE = /[>\)\]\}]/; + var closeParenRE = /[>\)\]\}]/; var closeParenWords = [ "}","]",")",">>"]; @@ -99,23 +78,25 @@ CodeMirror.defineMode("erlang", function(cmCfg) { "term_to_binary","time","throw","tl","trunc","tuple_size", "tuple_to_list","unlink","unregister","whereis"]; -// [Ø-Þ] [À-Ö] -// [ß-ö] [ø-ÿ] +// upper case: [A-Z] [Ø-Þ] [À-Ö] +// lower case: [a-z] [ß-ö] [ø-ÿ] var anumRE = /[\w@Ø-ÞÀ-Öß-öø-ÿ]/; var escapesRE = /[0-7]{1,3}|[bdefnrstv\\"']|\^[a-zA-Z]|x[0-9a-zA-Z]{2}|x{[0-9a-zA-Z]+}/; - function tokenize(stream, state) { +///////////////////////////////////////////////////////////////////////////// +// tokenizer + function tokenizer(stream,state) { // in multi-line string if (state.in_string) { - state.in_string = (!doubleQuote(stream)); + state.in_string = (!doubleQuote(stream)); return rval(state,stream,"string"); } // in multi-line atom if (state.in_atom) { - state.in_atom = (!singleQuote(stream)); + state.in_atom = (!singleQuote(stream)); return rval(state,stream,"atom"); } @@ -125,9 +106,9 @@ CodeMirror.defineMode("erlang", function(cmCfg) { } // attributes and type specs - if ((peekToken(state).token == "") && + if (!peekToken(state) && stream.match(/-\s*[a-zß-öø-ÿ][\wØ-ÞÀ-Öß-öø-ÿ]*/)) { - if (isMember(stream.current(),typeWords)) { + if (is_member(stream.current(),typeWords)) { return rval(state,stream,"type"); }else{ return rval(state,stream,"attribute"); @@ -142,32 +123,43 @@ CodeMirror.defineMode("erlang", function(cmCfg) { return rval(state,stream,"comment"); } + // colon + if (ch == ":") { + return rval(state,stream,"colon"); + } + // macro if (ch == '?') { + stream.eatSpace(); stream.eatWhile(anumRE); return rval(state,stream,"macro"); } // record if (ch == "#") { + stream.eatSpace(); stream.eatWhile(anumRE); return rval(state,stream,"record"); } // dollar escape - if ( ch == "$" ) { + if (ch == "$") { if (stream.next() == "\\" && !stream.match(escapesRE)) { return rval(state,stream,"error"); } return rval(state,stream,"number"); } + // dot + if (ch == ".") { + return rval(state,stream,"dot"); + } + // quoted atom if (ch == '\'') { if (!(state.in_atom = (!singleQuote(stream)))) { if (stream.match(/\s*\/\s*[0-9]/,false)) { stream.match(/\s*\/\s*[0-9]/,true); - popToken(state); return rval(state,stream,"fun"); // 'f'/0 style fun } if (stream.match(/\s*\(/,false) || stream.match(/\s*:/,false)) { @@ -195,34 +187,37 @@ CodeMirror.defineMode("erlang", function(cmCfg) { if (stream.match(/\s*\/\s*[0-9]/,false)) { stream.match(/\s*\/\s*[0-9]/,true); - popToken(state); return rval(state,stream,"fun"); // f/0 style fun } var w = stream.current(); - if (isMember(w,keywordWords)) { - pushToken(state,stream); + if (is_member(w,keywordWords)) { return rval(state,stream,"keyword"); + }else if (is_member(w,operatorAtomWords)) { + return rval(state,stream,"operator"); }else if (stream.match(/\s*\(/,false)) { // 'put' and 'erlang:put' are bifs, 'foo:put' is not - if (isMember(w,bifWords) && - (!isPrev(stream,":") || isPrev(stream,"erlang:"))) { + if (is_member(w,bifWords) && + ((peekToken(state).token != ":") || + (peekToken(state,2).token == "erlang"))) { return rval(state,stream,"builtin"); - }else if (isMember(w,guardWords)) { + }else if (is_member(w,guardWords)) { return rval(state,stream,"guard"); }else{ return rval(state,stream,"function"); } - }else if (isMember(w,operatorWords)) { + }else if (is_member(w,operatorAtomWords)) { return rval(state,stream,"operator"); - }else if (stream.match(/\s*:/,false)) { + }else if (lookahead(stream) == ":") { if (w == "erlang") { return rval(state,stream,"builtin"); } else { return rval(state,stream,"function"); } - }else if (isMember(w,["true","false"])) { + }else if (is_member(w,["true","false"])) { + return rval(state,stream,"boolean"); + }else if (is_member(w,["true","false"])) { return rval(state,stream,"boolean"); }else{ return rval(state,stream,"atom"); @@ -234,15 +229,25 @@ CodeMirror.defineMode("erlang", function(cmCfg) { var radixRE = /[0-9a-zA-Z]/; // 36#zZ style int if (digitRE.test(ch)) { stream.eatWhile(digitRE); - if (stream.eat('#')) { - stream.eatWhile(radixRE); // 36#aZ style integer - } else { - if (stream.eat('.')) { // float - stream.eatWhile(digitRE); + if (stream.eat('#')) { // 36#aZ style integer + if (!stream.eatWhile(radixRE)) { + stream.backUp(1); //"36#" - syntax error } - if (stream.eat(/[eE]/)) { - stream.eat(/[-+]/); // float with exponent - stream.eatWhile(digitRE); + } else if (stream.eat('.')) { // float + if (!stream.eatWhile(digitRE)) { + stream.backUp(1); // "3." - probably end of function + } else { + if (stream.eat(/[eE]/)) { // float with exponent + if (stream.eat(/[-+]/)) { + if (!stream.eatWhile(digitRE)) { + stream.backUp(2); // "2e-" - syntax error + } + } else { + if (!stream.eatWhile(digitRE)) { + stream.backUp(1); // "2e" - syntax error + } + } + } } } return rval(state,stream,"number"); // normal integer @@ -250,50 +255,35 @@ CodeMirror.defineMode("erlang", function(cmCfg) { // open parens if (nongreedy(stream,openParenRE,openParenWords)) { - pushToken(state,stream); return rval(state,stream,"open_paren"); } // close parens if (nongreedy(stream,closeParenRE,closeParenWords)) { - pushToken(state,stream); return rval(state,stream,"close_paren"); } // separators if (greedy(stream,separatorRE,separatorWords)) { - // distinguish between "." as terminator and record field operator - if (!state.in_record) { - pushToken(state,stream); - } return rval(state,stream,"separator"); } // operators - if (greedy(stream,symbolRE,symbolWords)) { + if (greedy(stream,operatorSymbolRE,operatorSymbolWords)) { return rval(state,stream,"operator"); } return rval(state,stream,null); } - function isPrev(stream,string) { - var start = stream.start; - var len = string.length; - if (len <= start) { - var word = stream.string.slice(start-len,start); - return word == string; - }else{ - return false; - } - } - +///////////////////////////////////////////////////////////////////////////// +// utilities function nongreedy(stream,re,words) { if (stream.current().length == 1 && re.test(stream.current())) { stream.backUp(1); while (re.test(stream.peek())) { stream.next(); - if (isMember(stream.current(),words)) { + if (is_member(stream.current(),words)) { return true; } } @@ -308,7 +298,7 @@ CodeMirror.defineMode("erlang", function(cmCfg) { stream.next(); } while (0 < stream.current().length) { - if (isMember(stream.current(),words)) { + if (is_member(stream.current(),words)) { return true; }else{ stream.backUp(1); @@ -339,144 +329,277 @@ CodeMirror.defineMode("erlang", function(cmCfg) { return false; } - function isMember(element,list) { + function lookahead(stream) { + var m = stream.match(/([\n\s]+|%[^\n]*\n)*(.)/,false); + return m ? m.pop() : ""; + } + + function is_member(element,list) { return (-1 < list.indexOf(element)); } -///////////////////////////////////////////////////////////////////////////// - function myIndent(state,textAfter) { - var indent = cmCfg.indentUnit; - var token = (peekToken(state)).token; - var wordAfter = takewhile(textAfter,/[^a-z]/); + function rval(state,stream,type) { - if (state.in_string || state.in_atom) { - return CodeMirror.Pass; - }else if (token == "") { - return 0; - }else if (isMember(token,openParenWords)) { - return (peekToken(state)).column+token.length; - }else if (token == "when") { - return (peekToken(state)).column+token.length+1; - }else if (token == "fun" && wordAfter == "") { - return (peekToken(state)).column+token.length; - }else if (token == "->") { - if (isMember(wordAfter,["end","after","catch"])) { - return peekToken(state,2).column; - }else if (peekToken(state,2).token == "fun") { - return peekToken(state,2).column+indent; - }else if (peekToken(state,2).token == "") { - return indent; - }else{ - return (peekToken(state)).indent+indent; - } - }else if (isMember(wordAfter,["after","catch","of"])) { - return (peekToken(state)).indent; - }else{ - return (peekToken(state)).column+indent; + // parse stack + pushToken(state,realToken(type,stream)); + + // map erlang token type to CodeMirror style class + // erlang -> CodeMirror tag + switch (type) { + case "atom": return "atom"; + case "attribute": return "attribute"; + case "boolean": return "special"; + case "builtin": return "builtin"; + case "close_paren": return null; + case "colon": return null; + case "comment": return "comment"; + case "dot": return null; + case "error": return "error"; + case "fun": return "meta"; + case "function": return "tag"; + case "guard": return "property"; + case "keyword": return "keyword"; + case "macro": return "variable-2"; + case "number": return "number"; + case "open_paren": return null; + case "operator": return "operator"; + case "record": return "bracket"; + case "separator": return null; + case "string": return "string"; + case "type": return "def"; + case "variable": return "variable"; + default: return null; } } - function takewhile(str,re) { - var m = str.match(re); - return m ? str.slice(0,m.index) : str; + function aToken(tok,col,ind,typ) { + return {token: tok, + column: col, + indent: ind, + type: typ}; } - function Token(stream) { - this.token = stream ? stream.current() : ""; - this.column = stream ? stream.column() : 0; - this.indent = stream ? stream.indentation() : 0; + function realToken(type,stream) { + return aToken(stream.current(), + stream.column(), + stream.indentation(), + type); } - function popToken(state) { - return state.tokenStack.pop(); + function fakeToken(type) { + return aToken(type,0,0,type); } function peekToken(state,depth) { var len = state.tokenStack.length; var dep = (depth ? depth : 1); + if (len < dep) { - return new Token; + return false; }else{ return state.tokenStack[len-dep]; } } - function pushToken(state,stream) { - var token = stream.current(); - var prev_token = peekToken(state).token; + function pushToken(state,token) { - if (token == ".") { - state.tokenStack = []; - return false; - }else if(isMember(token,[",", ":", "of", "cond", "let", "query"])) { - return false; - }else if (drop_last(prev_token,token)) { - return false; - }else if (drop_both(prev_token,token)) { - popToken(state); - return false; - }else if (drop_first(prev_token,token)) { - popToken(state); - return pushToken(state,stream); - }else if (isMember(token,["after","catch"])) { - return false; + if (!(token.type == "comment" || token.type == "whitespace")) { + state.tokenStack = maybe_drop_pre(state.tokenStack,token); + state.tokenStack = maybe_drop_post(state.tokenStack); + } + } + + function maybe_drop_pre(s,token) { + var last = s.length-1; + + if (0 < last && s[last].type === "record" && token.type === "dot") { + s.pop(); + }else if (0 < last && s[last].type === "group") { + s.pop(); + s.push(token); }else{ - state.tokenStack.push(new Token(stream)); - return true; + s.push(token); } + return s; } - function drop_last(open, close) { - switch(open+" "+close) { - case "when ;": return true; - default: return false; + function maybe_drop_post(s) { + var last = s.length-1; + + if (s[last].type === "dot") { + return []; + } + if (s[last].type === "fun" && s[last-1].token === "fun") { + return s.slice(0,last-1); + } + switch (s[s.length-1].token) { + case "}": return d(s,{g:["{"]}); + case "]": return d(s,{i:["["]}); + case ")": return d(s,{i:["("]}); + case ">>": return d(s,{i:["<<"]}); + case "end": return d(s,{i:["begin","case","fun","if","receive","try"]}); + case ",": return d(s,{e:["begin","try","when","->", + ",","(","[","{","<<"]}); + case "->": return d(s,{r:["when"], + m:["try","if","case","receive"]}); + case ";": return d(s,{E:["case","fun","if","receive","try","when"]}); + case "catch":return d(s,{e:["try"]}); + case "of": return d(s,{e:["case"]}); + case "after":return d(s,{e:["receive","try"]}); + default: return s; } } - function drop_first(open, close) { - switch (open+" "+close) { - case "when ->": return true; - case "-> end": return true; - default: return false; + function d(stack,tt) { + // stack is a stack of Token objects. + // tt is an object; {type:tokens} + // type is a char, tokens is a list of token strings. + // The function returns (possibly truncated) stack. + // It will descend the stack, looking for a Token such that Token.token + // is a member of tokens. If it does not find that, it will normally (but + // see "E" below) return stack. If it does find a match, it will remove + // all the Tokens between the top and the matched Token. + // If type is "m", that is all it does. + // If type is "i", it will also remove the matched Token and the top Token. + // If type is "g", like "i", but add a fake "group" token at the top. + // If type is "r", it will remove the matched Token, but not the top Token. + // If type is "e", it will keep the matched Token but not the top Token. + // If type is "E", it behaves as for type "e", except if there is no match, + // in which case it will return an empty stack. + + for (var type in tt) { + var len = stack.length-1; + var tokens = tt[type]; + for (var i = len-1; -1 < i ; i--) { + if (is_member(stack[i].token,tokens)) { + var ss = stack.slice(0,i); + switch (type) { + case "m": return ss.concat(stack[i]).concat(stack[len]); + case "r": return ss.concat(stack[len]); + case "i": return ss; + case "g": return ss.concat(fakeToken("group")); + case "E": return ss.concat(stack[i]); + case "e": return ss.concat(stack[i]); + } + } + } } + return (type == "E" ? [] : stack); } - function drop_both(open, close) { - switch (open+" "+close) { - case "( )": return true; - case "[ ]": return true; - case "{ }": return true; - case "<< >>": return true; - case "begin end": return true; - case "case end": return true; - case "fun end": return true; - case "if end": return true; - case "receive end": return true; - case "try end": return true; - case "-> catch": return true; - case "-> after": return true; - case "-> ;": return true; - default: return false; +///////////////////////////////////////////////////////////////////////////// +// indenter + + function indenter(state,textAfter) { + var t; + var unit = cmCfg.indentUnit; + var wordAfter = wordafter(textAfter); + var currT = peekToken(state,1); + var prevT = peekToken(state,2); + + if (state.in_string || state.in_atom) { + return CodeMirror.Pass; + }else if (!prevT) { + return 0; + }else if (currT.token == "when") { + return currT.column+unit; + }else if (wordAfter === "when" && prevT.type === "function") { + return prevT.indent+unit; + }else if (wordAfter === "(" && currT.token === "fun") { + return currT.column+3; + }else if (wordAfter === "catch" && (t = getToken(state,["try"]))) { + return t.column; + }else if (is_member(wordAfter,["end","after","of"])) { + t = getToken(state,["begin","case","fun","if","receive","try"]); + return t ? t.column : CodeMirror.Pass; + }else if (is_member(wordAfter,closeParenWords)) { + t = getToken(state,openParenWords); + return t ? t.column : CodeMirror.Pass; + }else if (is_member(currT.token,[",","|","||"]) || + is_member(wordAfter,[",","|","||"])) { + t = postcommaToken(state); + return t ? t.column+t.token.length : unit; + }else if (currT.token == "->") { + if (is_member(prevT.token, ["receive","case","if","try"])) { + return prevT.column+unit+unit; + }else{ + return prevT.column+unit; + } + }else if (is_member(currT.token,openParenWords)) { + return currT.column+currT.token.length; + }else{ + t = defaultToken(state); + return truthy(t) ? t.column+unit : 0; } } + function wordafter(str) { + var m = str.match(/,|[a-z]+|\}|\]|\)|>>|\|+|\(/); + + return truthy(m) && (m.index === 0) ? m[0] : ""; + } + + function postcommaToken(state) { + var objs = state.tokenStack.slice(0,-1); + var i = getTokenIndex(objs,"type",["open_paren"]); + + return truthy(objs[i]) ? objs[i] : false; + } + + function defaultToken(state) { + var objs = state.tokenStack; + var stop = getTokenIndex(objs,"type",["open_paren","separator","keyword"]); + var oper = getTokenIndex(objs,"type",["operator"]); + + if (truthy(stop) && truthy(oper) && stop < oper) { + return objs[stop+1]; + } else if (truthy(stop)) { + return objs[stop]; + } else { + return false; + } + } + + function getToken(state,tokens) { + var objs = state.tokenStack; + var i = getTokenIndex(objs,"token",tokens); + + return truthy(objs[i]) ? objs[i] : false; + } + + function getTokenIndex(objs,propname,propvals) { + + for (var i = objs.length-1; -1 < i ; i--) { + if (is_member(objs[i][propname],propvals)) { + return i; + } + } + return false; + } + + function truthy(x) { + return (x !== false) && (x != null); + } + +///////////////////////////////////////////////////////////////////////////// +// this object defines the mode + return { startState: function() { return {tokenStack: [], - in_record: false, in_string: false, in_atom: false}; }, token: function(stream, state) { - return tokenize(stream, state); + return tokenizer(stream, state); }, indent: function(state, textAfter) { - return myIndent(state,textAfter); + return indenter(state,textAfter); }, lineComment: "%" diff --git a/mode/erlang/index.html b/mode/erlang/index.html index e63e231201..9cacb759f6 100644 --- a/mode/erlang/index.html +++ b/mode/erlang/index.html @@ -51,11 +51,12 @@

    Erlang mode

    case tuple_size(Tup) of L when L < 1 -> Tup; L -> - try Fields = M:rec_info(element(1,Tup)), - L = length(Fields)+1, - lists:zip(Fields,expand_recs(M,tl(tuple_to_list(Tup)))) - catch _:_ -> - list_to_tuple(expand_recs(M,tuple_to_list(Tup))) + try + Fields = M:rec_info(element(1,Tup)), + L = length(Fields)+1, + lists:zip(Fields,expand_recs(M,tl(tuple_to_list(Tup)))) + catch + _:_ -> list_to_tuple(expand_recs(M,tuple_to_list(Tup))) end end; expand_recs(_,Term) -> From cbce0ffe5778a663c7a52f6cb9c888a5cbee0a67 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 16 Jan 2014 13:12:28 +0100 Subject: [PATCH 0160/4131] [xml mode] Return Pass when indenting cdata/pre content Issue #2135 --- mode/xml/xml.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mode/xml/xml.js b/mode/xml/xml.js index c75200ec7b..96b51ff970 100644 --- a/mode/xml/xml.js +++ b/mode/xml/xml.js @@ -298,8 +298,8 @@ CodeMirror.defineMode("xml", function(config, parserConfig) { if (state.tokenize.isInAttribute) { return state.stringStartCol + 1; } - if ((state.tokenize != inTag && state.tokenize != inText) || - context && context.noIndent) + if (context && context.noIndent) return CodeMirror.Pass; + if (state.tokenize != inTag && state.tokenize != inText) return fullLine ? fullLine.match(/^(\s*)/)[0].length : 0; // Indent the starts of attribute names. if (state.tagName) { From 8f10e2fb124240c3dbab66bd9b5f0ddca7558b02 Mon Sep 17 00:00:00 2001 From: Peter Kroon Date: Thu, 16 Jan 2014 13:13:57 +0100 Subject: [PATCH 0161/4131] [css mode] More careful categorizing of @-names as variables https://developer.mozilla.org/en-US/docs/Web/CSS/At-rule --- mode/css/css.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mode/css/css.js b/mode/css/css.js index c28d3e0a3b..8f6fe7df4d 100644 --- a/mode/css/css.js +++ b/mode/css/css.js @@ -667,7 +667,7 @@ CodeMirror.defineMode("css", function(config, parserConfig) { } }, "@": function(stream) { - if (stream.match(/^(font-face|media|import)\b/, false)) return false; + if (stream.match(/^(charset|document|font-face|import|keyframes|media|namespace|page|supports)\b/, false)) return false; stream.eatWhile(/[\w\\\-]/); if (stream.match(/^\s*:/, false)) return ["variable-2", "variable-definition"]; From 4c07e0b7793f6e701f14a72d5d496cfd8740b961 Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Sat, 11 Jan 2014 13:13:10 -0500 Subject: [PATCH 0162/4131] [mllike mode] Rename OCaml mode and extend with F# support Add support for the F# programming language. Highlighting is provided for all keywords, number literals, strings, ML-style comments and select built-ins. C-style comments not currently supported. --- mode/{ocaml => mllike}/index.html | 49 ++++++++++-- mode/{ocaml/ocaml.js => mllike/mllike.js} | 93 ++++++++++++++++++++--- 2 files changed, 122 insertions(+), 20 deletions(-) rename mode/{ocaml => mllike}/index.html (80%) rename mode/{ocaml/ocaml.js => mllike/mllike.js} (59%) diff --git a/mode/ocaml/index.html b/mode/mllike/index.html similarity index 80% rename from mode/ocaml/index.html rename to mode/mllike/index.html index 5d39fadd97..67bfef8581 100644 --- a/mode/ocaml/index.html +++ b/mode/mllike/index.html @@ -1,13 +1,13 @@ -CodeMirror: OCaml mode +CodeMirror: ML-like mode - + @@ -21,7 +21,7 @@ @@ -29,7 +29,7 @@

    OCaml mode

    - +

    F# mode

    + + + -

    MIME types defined: text/x-ocaml.

    +

    MIME types defined: text/x-ocaml (OCaml) and text/x-fsharp (F#).

    diff --git a/mode/ocaml/ocaml.js b/mode/mllike/mllike.js similarity index 59% rename from mode/ocaml/ocaml.js rename to mode/mllike/mllike.js index 32cbc0b7ba..ea75ffa214 100644 --- a/mode/ocaml/ocaml.js +++ b/mode/mllike/mllike.js @@ -1,14 +1,11 @@ -CodeMirror.defineMode('ocaml', function() { +CodeMirror.defineMode('mllike', function(_config, parserConfig) { var words = { - 'true': 'atom', - 'false': 'atom', 'let': 'keyword', 'rec': 'keyword', 'in': 'keyword', 'of': 'keyword', 'and': 'keyword', - 'succ': 'keyword', 'if': 'keyword', 'then': 'keyword', 'else': 'keyword', @@ -25,17 +22,19 @@ CodeMirror.defineMode('ocaml', function() { 'match': 'keyword', 'with': 'keyword', 'try': 'keyword', - 'raise': 'keyword', - 'begin': 'keyword', - 'end': 'keyword', 'open': 'builtin', - 'trace': 'builtin', 'ignore': 'builtin', - 'exit': 'builtin', - 'print_string': 'builtin', - 'print_endline': 'builtin' + 'begin': 'keyword', + 'end': 'keyword' }; + var extraWords = parserConfig.extraWords || {}; + for (var prop in extraWords) { + if (extraWords.hasOwnProperty(prop)) { + words[prop] = parserConfig.extraWords[prop]; + } + } + function tokenBase(stream, state) { var ch = stream.next(); @@ -113,4 +112,74 @@ CodeMirror.defineMode('ocaml', function() { }; }); -CodeMirror.defineMIME('text/x-ocaml', 'ocaml'); +CodeMirror.defineMIME('text/x-ocaml', { + name: 'mllike', + extraWords: { + 'succ': 'keyword', + 'trace': 'builtin', + 'exit': 'builtin', + 'print_string': 'builtin', + 'print_endline': 'builtin', + 'true': 'atom', + 'false': 'atom', + 'raise': 'keyword' + } +}); + +CodeMirror.defineMIME('text/x-fsharp', { + name: 'mllike', + extraWords: { + 'abstract': 'keyword', + 'as': 'keyword', + 'assert': 'keyword', + 'base': 'keyword', + 'class': 'keyword', + 'default': 'keyword', + 'delegate': 'keyword', + 'downcast': 'keyword', + 'downto': 'keyword', + 'elif': 'keyword', + 'exception': 'keyword', + 'extern': 'keyword', + 'finally': 'keyword', + 'global': 'keyword', + 'inherit': 'keyword', + 'inline': 'keyword', + 'interface': 'keyword', + 'internal': 'keyword', + 'lazy': 'keyword', + 'let!': 'keyword', + 'member' : 'keyword', + 'module': 'keyword', + 'namespace': 'keyword', + 'new': 'keyword', + 'null': 'keyword', + 'override': 'keyword', + 'private': 'keyword', + 'public': 'keyword', + 'return': 'keyword', + 'return!': 'keyword', + 'select': 'keyword', + 'static': 'keyword', + 'struct': 'keyword', + 'upcast': 'keyword', + 'use': 'keyword', + 'use!': 'keyword', + 'val': 'keyword', + 'when': 'keyword', + 'yield': 'keyword', + 'yield!': 'keyword', + + 'List': 'builtin', + 'Seq': 'builtin', + 'Map': 'builtin', + 'Set': 'builtin', + 'int': 'builtin', + 'string': 'builtin', + 'raise': 'builtin', + 'failwith': 'builtin', + 'not': 'builtin', + 'true': 'builtin', + 'false': 'builtin' + } +}); \ No newline at end of file From 53f3aba5bf1f7faf0fbef0ef5522970d5f4942e6 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 16 Jan 2014 13:35:27 +0100 Subject: [PATCH 0163/4131] [mllike mode] Integrate Add //-comment support for F# Issue #2136 --- doc/compress.html | 2 +- mode/index.html | 3 ++- mode/mllike/mllike.js | 12 +++++++++--- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/doc/compress.html b/doc/compress.html index 3f3bfb0465..205f7839ba 100644 --- a/doc/compress.html +++ b/doc/compress.html @@ -114,9 +114,9 @@

    Script compression helper

    + - diff --git a/mode/index.html b/mode/index.html index e332f84f70..7c1f740615 100644 --- a/mode/index.html +++ b/mode/index.html @@ -46,6 +46,7 @@

    Language modes

  • Eiffel
  • Erlang
  • Fortran
  • +
  • F#
  • Gas (AT&T-style assembly)
  • Gherkin
  • Go
  • @@ -68,7 +69,7 @@

    Language modes

  • mIRC
  • Nginx
  • NTriples
  • -
  • OCaml
  • +
  • OCaml
  • Octave (MATLAB)
  • Pascal
  • PEG.js
  • diff --git a/mode/mllike/mllike.js b/mode/mllike/mllike.js index ea75ffa214..1d64789a19 100644 --- a/mode/mllike/mllike.js +++ b/mode/mllike/mllike.js @@ -57,6 +57,10 @@ CodeMirror.defineMode('mllike', function(_config, parserConfig) { stream.eatWhile(/\w/); return 'quote'; } + if (ch === '/' && parserConfig.slashComments && stream.eat('/')) { + stream.skipToEnd(); + return 'comment'; + } if (/\d/.test(ch)) { stream.eatWhile(/[\d]/); if (stream.eat('.')) { @@ -108,7 +112,8 @@ CodeMirror.defineMode('mllike', function(_config, parserConfig) { }, blockCommentStart: "(*", - blockCommentEnd: "*)" + blockCommentEnd: "*)", + lineComment: parserConfig.slashComments ? "//" : null }; }); @@ -181,5 +186,6 @@ CodeMirror.defineMIME('text/x-fsharp', { 'not': 'builtin', 'true': 'builtin', 'false': 'builtin' - } -}); \ No newline at end of file + }, + slashComments: true +}); From 40a973a45f8059770dae169599f90343425d7668 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 16 Jan 2014 13:36:42 +0100 Subject: [PATCH 0164/4131] [mllike mode] Update mode/meta.js Issue #2136 --- mode/meta.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mode/meta.js b/mode/meta.js index 226cff12e5..f37cea55b5 100644 --- a/mode/meta.js +++ b/mode/meta.js @@ -18,6 +18,7 @@ CodeMirror.modeInfo = [ {name: 'Eiffel', mime: 'text/x-eiffel', mode: 'eiffel'}, {name: 'Erlang', mime: 'text/x-erlang', mode: 'erlang'}, {name: 'Fortran', mime: 'text/x-fortran', mode: 'fortran'}, + {name: 'F#', mime: 'text/x-fsharp', mode: 'mllike'}, {name: 'Gas', mime: 'text/x-gas', mode: 'gas'}, {name: 'Gherkin', mime: 'text/x-feature', mode: 'gherkin'}, {name: 'GitHub Flavored Markdown', mime: 'text/x-gfm', mode: 'gfm'}, @@ -45,7 +46,7 @@ CodeMirror.modeInfo = [ {name: 'mIRC', mime: 'text/mirc', mode: 'mirc'}, {name: 'Nginx', mime: 'text/x-nginx-conf', mode: 'nginx'}, {name: 'NTriples', mime: 'text/n-triples', mode: 'ntriples'}, - {name: 'OCaml', mime: 'text/x-ocaml', mode: 'ocaml'}, + {name: 'OCaml', mime: 'text/x-ocaml', mode: 'mllike'}, {name: 'Octave', mime: 'text/x-octave', mode: 'octave'}, {name: 'Pascal', mime: 'text/x-pascal', mode: 'pascal'}, {name: 'PEG.js', mime: null, mode: 'pegjs'}, From cc23d768069bff93f8ad2bdda3e162e06fe945e1 Mon Sep 17 00:00:00 2001 From: Andrey Lushnikov Date: Mon, 13 Jan 2014 18:16:12 +0400 Subject: [PATCH 0165/4131] [runmode addon] Define text/plain mode in standalone script. --- addon/runmode/runmode-standalone.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/addon/runmode/runmode-standalone.js b/addon/runmode/runmode-standalone.js index 9ebde8b054..ec06ba11cb 100644 --- a/addon/runmode/runmode-standalone.js +++ b/addon/runmode/runmode-standalone.js @@ -91,6 +91,10 @@ CodeMirror.getMode = function (options, spec) { return mfactory(options, spec); }; CodeMirror.registerHelper = CodeMirror.registerGlobalHelper = Math.min; +CodeMirror.defineMode("null", function() { + return {token: function(stream) {stream.skipToEnd();}}; +}); +CodeMirror.defineMIME("text/plain", "null"); CodeMirror.runMode = function (string, modespec, callback, options) { var mode = CodeMirror.getMode({ indentUnit: 2 }, modespec); From 33c40af12557ad7a58ff2ca35027733c27cdb516 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 16 Jan 2014 13:50:07 +0100 Subject: [PATCH 0166/4131] Give change events for 'cut' changes origin="cut" Issue #2140 --- lib/codemirror.js | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/lib/codemirror.js b/lib/codemirror.js index d2930ed270..4ca2ee3889 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -62,7 +62,8 @@ window.CodeMirror = (function() { overlays: [], modeGen: 0, overwrite: false, focused: false, - suppressEdits: false, pasteIncoming: false, + suppressEdits: false, + pasteIncoming: false, cutIncoming: false, draggingText: false, highlight: new Delayed()}; @@ -1512,11 +1513,11 @@ window.CodeMirror = (function() { var updateInput = cm.curOp.updateInput; var changeEvent = {from: from, to: to, text: splitLines(inserted), - origin: cm.state.pasteIncoming ? "paste" : "+input"}; + origin: cm.state.pasteIncoming ? "paste" : cm.state.cutIncoming ? "cut" : "+input"}; makeChange(cm.doc, changeEvent, "end"); cm.curOp.updateInput = updateInput; signalLater(cm, "inputRead", cm, changeEvent); - if (!cm.state.pasteIncoming && cm.options.electricChars && + if (inserted && !cm.state.pasteIncoming && cm.options.electricChars && cm.options.smartIndent && sel.head.ch < 100) { var electric = cm.getModeAt(sel.head).electricChars; if (electric) for (var i = 0; i < electric.length; i++) @@ -1529,7 +1530,7 @@ window.CodeMirror = (function() { if (text.length > 1000 || text.indexOf("\n") > -1) input.value = cm.display.prevInput = ""; else cm.display.prevInput = text; if (withOp) endOperation(cm); - cm.state.pasteIncoming = false; + cm.state.pasteIncoming = cm.state.cutIncoming = false; return true; } @@ -1670,13 +1671,14 @@ window.CodeMirror = (function() { fastPoll(cm); }); - function prepareCopy() { + function prepareCopy(e) { if (d.inaccurateSelection) { d.prevInput = ""; d.inaccurateSelection = false; d.input.value = cm.getSelection(); selectInput(d.input); } + if (e.type == "cut") cm.state.cutIncoming = true; } on(d.input, "cut", prepareCopy); on(d.input, "copy", prepareCopy); From 5befcdce0b7ad0d8dcada5eb1bfc81a5d5b6342e Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 16 Jan 2014 14:02:05 +0100 Subject: [PATCH 0167/4131] [javascript mode] Don't terminate regexp on slash inside of square brackets Closes #2141 --- mode/javascript/javascript.js | 22 ++++++++++++++-------- mode/javascript/test.js | 7 +++++++ 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/mode/javascript/javascript.js b/mode/javascript/javascript.js index 1985c6bbf5..fbf574b4fe 100644 --- a/mode/javascript/javascript.js +++ b/mode/javascript/javascript.js @@ -54,14 +54,16 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { var isOperatorChar = /[+\-*&%=<>!?|~^]/; - function nextUntilUnescaped(stream, end) { - var escaped = false, next; + function readRegexp(stream) { + var escaped = false, next, inSet = false; while ((next = stream.next()) != null) { - if (next == end && !escaped) - return false; + if (!escaped) { + if (next == "/" && !inSet) return; + if (next == "[") inSet = true; + else if (inSet && next == "]") inSet = false; + } escaped = !escaped && next == "\\"; } - return escaped; } // Used as scratch variables to communicate multiple values without @@ -99,7 +101,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { return ret("comment", "comment"); } else if (state.lastType == "operator" || state.lastType == "keyword c" || state.lastType == "sof" || /^[\[{}\(,;:]$/.test(state.lastType)) { - nextUntilUnescaped(stream, "/"); + readRegexp(stream); stream.eatWhile(/[gimy]/); // 'y' is "sticky" option in Mozilla return ret("regexp", "string-2"); } else { @@ -125,8 +127,12 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { function tokenString(quote) { return function(stream, state) { - if (!nextUntilUnescaped(stream, quote)) - state.tokenize = tokenBase; + var escaped = false, next; + while ((next = stream.next()) != null) { + if (next == quote && !escaped) break; + escaped = !escaped && next == "\\"; + } + if (!escaped) state.tokenize = tokenBase; return ret("string", "string"); }; } diff --git a/mode/javascript/test.js b/mode/javascript/test.js index cbb936d963..911bbbfd7b 100644 --- a/mode/javascript/test.js +++ b/mode/javascript/test.js @@ -103,4 +103,11 @@ "{", " [keyword debugger];", "}"); + + MT("multilinestring", + "[keyword var] [variable x] [operator =] [string 'foo\\]", + "[string bar'];"); + + MT("scary_regexp", + "[string-2 /foo[[/]]bar/];"); })(); From ba21b55c61dd07e2c294edc75cc8a1d8aeec9504 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 16 Jan 2014 14:07:56 +0100 Subject: [PATCH 0168/4131] [emacs keymap] Make ctrl-g clear mark Closes #2142 --- keymap/emacs.js | 15 ++++++++++++--- lib/codemirror.js | 5 ++++- test/emacs_test.js | 3 +++ 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/keymap/emacs.js b/keymap/emacs.js index f08e2e8d48..592238bc90 100644 --- a/keymap/emacs.js +++ b/keymap/emacs.js @@ -201,6 +201,11 @@ cm.on("change", function() { cm.setExtending(false); }); } + function clearMark(cm) { + cm.setExtending(false); + cm.setCursor(cm.getCursor()); + } + function getInput(cm, msg, f) { if (cm.openDialog) cm.openDialog(msg + ": ", f, {bottom: true}); @@ -234,6 +239,11 @@ } } + function quit(cm) { + cm.execCommand("clearSearch"); + clearMark(cm); + } + // Actual keymap var keyMap = CodeMirror.keyMap.emacs = { @@ -249,8 +259,7 @@ }), "Alt-W": function(cm) { addToRing(cm.getSelection()); - cm.setExtending(false); - cm.setCursor(cm.getCursor()); + clearMark(cm); }, "Ctrl-Y": function(cm) { var start = cm.getCursor(); @@ -336,7 +345,7 @@ "Ctrl-/": repeated("undo"), "Shift-Ctrl--": repeated("undo"), "Ctrl-Z": repeated("undo"), "Cmd-Z": repeated("undo"), "Shift-Alt-,": "goDocStart", "Shift-Alt-.": "goDocEnd", - "Ctrl-S": "findNext", "Ctrl-R": "findPrev", "Ctrl-G": "clearSearch", "Shift-Alt-5": "replace", + "Ctrl-S": "findNext", "Ctrl-R": "findPrev", "Ctrl-G": quit, "Shift-Alt-5": "replace", "Alt-/": "autocomplete", "Ctrl-J": "newlineAndIndent", "Enter": false, "Tab": "indentAuto", diff --git a/lib/codemirror.js b/lib/codemirror.js index 4ca2ee3889..c450c4e1d0 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -3154,7 +3154,10 @@ window.CodeMirror = (function() { triggerOnKeyDown: operation(null, onKeyDown), - execCommand: function(cmd) {return commands[cmd](this);}, + execCommand: function(cmd) { + if (commands.hasOwnProperty(cmd)) + return commands[cmd](this); + }, findPosH: function(from, amount, unit, visually) { var dir = 1; diff --git a/test/emacs_test.js b/test/emacs_test.js index ab18241dee..f21605bb37 100644 --- a/test/emacs_test.js +++ b/test/emacs_test.js @@ -125,6 +125,9 @@ sim("transposeExpr", "do foo[bar] dah", Pos(0, 6), "Ctrl-Alt-T", txt("do [bar]foo dah")); + sim("clearMark", "abcde", Pos(0, 2), "Ctrl-Space", "Ctrl-F", "Ctrl-F", + "Ctrl-G", "Ctrl-W", txt("abcde")); + testCM("save", function(cm) { var saved = false; CodeMirror.commands.save = function(cm) { saved = cm.getValue(); }; From 306f6d8d01e948009f3f6190e58986c75b01d218 Mon Sep 17 00:00:00 2001 From: Shawn A Date: Wed, 15 Jan 2014 13:34:29 -0600 Subject: [PATCH 0169/4131] [compression helper] Add anyword-hint --- doc/compress.html | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/compress.html b/doc/compress.html index 205f7839ba..beac099370 100644 --- a/doc/compress.html +++ b/doc/compress.html @@ -159,6 +159,7 @@

    Script compression helper

    + From bc32d2ac4288f51919cbb06e83ce1d4f5bb27e88 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 16 Jan 2014 14:24:30 +0100 Subject: [PATCH 0170/4131] [ruby mode] Fix 'loop do' creating two indentation contexts Closes #2146 --- mode/ruby/ruby.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mode/ruby/ruby.js b/mode/ruby/ruby.js index 96cdd5f9dd..1cdc9a4e43 100644 --- a/mode/ruby/ruby.js +++ b/mode/ruby/ruby.js @@ -12,7 +12,7 @@ CodeMirror.defineMode("ruby", function(config) { "caller", "lambda", "proc", "public", "protected", "private", "require", "load", "require_relative", "extend", "autoload", "__END__", "__FILE__", "__LINE__", "__dir__" ]); - var indentWords = wordObj(["def", "class", "case", "for", "while", "do", "module", "then", + var indentWords = wordObj(["def", "class", "case", "for", "while", "module", "then", "catch", "loop", "proc", "begin"]); var dedentWords = wordObj(["end", "until"]); var matching = {"[": "]", "{": "}", "(": ")"}; @@ -214,6 +214,8 @@ CodeMirror.defineMode("ruby", function(config) { else if (dedentWords.propertyIsEnumerable(word)) kwtype = "dedent"; else if ((word == "if" || word == "unless") && stream.column() == stream.indentation()) kwtype = "indent"; + else if (word == "do" && state.context.indented < state.indented) + kwtype = "indent"; } if (curPunc || (style && style != "comment")) state.lastTok = word || curPunc || style; if (curPunc == "|") state.varList = !state.varList; From 0e41639bebaa0535ab913563d0031d125ab241d4 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 16 Jan 2014 15:03:10 +0100 Subject: [PATCH 0171/4131] Kludge for another IE focus issue Issue #2127 --- lib/codemirror.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/codemirror.js b/lib/codemirror.js index c450c4e1d0..210806aace 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -1770,6 +1770,9 @@ window.CodeMirror = (function() { e_preventDefault(e2); extendSelection(cm.doc, start); focusInput(cm); + // Work around unexplainable focus problem in IE9 (#2127) + if (old_ie && !ie_lt9) + setTimeout(function() {document.body.focus(); focusInput(cm);}, 20); } }); // Let the drag handler handle this. From 81c01d196e6b0148ce3412d8f686c3039013f7c3 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 16 Jan 2014 19:34:52 +0100 Subject: [PATCH 0172/4131] Add a script to help bring out releases Does all the version bumping and such. --- bin/release | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100755 bin/release diff --git a/bin/release b/bin/release new file mode 100755 index 0000000000..f92ab006d5 --- /dev/null +++ b/bin/release @@ -0,0 +1,41 @@ +#!/usr/bin/env node + +var fs = require("fs"), child = require("child_process"); + +var number, bumpOnly; + +for (var i = 2; i < process.argv.length; i++) { + if (process.argv[i] == "-bump") bumpOnly = true; + else if (/^\d+\.\d+\.\d+$/.test(process.argv[i])) number = process.argv[i]; + else { console.log("Bogus command line arg: " + process.argv[i]); process.exit(1); } +} + +if (!number) { console.log("Must give a version"); process.exit(1); } + +function rewrite(file, f) { + fs.writeFileSync(file, f(fs.readFileSync(file, "utf8")), "utf8"); +} + +rewrite("lib/codemirror.js", function(lib) { + return lib.replace(/CodeMirror\.version = "\d+\.\d+\.\d+"/, + "CodeMirror.version = \"" + number + "\""); +}); +rewrite("package.json", function(pack) { + return pack.replace(/"version":"\d+\.\d+\.\d+"/, "\"version\":\"" + number + "\""); +}); + +if (bumpOnly) process.exit(0); + +child.exec("bash bin/authors.sh", function(){}); + +var simple = number.slice(0, number.lastIndexOf(".")); + +rewrite("doc/compress.html", function(cmp) { + return cmp.replace(/\n "); +}); + +rewrite("index.html", function(index) { + return index.replace(/version 3.20<\/strong>/, + "version " + simple + ""); +}); From 3a76b567e1cd5ebe7a4aca7ef139058c36f154e9 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 16 Jan 2014 20:05:09 +0100 Subject: [PATCH 0173/4131] Mark release 3.21 --- AUTHORS | 45 +++++++++++++++++++++++++++++++++++++++++++++ doc/compress.html | 1 + doc/releases.html | 13 +++++++++++++ index.html | 2 +- lib/codemirror.js | 2 +- package.json | 2 +- 6 files changed, 62 insertions(+), 3 deletions(-) diff --git a/AUTHORS b/AUTHORS index 260c13a864..737acedaba 100644 --- a/AUTHORS +++ b/AUTHORS @@ -2,6 +2,7 @@ List of CodeMirror contributors. Updated before every release. 4r2r Aaron Brooks +Abe Fettig Adam King adanlobato Adán Lobato @@ -10,16 +11,20 @@ Ahmad Amireh Ahmad M. Zawawi ahoward Akeksandr Motsjonov +Alberto Pose Albert Xing Alexander Pavlov Alexander Schepanovski +Alexander Solovyov alexey-k Alex Piggott Amy Ananya Sen AndersMad +Anderson Mesquita Andre von Houck Andrey Lushnikov +Andy Joslin Andy Kimball Andy Li angelozerr @@ -27,16 +32,20 @@ angelo.zerr@gmail.com Ankit Ahuja Ansel Santosa Anthony Grimes +Anton Kovalyov areos +AtomicPages LLC Atul Bhouraskar Aurelian Oancea Bastian Müller benbro +Beni Cherniavsky-Paskin Benjamin DeCoste Ben Keen boomyjee borawjm Brandon Frohs +Brandon Wamboldt Brett Zamir Brian Sletten Bruce Mitchener @@ -54,9 +63,11 @@ Dan Heberden Daniel, Dao Quang Minh Daniel Faust Daniel Huigens +Daniel KJ Daniel Neel Daniel Parnell Danny Yoo +Darius Roberts David Mignot David Pathakjee deebugger @@ -68,10 +79,13 @@ Drew Hintz Drew Khoury Dror BG duralog +eborden edsharp ekhaled +Enam Mijbah Noor Eric Allam eustas +Fabio Zendhi Nagao Fauntleroy fbuchinger feizhang365 @@ -80,6 +94,7 @@ Felix Raab Filip Noetzel flack ForbesLindesay +Forbes Lindesay Ford_Lawnmower Gabriel Nahmias galambalazs @@ -94,12 +109,15 @@ Guillaume Massé Hans Engel Hardest Hasan Karahan +hitsthings Hocdoc Ian Beck +Ian Dickinson Ian Wehrman Ian Wetherbee Ice White ICHIKAWA, Yuji +ilvalle Ingo Richter Irakli Gozalishvili Ivan Kurnosov @@ -111,6 +129,7 @@ Jamie Hill Jan Jongboom jankeromnes Jan Keromnes +Jan Odvarko Jan T. Sott Jason Jason Grout @@ -122,16 +141,21 @@ jeffkenton Jeff Pickhardt jem (graphite) Jochen Berger +Johan Ask John Connor John Lees-Miller John Snelson +John Van Der Loo jongalloway +Jon Malmaud Joost-Wim Boekesteijn Joseph Pecoraro Joshua Newman jots +jsoojeon Juan Benavides Romero Jucovschi Constantin +Juho Vuori jwallers@gmail.com kaniga Ken Newman @@ -145,11 +169,13 @@ koops ks-ifware kubelsmieci Lanny +Laszlo Vidacs leaf corcoran Leonya Khachaturov Liam Newman LM Lorenzo Stoakes +Luciano Longo lynschinzer Maksim Lin Maksym Taran @@ -158,8 +184,10 @@ Marco Aurélio Marijn Haverbeke Mario Pietsch Mark Lentczner +Marko Bonaci Martin Balek Martín Gaitán +Martin Hasoň Mason Malone Mateusz Paprocki mats cronqvist @@ -169,6 +197,7 @@ Matt McDonald Matt Pass Matt Sacks Maximilian Hils +Maxim Kraev Max Kirsch mbarkhau Metatheos @@ -183,7 +212,9 @@ Mike Diaz Mike Ivanov Mike Kadin MinRK +Miraculix87 misfo +mloginov mps Narciso Jaramillo Nathan Williams @@ -192,6 +223,7 @@ nguillaumin Niels van Groningen Nikita Beloglazov Nikita Vasilyev +Nikolay Kostov nlwillia pablo Page @@ -199,6 +231,7 @@ Patrick Strawderman Paul Garvin Paul Ivanov Pavel Feldman +Pavel Strashkin Paweł Bartkiewicz peteguhl peterkroon @@ -219,16 +252,22 @@ Sascha Peilicke satchmorun sathyamoorthi SCLINIC\jdecker +Sebastian Zaha shaund shaun gilchrist +Shawn A +Shiv Deepak Shmuel Englard +soliton4 sonson spastorelli +Stanislav Oaserele Stas Kobzar Stefan Borsje Steffen Beyer Steve O'Hara stoskov +Taha Jahangir Tarmil tfjgeorge Thaddee Tyl @@ -244,12 +283,18 @@ Tomas Varaneckas Tom Erik Støwer Tom MacWright Tony Jian +Travis Heppe Vestimir Markov vf Volker Mische +wenli +Wesley Wiser William Jamieson Wojtek Ptak Xavier Mendez +YNH Webdev Yunchi Luo Yuvi Panda Zachary Dremann +zziuni +魏鹏刚 diff --git a/doc/compress.html b/doc/compress.html index beac099370..c2ba8f7021 100644 --- a/doc/compress.html +++ b/doc/compress.html @@ -33,6 +33,7 @@

    Script compression helper

    Version: +
    + + + +

    + +
    +

    Multiple Selection Keybindings

    + +
    + + + +

    Demonstrates the extra bindings provided by +the multiselect addon.

    + +
    diff --git a/doc/compress.html b/doc/compress.html index c2ba8f7021..55e25f3e68 100644 --- a/doc/compress.html +++ b/doc/compress.html @@ -207,6 +207,7 @@

    Script compression helper

    + diff --git a/keymap/multiselect.js b/keymap/multiselect.js new file mode 100644 index 0000000000..f45f27254a --- /dev/null +++ b/keymap/multiselect.js @@ -0,0 +1,47 @@ +// A number of extra keybindings for multiple-selection handling +// Depends on addon/search/searchcursor.js and optionally addon/dialog/dialogs.js + +(function() { + "use strict"; + + var pc = CodeMirror.keyMap.pcDefault, mac = CodeMirror.keyMap.macDefault; + var Pos = CodeMirror.Pos; + + function dialog(cm, text, shortText, f) { + if (cm.openDialog) cm.openDialog(text, f); + else f(prompt(shortText, "")); + } + + // Split selection + pc["Shift-Ctrl-L"] = mac["Shift-Cmd-L"] = function(cm) { + var ranges = [], from = cm.getCursor("from"), to = cm.getCursor("to"); + for (var line = from.line; line <= to.line; ++line) + ranges.push({anchor: line == from.line ? from : Pos(line, 0), + head: line == to.line ? to : Pos(line)}); + cm.setSelections(ranges, 0); + }; + + // Add next occurrence to selection + pc["Ctrl-D"] = mac["Cmd-D"] = function(cm) { + var at = cm.getCursor("to"); + var cur = cm.getSearchCursor(cm.getRange(cm.getCursor("from"), at), at); + if (!cur.findNext()) return; + cm.addSelection(cur.from(), cur.to()); + }; + + // Go to a single selection + pc["Alt-Esc"] = mac["Alt-Esc"] = function(cm) { + cm.setSelection(cm.getCursor("anchor"), cm.getCursor("head")); + }; + + // Select matching parts of current selection + var dialogText = 'Match: (Use /re/ syntax for regexp)'; + pc["Alt-F"] = mac["Alt-F"] = function(cm) { + if (!cm.somethingSelected()) return; + dialog(cm, dialogText, "Match:", function(query) { + var isRE = query.match(/^\/(.*)\/([a-z]*)$/); + if (isRE) query = new RegExp(isRE[1], isRE[2].indexOf("i") == -1 ? "" : "i"); + cm.selectMatches(query); + }); + }; +})(); From 765d3a967a75c9827dcce556afeb2a8106c32f1f Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Wed, 13 Nov 2013 13:15:54 +0100 Subject: [PATCH 0214/4131] [tern addon] Add select-variable-instances functionality --- addon/tern/tern.js | 23 ++++++++++++++++++++++- demo/tern.html | 2 ++ lib/codemirror.js | 1 + 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/addon/tern/tern.js b/addon/tern/tern.js index 7f83c4e4c0..fa2a2c3528 100644 --- a/addon/tern/tern.js +++ b/addon/tern/tern.js @@ -106,6 +106,8 @@ rename: function(cm) { rename(this, cm); }, + selectName: function(cm) { selectName(this, cm); }, + request: function (cm, query, c, pos) { var self = this; var doc = findDoc(this, cm.getDoc()); @@ -429,6 +431,25 @@ }); } + function selectName(ts, cm) { + var cur = cm.getCursor(), token = cm.getTokenAt(cur); + if (!/\w/.test(token.string)) showError(ts, cm, "Not at a variable"); + var name = findDoc(ts, cm.doc).name; + ts.request(cm, {type: "refs"}, function(error, data) { + if (error) return showError(ts, cm, error); + var ranges = [], cur = 0; + for (var i = 0; i < data.refs.length; i++) { + var ref = data.refs[i]; + if (ref.file == name) { + ranges.push({anchor: ref.start, head: ref.end}); + if (cmpPos(cur, ref.start) >= 0 && cmpPos(cur, ref.end) <= 0) + cur = ranges.length - 1; + } + } + cm.setSelections(ranges, cur); + }); + } + var nextChangeOrig = 0; function applyChanges(ts, changes) { var perFile = Object.create(null); @@ -521,7 +542,7 @@ // Generic utilities - function cmpPos(a, b) { return a.line - b.line || a.ch - b.ch; } + var cmpPos = CodeMirror.cmpPos; function elt(tagname, cls /*, ... elts*/) { var e = document.createElement(tagname); diff --git a/demo/tern.html b/demo/tern.html index 6843c7f5ec..57027f7267 100644 --- a/demo/tern.html +++ b/demo/tern.html @@ -86,6 +86,7 @@

    Tern Demo

    Ctrl-I
    Find type at cursor
    Alt-.
    Jump to definition (Alt-, to jump back)
    Ctrl-Q
    Rename variable
    +
    Ctrl-.
    Select all occurrences of a variable

    Documentation is sparse for now. See the top of @@ -116,6 +117,7 @@

    Tern Demo

    "Alt-.": function(cm) { server.jumpToDef(cm); }, "Alt-,": function(cm) { server.jumpBack(cm); }, "Ctrl-Q": function(cm) { server.rename(cm); }, + "Ctrl-.": function(cm) { server.selectName(cm); } }) editor.on("cursorActivity", function(cm) { server.updateArgHints(cm); }); }); diff --git a/lib/codemirror.js b/lib/codemirror.js index e9aabb2332..be6ac6f999 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -5249,6 +5249,7 @@ window.CodeMirror = (function() { extendSelections(this, map(this.sel.ranges, f), bias); }), setSelections: docOperation(function(ranges, primary, bias) { + if (!ranges.length) return; for (var i = 0, out = []; i < ranges.length; i++) out[i] = new Range(clipPos(this, ranges[i].anchor), clipPos(this, ranges[i].head)); From 62827d68cac988c09cac7cda9fb7d56f40461a65 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Wed, 13 Nov 2013 14:29:03 +0100 Subject: [PATCH 0215/4131] [doc toc script] More accurate active link highlighting --- doc/activebookmark.js | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/doc/activebookmark.js b/doc/activebookmark.js index 88c879cf42..407282d02c 100644 --- a/doc/activebookmark.js +++ b/doc/activebookmark.js @@ -3,6 +3,7 @@ document.createElement("section"); document.createElement("article"); (function() { + if (!window.addEventListener) return; var pending = false, prevVal = null; function updateSoon() { @@ -41,8 +42,16 @@ document.createElement("article"); } } - if (window.addEventListener) { - window.addEventListener("scroll", updateSoon); - window.addEventListener("load", updateSoon); - } + window.addEventListener("scroll", updateSoon); + window.addEventListener("load", updateSoon); + window.addEventListener("hashchange", function() { + setTimeout(function() { + var hash = document.location.hash, found = null, m; + var marks = document.getElementById("nav").getElementsByTagName("a"); + for (var i = 0; i < marks.length; i++) + if ((m = marks[i].href.match(/(#.*)/)) && m[1] == hash) { found = i; break; } + if (found != null) for (var i = 0; i < marks.length; i++) + marks[i].className = i == found ? "active" : ""; + }, 300); + }); })(); From 7f01799b236514ab4be01b72cad8730b019ac1ea Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Wed, 13 Nov 2013 16:10:46 +0100 Subject: [PATCH 0216/4131] Document multiple selection API Issue #778 --- doc/manual.html | 95 +++++++++++++++++++++++++++++++++++-------------- 1 file changed, 69 insertions(+), 26 deletions(-) diff --git a/doc/manual.html b/doc/manual.html index c56af630e5..bb0517fb9a 100644 --- a/doc/manual.html +++ b/doc/manual.html @@ -514,14 +514,15 @@

    Events

    Fired whenever new input is read from the hidden textarea (typed or pasted by the user).
    -
    "beforeSelectionChange" (instance: CodeMirror, selection: {head, anchor})
    +
    "beforeSelectionChange" (instance: CodeMirror, obj: {ranges, update})
    This event is fired before the selection is moved. Its - handler may modify the resulting selection head and anchor. - The selection parameter is an object - with head and anchor properties - holding {line, ch} objects, which the handler can - read and update. Handlers for this event have the same - restriction + handler may inspect the set of selection ranges, present as an + array of {anchor, head} objects in + the ranges property of the obj + argument, and optionally change them by calling + the update method on this object, passing an array + of ranges in the same format. Handlers for this event have the + same restriction as "beforeChange" handlers — they should not do anything to directly update the state of the editor.
    @@ -962,46 +963,88 @@

    Content manipulation methods

    Cursor and selection methods

    -
    doc.getSelection() → string
    -
    Get the currently selected code.
    -
    doc.replaceSelection(replacement: string, ?collapse: string)
    -
    Replace the selection with the given string. By default, the - new selection will span the inserted text. The - optional collapse argument can be used to change - this—passing "start" or "end" will - collapse the selection to the start or end of the inserted - text.
    +
    doc.getSelection(?lineSep: string) → string
    +
    Get the currently selected code. Optionally pass a line + separator to put between the lines in the output. When multiple + selections are present, they are concatenated with instances + of lineSep in between.
    +
    doc.getSelections(?lineSep: string) → string
    +
    Returns an array containing a string for each selection, + representing the content of the selections.
    + +
    doc.replaceSelection(replacement: string, ?select: string)
    +
    Replace the selection(s) with the given string. By default, + the new selection ends up after the inserted text. The + optional select argument can be used to change + this—passing "around" will cause the new text to be + selected, passing "start" will collapse the + selection to the start of the inserted text.
    +
    doc.replaceSelections(replacements: array<string>, ?select: string)
    +
    The length of the given array should be the same as the + number of active selections. Replaces the content of the + selections with the strings in the array. + The select argument works the same as + in replaceSelection.
    doc.getCursor(?start: string) → {line, ch}
    -
    start is a an optional string indicating which - end of the selection to return. It may - be "start", "end", "head" +
    Retrieve one end of the primary + selection. start is a an optional string indicating + which end of the selection to return. It may + be "from", "to", "head" (the side of the selection that moves when you press shift+arrow), or "anchor" (the fixed side of the selection). Omitting the argument is the same as passing "head". A {line, ch} object will be returned.
    +
    doc.listSelections() → array<{anchor, head}<
    +
    Retrieves a list of all current selections. These will + always be sorted, and never overlap (overlapping selections are + merged). Each object in the array contains anchor + and head properties referring to {line, + ch} objects.
    +
    doc.somethingSelected() → boolean
    Return true if any text is selected.
    doc.setCursor(pos: {line, ch})
    Set the cursor position. You can either pass a single {line, ch} object, or the line and the - character as two separate parameters.
    + character as two separate parameters. Will replace all + selections with a single, empty selection at the given + position. +
    doc.setSelection(anchor: {line, ch}, ?head: {line, ch})
    -
    Set the selection range. anchor +
    Set a single selection range. anchor and head should be {line, ch} objects. head defaults to anchor when not given.
    +
    doc.setSelections(ranges: array<{anchor, head}>, ?primary: integer)
    +
    Sets a new set of selections. There must be at least one + selection in the given array. When primary is + given, it determines which selection is the primary one + (defaults to the last one).
    +
    doc.addSelection(anchor: {line, ch}, ?head: {line, ch})
    +
    Adds a new selection to the existing set of selections, and + makes it the primary selection.
    +
    doc.extendSelection(from: {line, ch}, ?to: {line, ch})
    Similar to setSelection, but will, if shift is held or the extending flag is set, move the head of the selection while leaving the anchor at its current - place. to is optional, and can be passed to - ensure a region (for example a word or paragraph) will end up - selected (in addition to whatever lies between that region and - the current anchor).
    + place. to is optional, and can be passed to ensure + a region (for example a word or paragraph) will end up selected + (in addition to whatever lies between that region and the + current anchor). When multiple selections are present, all but + the primary selection will be dropped by this method. +
    doc.extendSelections(heads: array<{line, ch}>)
    +
    An equivalent + of extendSelection + that acts on all selections at once.
    +
    doc.extendSelectionsBy(f: function(range: {anchor, head}) → {anchor, head}))
    +
    Applies the given function to all existing selections, and + calls extendSelections + on the result.
    doc.setExtending(value: boolean)
    Sets or clears the 'extending' flag, which acts similar to the shift key, in that it will cause cursor movement and calls @@ -1011,7 +1054,7 @@

    Cursor and selection methods

    cm.hasFocus() → boolean
    Tells you whether the editor currently has focus.
    -
    cm.findPosH(start: {line, ch}, amount: integer, unit: string, visually: boolean) → {line, ch, ?hitSide: boolean}
    +
    cm.findPosH(start: {line, ch}, amount: integer, unit: string, visually: boolean) → {line, ch, ?hitSide: boolean}
    Used to find the target position for horizontal cursor motion. start is a {line, ch} object, amount an integer (may be negative), From 61253d27ece551568397e63a32199e14e2dc4a5d Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Wed, 13 Nov 2013 16:21:23 +0100 Subject: [PATCH 0217/4131] Don't use .next properties in change event objects anymore --- doc/manual.html | 7 ++----- lib/codemirror.js | 23 ++++++++++------------- test/test.js | 9 +++++++-- 3 files changed, 19 insertions(+), 20 deletions(-) diff --git a/doc/manual.html b/doc/manual.html index bb0517fb9a..3e81b94c3a 100644 --- a/doc/manual.html +++ b/doc/manual.html @@ -460,7 +460,7 @@

    Events

    "change" (instance: CodeMirror, changeObj: object)
    Fires every time the content of the editor is changed. The changeObj is a {from, to, text, removed, - next} object containing information about the changes + origin} object containing information about the changes that occurred as second argument. from and to are the positions (in the pre-change coordinate system) where the change started and ended (for @@ -469,10 +469,7 @@

    Events

    an array of strings representing the text that replaced the changed range (split by line). removed is the text that used to be between from and to, - which is overwritten by this change. If multiple changes - happened during a single operation, the object will have - a next property pointing to another change object - (which may point to another, etc).
    + which is overwritten by this change.
    "beforeChange" (instance: CodeMirror, changeObj: object)
    This event is fired before a change is applied, and its diff --git a/lib/codemirror.js b/lib/codemirror.js index be6ac6f999..c5a332264f 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -1435,7 +1435,7 @@ window.CodeMirror = (function() { forceUpdate: false, updateInput: null, userSelChange: null, - textChanged: null, + changeObjs: null, selectionChanged: false, cursorActivity: false, updateMaxLine: false, @@ -1498,8 +1498,8 @@ window.CodeMirror = (function() { delayed = delayedCallbacks; delayedCallbacks = null; } - if (op.textChanged) - signal(cm, "change", cm, op.textChanged); + if (op.changeObjs) for (var i = 0; i < op.changeObjs.length; i++) + signal(cm, "change", cm, op.changeObjs[i]); if (op.cursorActivity) signal(cm, "cursorActivity", cm); if (delayed) for (var i = 0; i < delayed.length; ++i) delayed[i](); } @@ -2631,16 +2631,13 @@ window.CodeMirror = (function() { // Remember that these lines changed, for updating the display regChange(cm, from.line, to.line + 1, lendiff); - if (hasHandler(cm, "change")) { - var changeObj = {from: from, to: to, - text: change.text, - removed: change.removed, - origin: change.origin}; - if (cm.curOp.textChanged) { - for (var cur = cm.curOp.textChanged; cur.next; cur = cur.next) {} - cur.next = changeObj; - } else cm.curOp.textChanged = changeObj; - } + if (hasHandler(cm, "change")) + (cm.curOp.changeObjs || (cm.curOp.changeObjs = [])).push({ + from: from, to: to, + text: change.text, + removed: change.removed, + origin: change.origin + }); } function replaceRange(doc, code, from, to, origin) { diff --git a/test/test.js b/test/test.js index 0c129e9444..b96824bd2d 100644 --- a/test/test.js +++ b/test/test.js @@ -1603,9 +1603,9 @@ testCM("beforeSelectionChange", function(cm) { testCM("change_removedText", function(cm) { cm.setValue("abc\ndef"); - var removedText; + var removedText = []; cm.on("change", function(cm, change) { - removedText = [change.removed, change.next && change.next.removed]; + removedText.push(change.removed); }); cm.operation(function() { @@ -1613,14 +1613,19 @@ testCM("change_removedText", function(cm) { cm.replaceRange("123", Pos(0,0)); }); + eq(removedText.length, 2); eq(removedText[0].join("\n"), "abc\nd"); eq(removedText[1].join("\n"), ""); + var removedText = []; cm.undo(); + eq(removedText.length, 2); eq(removedText[0].join("\n"), "123"); eq(removedText[1].join("\n"), "xyz"); + var removedText = []; cm.redo(); + eq(removedText.length, 2); eq(removedText[0].join("\n"), "abc\nd"); eq(removedText[1].join("\n"), ""); }); From 451c9a83caf1e5f9b1bc2736bf1a1432195df92e Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Wed, 13 Nov 2013 16:27:48 +0100 Subject: [PATCH 0218/4131] Add a v4 upgrade guide --- doc/upgrade_v4.html | 81 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 doc/upgrade_v4.html diff --git a/doc/upgrade_v4.html b/doc/upgrade_v4.html new file mode 100644 index 0000000000..64a838ca26 --- /dev/null +++ b/doc/upgrade_v4.html @@ -0,0 +1,81 @@ + + +CodeMirror: Version 4 upgrade guide + + + + + + +
    + +

    Upgrading to version 4

    + +

    Note: Version 4 hasn't been released yet. The +information here is provisional and might still change.

    + +

    CodeMirror 4's interface is very close version 3, but it +does fix a few awkward details in a backwards-incompatible ways. At +least skim the text below before upgrading.

    + +

    Multiple selections

    + +

    The main new feature in version 4 is multiple selections. The +single-selection variants of methods are still there, but now +typically act only on the primary selection (usually the last +one added).

    + +

    The exception to this +is getSelection, +which will now return the content of all selections +(separated by newlines, or whatever lineSep parameter you passed +it).

    + +
    + +

    The beforeSelectionChange event

    + +

    This event still exists, but the object it is passed has +a completely new +interface, because such changes now concern multiple +selections.

    + +
    + +

    replaceSelection's collapsing behavior

    + +

    By +default, replaceSelection +would leave the newly inserted text selected. This is only rarely what +you want, and also (slightly) more expensive in the new model, so the +default was changed to "end", meaning the old behavior +must be explicitly specified by passing a second argument +of "around".

    + +
    + +

    change event data

    + +

    Rather than forcing client code to follow next +pointers from one change object to the next, the library will now +simply fire +multiple "change" +events. Existing code will probably continue to work unmodified.

    + +
    +
    From 38073cd5ffadd6c19eaac8b46e3094c5238358ee Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Wed, 13 Nov 2013 22:42:09 +0100 Subject: [PATCH 0219/4131] Wrap all modules in AMD and CommonJS-supporting shims --- addon/comment/comment.js | 11 +- addon/comment/continuecomment.js | 11 +- addon/dialog/dialog.js | 11 +- addon/display/fullscreen.js | 11 +- addon/display/placeholder.js | 11 +- addon/edit/closebrackets.js | 11 +- addon/edit/closetag.js | 11 +- addon/edit/continuelist.js | 11 +- addon/edit/matchbrackets.js | 11 +- addon/edit/matchtags.js | 11 +- addon/edit/trailingspace.js | 37 ++++--- addon/fold/brace-fold.js | 15 ++- addon/fold/comment-fold.js | 12 +++ addon/fold/foldcode.js | 11 +- addon/fold/foldgutter.js | 11 +- addon/fold/indent-fold.js | 13 ++- addon/fold/xml-fold.js | 13 ++- addon/hint/anyword-hint.js | 11 +- addon/hint/css-hint.js | 11 +- addon/hint/html-hint.js | 14 ++- addon/hint/javascript-hint.js | 13 ++- addon/hint/pig-hint.js | 12 ++- addon/hint/python-hint.js | 14 ++- addon/hint/show-hint.js | 11 +- addon/hint/sql-hint.js | 11 +- addon/hint/xml-hint.js | 12 ++- addon/lint/coffeescript-lint.js | 13 ++- addon/lint/css-lint.js | 12 +++ addon/lint/javascript-lint.js | 12 ++- addon/lint/json-lint.js | 13 ++- addon/lint/lint.js | 18 ++-- addon/merge/merge.js | 11 +- addon/mode/loadmode.js | 11 +- addon/mode/multiplex.js | 12 +++ addon/mode/overlay.js | 15 ++- addon/runmode/colorize.js | 14 ++- addon/runmode/runmode-standalone.js | 2 - addon/runmode/runmode.js | 12 +++ addon/scroll/scrollpastend.js | 11 +- addon/search/match-highlighter.js | 13 ++- addon/search/search.js | 11 +- addon/search/searchcursor.js | 12 ++- addon/selection/active-line.js | 11 +- addon/selection/mark-selection.js | 11 +- addon/tern/tern.js | 11 +- addon/wrap/hardwrap.js | 11 +- demo/btree.html | 1 - doc/compress.html | 3 +- doc/manual.html | 39 ++++++- doc/upgrade_v4.html | 16 +++ keymap/emacs.js | 11 +- keymap/multiselect.js | 11 +- keymap/vim.js | 12 ++- lib/codemirror.js | 13 ++- mode/apl/apl.js | 12 +++ mode/asterisk/asterisk.js | 12 +++ mode/clike/clike.js | 12 +++ mode/clojure/clojure.js | 13 +++ mode/cobol/cobol.js | 12 +++ mode/coffeescript/coffeescript.js | 12 +++ mode/commonlisp/commonlisp.js | 12 +++ mode/css/css.js | 16 ++- mode/d/d.js | 14 ++- mode/diff/diff.js | 12 +++ mode/dtd/dtd.js | 12 +++ mode/ecl/ecl.js | 12 +++ mode/eiffel/eiffel.js | 12 +++ mode/erlang/erlang.js | 12 +++ mode/fortran/fortran.js | 12 +++ mode/gas/gas.js | 12 +++ mode/gfm/gfm.js | 12 +++ mode/gherkin/gherkin.js | 12 +++ mode/go/go.js | 12 +++ mode/groovy/groovy.js | 12 +++ mode/haml/haml.js | 12 +++ mode/haskell/haskell.js | 12 +++ mode/haxe/haxe.js | 12 +++ mode/htmlembedded/htmlembedded.js | 12 +++ mode/htmlmixed/htmlmixed.js | 12 +++ mode/http/http.js | 12 +++ mode/index.html | 2 +- mode/jade/jade.js | 12 +++ mode/javascript/javascript.js | 12 +++ mode/jinja2/jinja2.js | 67 +++++++----- mode/julia/julia.js | 12 +++ mode/less/less.js | 12 +++ mode/livescript/livescript.js | 13 +++ mode/lua/lua.js | 12 +++ mode/markdown/markdown.js | 12 +++ mode/mirc/mirc.js | 13 +++ mode/mllike/mllike.js | 13 ++- mode/nginx/nginx.js | 12 +++ mode/ntriples/ntriples.js | 13 +++ mode/octave/octave.js | 12 +++ mode/pascal/pascal.js | 12 +++ mode/pegjs/pegjs.js | 12 +++ mode/perl/perl.js | 157 +++++++++++++++------------- mode/php/php.js | 13 ++- mode/pig/pig.js | 12 +++ mode/properties/properties.js | 12 +++ mode/python/python.js | 32 ++++-- mode/q/q.js | 12 +++ mode/r/r.js | 12 +++ mode/rpm/changes/changes.js | 19 ---- mode/rpm/changes/index.html | 67 ------------ mode/rpm/{spec => }/index.html | 68 +++++++++--- mode/rpm/{spec/spec.js => rpm.js} | 36 ++++++- mode/rpm/spec/spec.css | 5 - mode/rst/rst.js | 12 +++ mode/ruby/ruby.js | 11 ++ mode/rust/rust.js | 12 +++ mode/sass/sass.js | 12 +++ mode/scheme/scheme.js | 13 +++ mode/shell/shell.js | 12 +++ mode/sieve/sieve.js | 15 ++- mode/smalltalk/smalltalk.js | 12 +++ mode/smarty/smarty.js | 13 +++ mode/smartymixed/smartymixed.js | 16 ++- mode/sparql/sparql.js | 12 +++ mode/sql/sql.js | 12 +++ mode/stex/stex.js | 12 +++ mode/tcl/tcl.js | 13 +++ mode/tiddlywiki/tiddlywiki.js | 13 +++ mode/tiki/tiki.js | 12 +++ mode/toml/toml.js | 12 +++ mode/turtle/turtle.js | 12 +++ mode/vb/vb.js | 12 +++ mode/vbscript/vbscript.js | 13 +++ mode/velocity/velocity.js | 12 +++ mode/verilog/verilog.js | 14 ++- mode/xml/xml.js | 12 +++ mode/xquery/xquery.js | 12 +++ mode/yaml/yaml.js | 12 +++ mode/z80/z80.js | 12 +++ 134 files changed, 1640 insertions(+), 363 deletions(-) delete mode 100644 mode/rpm/changes/changes.js delete mode 100644 mode/rpm/changes/index.html rename mode/rpm/{spec => }/index.html (60%) rename mode/rpm/{spec/spec.js => rpm.js} (70%) delete mode 100644 mode/rpm/spec/spec.css diff --git a/addon/comment/comment.js b/addon/comment/comment.js index c36e176912..1eb9a05c5d 100644 --- a/addon/comment/comment.js +++ b/addon/comment/comment.js @@ -1,4 +1,11 @@ -(function() { +(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"; var noOptions = {}; @@ -159,4 +166,4 @@ }); return true; }); -})(); +}); diff --git a/addon/comment/continuecomment.js b/addon/comment/continuecomment.js index 0566c74e43..6db3b0a2b9 100644 --- a/addon/comment/continuecomment.js +++ b/addon/comment/continuecomment.js @@ -1,4 +1,11 @@ -(function() { +(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) { var modes = ["clike", "css", "javascript"]; for (var i = 0; i < modes.length; ++i) CodeMirror.extendMode(modes[i], {blockCommentContinue: " * "}); @@ -59,4 +66,4 @@ cm.addKeyMap(map); } }); -})(); +}); diff --git a/addon/dialog/dialog.js b/addon/dialog/dialog.js index 41d7bf8663..2c26542045 100644 --- a/addon/dialog/dialog.js +++ b/addon/dialog/dialog.js @@ -1,6 +1,13 @@ // Open simple dialogs on top of an editor. Relies on dialog.css. -(function() { +(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) { function dialogDiv(cm, template, bottom) { var wrap = cm.getWrapperElement(); var dialog; @@ -119,4 +126,4 @@ if (duration) doneTimer = setTimeout(close, options.duration); }); -})(); +}); diff --git a/addon/display/fullscreen.js b/addon/display/fullscreen.js index a442f6a433..e39c6e162f 100644 --- a/addon/display/fullscreen.js +++ b/addon/display/fullscreen.js @@ -1,4 +1,11 @@ -(function() { +(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.defineOption("fullScreen", false, function(cm, val, old) { @@ -28,4 +35,4 @@ window.scrollTo(info.scrollLeft, info.scrollTop); cm.refresh(); } -})(); +}); diff --git a/addon/display/placeholder.js b/addon/display/placeholder.js index 748afe7275..0fdc9b0d5b 100644 --- a/addon/display/placeholder.js +++ b/addon/display/placeholder.js @@ -1,4 +1,11 @@ -(function() { +(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) { CodeMirror.defineOption("placeholder", "", function(cm, val, old) { var prev = old && old != CodeMirror.Init; if (val && !prev) { @@ -45,4 +52,4 @@ function isEmpty(cm) { return (cm.lineCount() === 1) && (cm.getLine(0) === ""); } -})(); +}); diff --git a/addon/edit/closebrackets.js b/addon/edit/closebrackets.js index 64c56f9530..84b2fc56f1 100644 --- a/addon/edit/closebrackets.js +++ b/addon/edit/closebrackets.js @@ -1,4 +1,11 @@ -(function() { +(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) { var DEFAULT_BRACKETS = "()[]{}''\"\""; var DEFAULT_EXPLODE_ON_ENTER = "[]{}"; var SPACE_CHAR_REGEX = /\s/; @@ -112,4 +119,4 @@ }); }; } -})(); +}); diff --git a/addon/edit/closetag.js b/addon/edit/closetag.js index 7047e27738..ac6c2fc6d4 100644 --- a/addon/edit/closetag.js +++ b/addon/edit/closetag.js @@ -22,7 +22,14 @@ * See demos/closetag.html for a usage example. */ -(function() { +(function(mod) { + if (typeof exports == "object" && typeof module == "object") // CommonJS + mod(require("../../lib/codemirror"), require("../fold/xml-fold")); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror", "../fold/xml-fold"], mod); + else // Plain browser env + mod(CodeMirror); +})(function(CodeMirror) { CodeMirror.defineOption("autoCloseTags", false, function(cm, val, old) { if (old != CodeMirror.Init && old) cm.removeKeyMap("autoCloseTags"); @@ -106,4 +113,4 @@ if (collection[i] == elt) return i; return -1; } -})(); +}); diff --git a/addon/edit/continuelist.js b/addon/edit/continuelist.js index a038345b4b..54c7340bbe 100644 --- a/addon/edit/continuelist.js +++ b/addon/edit/continuelist.js @@ -1,4 +1,11 @@ -(function() { +(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"; var listRE = /^(\s*)([*+-]|(\d+)\.)(\s*)/, @@ -25,4 +32,4 @@ cm.replaceSelections(replacements, null, "+insert"); }; -}()); +}); diff --git a/addon/edit/matchbrackets.js b/addon/edit/matchbrackets.js index 4d0c853a52..dcdee7516b 100644 --- a/addon/edit/matchbrackets.js +++ b/addon/edit/matchbrackets.js @@ -1,4 +1,11 @@ -(function() { +(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) { var ie_lt8 = /MSIE \d/.test(navigator.userAgent) && (document.documentMode == null || document.documentMode < 8); @@ -93,4 +100,4 @@ CodeMirror.defineExtension("findMatchingBracket", function(pos, strict){ return findMatchingBracket(this, pos, strict); }); -})(); +}); diff --git a/addon/edit/matchtags.js b/addon/edit/matchtags.js index f189c1f8ef..2b7d22ed84 100644 --- a/addon/edit/matchtags.js +++ b/addon/edit/matchtags.js @@ -1,4 +1,11 @@ -(function() { +(function(mod) { + if (typeof exports == "object" && typeof module == "object") // CommonJS + mod(require("../../lib/codemirror"), require("../fold/xml-fold")); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror", "../fold/xml-fold"], mod); + else // Plain browser env + mod(CodeMirror); +})(function(CodeMirror) { "use strict"; CodeMirror.defineOption("matchTags", false, function(cm, val, old) { @@ -53,4 +60,4 @@ if (other) cm.setSelection(other.to, other.from); } }; -})(); +}); diff --git a/addon/edit/trailingspace.js b/addon/edit/trailingspace.js index f6bb02645d..ec07221e30 100644 --- a/addon/edit/trailingspace.js +++ b/addon/edit/trailingspace.js @@ -1,15 +1,24 @@ -CodeMirror.defineOption("showTrailingSpace", false, function(cm, val, prev) { - if (prev == CodeMirror.Init) prev = false; - if (prev && !val) - cm.removeOverlay("trailingspace"); - else if (!prev && val) - cm.addOverlay({ - token: function(stream) { - for (var l = stream.string.length, i = l; i && /\s/.test(stream.string.charAt(i - 1)); --i) {} - if (i > stream.pos) { stream.pos = i; return null; } - stream.pos = l; - return "trailingspace"; - }, - name: "trailingspace" - }); +(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) { + CodeMirror.defineOption("showTrailingSpace", false, function(cm, val, prev) { + if (prev == CodeMirror.Init) prev = false; + if (prev && !val) + cm.removeOverlay("trailingspace"); + else if (!prev && val) + cm.addOverlay({ + token: function(stream) { + for (var l = stream.string.length, i = l; i && /\s/.test(stream.string.charAt(i - 1)); --i) {} + if (i > stream.pos) { stream.pos = i; return null; } + stream.pos = l; + return "trailingspace"; + }, + name: "trailingspace" + }); + }); }); diff --git a/addon/fold/brace-fold.js b/addon/fold/brace-fold.js index 2560b2b94c..f0ee62029a 100644 --- a/addon/fold/brace-fold.js +++ b/addon/fold/brace-fold.js @@ -1,3 +1,13 @@ +(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.registerHelper("fold", "brace", function(cm, start) { var line = start.line, lineText = cm.getLine(line); var startCh, tokenType; @@ -45,7 +55,6 @@ CodeMirror.registerHelper("fold", "brace", function(cm, start) { return {from: CodeMirror.Pos(line, startCh), to: CodeMirror.Pos(end, endCh)}; }); -CodeMirror.braceRangeFinder = CodeMirror.fold.brace; // deprecated CodeMirror.registerHelper("fold", "import", function(cm, start) { function hasImport(line) { @@ -70,7 +79,6 @@ CodeMirror.registerHelper("fold", "import", function(cm, start) { } return {from: cm.clipPos(CodeMirror.Pos(start, has.startCh + 1)), to: end}; }); -CodeMirror.importRangeFinder = CodeMirror.fold["import"]; // deprecated CodeMirror.registerHelper("fold", "include", function(cm, start) { function hasInclude(line) { @@ -90,4 +98,5 @@ CodeMirror.registerHelper("fold", "include", function(cm, start) { return {from: CodeMirror.Pos(start, has + 1), to: cm.clipPos(CodeMirror.Pos(end))}; }); -CodeMirror.includeRangeFinder = CodeMirror.fold.include; // deprecated + +}); diff --git a/addon/fold/comment-fold.js b/addon/fold/comment-fold.js index 26e72f09f5..d72c5479a7 100644 --- a/addon/fold/comment-fold.js +++ b/addon/fold/comment-fold.js @@ -1,3 +1,13 @@ +(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.registerGlobalHelper("fold", "comment", function(mode) { return mode.blockCommentStart && mode.blockCommentEnd; }, function(cm, start) { @@ -40,3 +50,5 @@ CodeMirror.registerGlobalHelper("fold", "comment", function(mode) { return {from: CodeMirror.Pos(line, startCh), to: CodeMirror.Pos(end, endCh)}; }); + +}); diff --git a/addon/fold/foldcode.js b/addon/fold/foldcode.js index 5c00d7093c..4627c81f9d 100644 --- a/addon/fold/foldcode.js +++ b/addon/fold/foldcode.js @@ -1,4 +1,11 @@ -(function() { +(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"; function doFold(cm, pos, options, force) { @@ -83,4 +90,4 @@ if (cur) return cur; } }); -})(); +}); diff --git a/addon/fold/foldgutter.js b/addon/fold/foldgutter.js index a4f3bb3186..9caba59aad 100644 --- a/addon/fold/foldgutter.js +++ b/addon/fold/foldgutter.js @@ -1,4 +1,11 @@ -(function() { +(function(mod) { + if (typeof exports == "object" && typeof module == "object") // CommonJS + mod(require("../../lib/codemirror"), require("./foldcode")); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror", "./foldcode"], mod); + else // Plain browser env + mod(CodeMirror); +})(function(CodeMirror) { "use strict"; CodeMirror.defineOption("foldGutter", false, function(cm, val, old) { @@ -121,4 +128,4 @@ if (line >= state.from && line < state.to) updateFoldInfo(cm, line, line + 1); } -})(); +}); diff --git a/addon/fold/indent-fold.js b/addon/fold/indent-fold.js index 434c2bc5ca..d0130836a2 100644 --- a/addon/fold/indent-fold.js +++ b/addon/fold/indent-fold.js @@ -1,3 +1,13 @@ +(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.registerHelper("fold", "indent", function(cm, start) { var tabSize = cm.getOption("tabSize"), firstLine = cm.getLine(start.line); if (!/\S/.test(firstLine)) return; @@ -27,4 +37,5 @@ CodeMirror.registerHelper("fold", "indent", function(cm, start) { to: CodeMirror.Pos(lastLineInFold, cm.getLine(lastLineInFold).length) }; }); -CodeMirror.indentRangeFinder = CodeMirror.fold.indent; // deprecated + +}); diff --git a/addon/fold/xml-fold.js b/addon/fold/xml-fold.js index db5aed7041..d554e2fc42 100644 --- a/addon/fold/xml-fold.js +++ b/addon/fold/xml-fold.js @@ -1,4 +1,11 @@ -(function() { +(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"; var Pos = CodeMirror.Pos; @@ -136,8 +143,6 @@ } } }); - CodeMirror.tagRangeFinder = CodeMirror.fold.xml; // deprecated - CodeMirror.findMatchingTag = function(cm, pos, range) { var iter = new Iter(cm, pos.line, pos.ch, range); if (iter.text.indexOf(">") == -1 && iter.text.indexOf("<") == -1) return; @@ -170,4 +175,4 @@ var iter = new Iter(cm, pos.line, pos.ch, end ? {from: 0, to: end} : null); return !!findMatchingClose(iter, name); }; -})(); +}); diff --git a/addon/hint/anyword-hint.js b/addon/hint/anyword-hint.js index a144768c81..1570664c4f 100644 --- a/addon/hint/anyword-hint.js +++ b/addon/hint/anyword-hint.js @@ -1,4 +1,11 @@ -(function() { +(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"; var WORD = /[\w$]+/, RANGE = 500; @@ -29,4 +36,4 @@ } return {list: list, from: CodeMirror.Pos(cur.line, start), to: CodeMirror.Pos(cur.line, end)}; }); -})(); +}); diff --git a/addon/hint/css-hint.js b/addon/hint/css-hint.js index 6789c458ba..9e5b1e132d 100644 --- a/addon/hint/css-hint.js +++ b/addon/hint/css-hint.js @@ -1,4 +1,11 @@ -(function () { +(function(mod) { + if (typeof exports == "object" && typeof module == "object") // CommonJS + mod(require("../../lib/codemirror"), require("../../mode/css/css")); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror", "../../mode/css/css"], mod); + else // Plain browser env + mod(CodeMirror); +})(function(CodeMirror) { "use strict"; var pseudoClasses = {link: 1, visited: 1, active: 1, hover: 1, focus: 1, @@ -43,4 +50,4 @@ to: CodeMirror.Pos(cur.line, end) }; }); -})(); +}); diff --git a/addon/hint/html-hint.js b/addon/hint/html-hint.js index cf256851ef..cbe7c61ad4 100755 --- a/addon/hint/html-hint.js +++ b/addon/hint/html-hint.js @@ -1,4 +1,13 @@ -(function () { +(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"; + var langs = "ab aa af ak sq am ar an hy as av ae ay az bm ba eu be bn bh bi bs br bg my ca ch ce ny zh cv kw co cr hr cs da dv nl dz en eo et ee fo fj fi fr ff gl ka de el gn gu ht ha he hz hi ho hu ia id ie ga ig ik io is it iu ja jv kl kn kr ks kk km ki rw ky kv kg ko ku kj la lb lg li ln lo lt lu lv gv mk mg ms ml mt mi mr mh mn na nv nb nd ne ng nn no ii nr oc oj cu om or os pa pi fa pl ps pt qu rm rn ro ru sa sc sd se sm sg sr gd sn si sk sl so st es su sw ss sv ta te tg th ti bo tk tl tn to tr ts tt tw ty ug uk ur uz ve vi vo wa cy wo fy xh yi yo za zu".split(" "); var targets = ["_blank", "_self", "_top", "_parent"]; var charsets = ["ascii", "utf-8", "utf-16", "latin1", "latin1"]; @@ -332,6 +341,5 @@ if (options) for (var opt in options) local[opt] = options[opt]; return CodeMirror.hint.xml(cm, local); } - CodeMirror.htmlHint = htmlHint; // deprecated CodeMirror.registerHelper("hint", "html", htmlHint); -})(); +}); diff --git a/addon/hint/javascript-hint.js b/addon/hint/javascript-hint.js index c347c206ec..305bb85a29 100644 --- a/addon/hint/javascript-hint.js +++ b/addon/hint/javascript-hint.js @@ -1,4 +1,11 @@ -(function () { +(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) { var Pos = CodeMirror.Pos; function forEach(arr, f) { @@ -47,7 +54,6 @@ function (e, cur) {return e.getTokenAt(cur);}, options); }; - CodeMirror.javascriptHint = javascriptHint; // deprecated CodeMirror.registerHelper("hint", "javascript", javascriptHint); function getCoffeeScriptToken(editor, cur) { @@ -71,7 +77,6 @@ function coffeescriptHint(editor, options) { return scriptHint(editor, coffeescriptKeywords, getCoffeeScriptToken, options); } - CodeMirror.coffeescriptHint = coffeescriptHint; // deprecated CodeMirror.registerHelper("hint", "coffeescript", coffeescriptHint); var stringProps = ("charAt charCodeAt indexOf lastIndexOf substring substr slice trim trimLeft trimRight " + @@ -128,4 +133,4 @@ } return found; } -})(); +}); diff --git a/addon/hint/pig-hint.js b/addon/hint/pig-hint.js index 6c0c523774..02342f0246 100644 --- a/addon/hint/pig-hint.js +++ b/addon/hint/pig-hint.js @@ -1,4 +1,11 @@ -(function () { +(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"; function forEach(arr, f) { @@ -46,7 +53,6 @@ function pigHint(editor) { return scriptHint(editor, pigKeywordsU, function (e, cur) {return e.getTokenAt(cur);}); } - CodeMirror.pigHint = pigHint; // deprecated CodeMirror.registerHelper("hint", "pig", pigHint); var pigKeywords = "VOID IMPORT RETURNS DEFINE LOAD FILTER FOREACH ORDER CUBE DISTINCT COGROUP " @@ -118,4 +124,4 @@ } return found; } -})(); +}); diff --git a/addon/hint/python-hint.js b/addon/hint/python-hint.js index 248284e8c5..eebfcc76dc 100644 --- a/addon/hint/python-hint.js +++ b/addon/hint/python-hint.js @@ -1,4 +1,13 @@ -(function () { +(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"; + function forEach(arr, f) { for (var i = 0, e = arr.length; i < e; ++i) f(arr[i]); } @@ -40,7 +49,6 @@ function pythonHint(editor) { return scriptHint(editor, pythonKeywordsU, function (e, cur) {return e.getTokenAt(cur);}); } - CodeMirror.pythonHint = pythonHint; // deprecated CodeMirror.registerHelper("hint", "python", pythonHint); var pythonKeywords = "and del from not while as elif global or with assert else if pass yield" @@ -88,4 +96,4 @@ } return found; } -})(); +}); diff --git a/addon/hint/show-hint.js b/addon/hint/show-hint.js index 831fe089da..6a4d74e360 100644 --- a/addon/hint/show-hint.js +++ b/addon/hint/show-hint.js @@ -1,4 +1,11 @@ -(function() { +(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"; var HINT_ELEMENT_CLASS = "CodeMirror-hint"; @@ -332,4 +339,4 @@ }); CodeMirror.commands.autocomplete = CodeMirror.showHint; -})(); +}); diff --git a/addon/hint/sql-hint.js b/addon/hint/sql-hint.js index d00781cff9..736dbaea06 100644 --- a/addon/hint/sql-hint.js +++ b/addon/hint/sql-hint.js @@ -1,4 +1,11 @@ -(function () { +(function(mod) { + if (typeof exports == "object" && typeof module == "object") // CommonJS + mod(require("../../lib/codemirror"), require("../../mode/sql/sql")); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror", "../../mode/sql/sql"], mod); + else // Plain browser env + mod(CodeMirror); +})(function(CodeMirror) { "use strict"; var tables; @@ -143,4 +150,4 @@ }; } CodeMirror.registerHelper("hint", "sql", sqlHint); -})(); +}); diff --git a/addon/hint/xml-hint.js b/addon/hint/xml-hint.js index 69f2b771fe..857564909a 100644 --- a/addon/hint/xml-hint.js +++ b/addon/hint/xml-hint.js @@ -1,4 +1,11 @@ -(function() { +(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"; var Pos = CodeMirror.Pos; @@ -64,6 +71,5 @@ }; } - CodeMirror.xmlHint = getHints; // deprecated CodeMirror.registerHelper("hint", "xml", getHints); -})(); +}); diff --git a/addon/lint/coffeescript-lint.js b/addon/lint/coffeescript-lint.js index 7f55a294dd..6df17f8f84 100644 --- a/addon/lint/coffeescript-lint.js +++ b/addon/lint/coffeescript-lint.js @@ -2,6 +2,16 @@ // declare global: coffeelint +(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.registerHelper("lint", "coffeescript", function(text) { var found = []; var parseError = function(err) { @@ -24,4 +34,5 @@ CodeMirror.registerHelper("lint", "coffeescript", function(text) { } return found; }); -CodeMirror.coffeeValidator = CodeMirror.lint.coffeescript; // deprecated + +}); diff --git a/addon/lint/css-lint.js b/addon/lint/css-lint.js index 1de71fbcbd..2a799ddc4f 100644 --- a/addon/lint/css-lint.js +++ b/addon/lint/css-lint.js @@ -2,6 +2,16 @@ // declare global: CSSLint +(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.registerHelper("lint", "css", function(text) { var found = []; var results = CSSLint.verify(text), messages = results.messages, message = null; @@ -17,3 +27,5 @@ CodeMirror.registerHelper("lint", "css", function(text) { } return found; }); + +}); diff --git a/addon/lint/javascript-lint.js b/addon/lint/javascript-lint.js index 7123ab7e64..bbb51083b8 100644 --- a/addon/lint/javascript-lint.js +++ b/addon/lint/javascript-lint.js @@ -1,4 +1,11 @@ -(function() { +(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"; // declare global: JSHINT @@ -19,7 +26,6 @@ } CodeMirror.registerHelper("lint", "javascript", validator); - CodeMirror.javascriptValidator = CodeMirror.lint.javascript; // deprecated function cleanup(error) { // All problems are warnings by default @@ -123,4 +129,4 @@ } } } -})(); +}); diff --git a/addon/lint/json-lint.js b/addon/lint/json-lint.js index e10e11bcaf..1f5f82d0ca 100644 --- a/addon/lint/json-lint.js +++ b/addon/lint/json-lint.js @@ -2,6 +2,16 @@ // declare global: jsonlint +(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.registerHelper("lint", "json", function(text) { var found = []; jsonlint.parseError = function(str, hash) { @@ -14,4 +24,5 @@ CodeMirror.registerHelper("lint", "json", function(text) { catch(e) {} return found; }); -CodeMirror.jsonValidator = CodeMirror.lint.json; // deprecated + +}); diff --git a/addon/lint/lint.js b/addon/lint/lint.js index 6121735d3f..db5162ee7a 100644 --- a/addon/lint/lint.js +++ b/addon/lint/lint.js @@ -1,4 +1,11 @@ -(function() { +(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"; var GUTTER_ID = "CodeMirror-lint-markers"; var SEVERITIES = /^(?:error|warning)$/; @@ -178,7 +185,7 @@ } } - function optionHandler(cm, val, old) { + CodeMirror.defineOption("lint", false, function(cm, val, old) { if (old && old != CodeMirror.Init) { clearMarks(cm); cm.off("change", onChange); @@ -196,8 +203,5 @@ startLinting(cm); } - } - - CodeMirror.defineOption("lintWith", false, optionHandler); // deprecated - CodeMirror.defineOption("lint", false, optionHandler); // deprecated -})(); + }); +}); diff --git a/addon/merge/merge.js b/addon/merge/merge.js index 89f852652b..99e5d075ba 100644 --- a/addon/merge/merge.js +++ b/addon/merge/merge.js @@ -1,4 +1,11 @@ -(function() { +(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"; // declare global: diff_match_patch, DIFF_INSERT, DIFF_DELETE, DIFF_EQUAL @@ -476,4 +483,4 @@ function posMin(a, b) { return (a.line - b.line || a.ch - b.ch) < 0 ? a : b; } function posMax(a, b) { return (a.line - b.line || a.ch - b.ch) > 0 ? a : b; } function posEq(a, b) { return a.line == b.line && a.ch == b.ch; } -})(); +}); diff --git a/addon/mode/loadmode.js b/addon/mode/loadmode.js index 60fafbb178..e08c281321 100644 --- a/addon/mode/loadmode.js +++ b/addon/mode/loadmode.js @@ -1,4 +1,11 @@ -(function() { +(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) { if (!CodeMirror.modeURL) CodeMirror.modeURL = "../mode/%N/%N.js"; var loading = {}; @@ -48,4 +55,4 @@ instance.setOption("mode", instance.getOption("mode")); }); }; -}()); +}); diff --git a/addon/mode/multiplex.js b/addon/mode/multiplex.js index 614ab1add3..07385c35f2 100644 --- a/addon/mode/multiplex.js +++ b/addon/mode/multiplex.js @@ -1,3 +1,13 @@ +(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.multiplexingMode = function(outer /*, others */) { // Others should be {open, close, mode [, delimStyle] [, innerStyle]} objects var others = Array.prototype.slice.call(arguments, 1); @@ -101,3 +111,5 @@ CodeMirror.multiplexingMode = function(outer /*, others */) { } }; }; + +}); diff --git a/addon/mode/overlay.js b/addon/mode/overlay.js index b7928a7bbf..6f556a13a7 100644 --- a/addon/mode/overlay.js +++ b/addon/mode/overlay.js @@ -6,8 +6,17 @@ // overlay wins, unless the combine argument was true, in which case // the styles are combined. -// overlayParser is the old, deprecated name -CodeMirror.overlayMode = CodeMirror.overlayParser = function(base, overlay, combine) { +(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.overlayMode = function(base, overlay, combine) { return { startState: function() { return { @@ -57,3 +66,5 @@ CodeMirror.overlayMode = CodeMirror.overlayParser = function(base, overlay, comb } }; }; + +}); diff --git a/addon/runmode/colorize.js b/addon/runmode/colorize.js index 62286d21e4..0f9530b17b 100644 --- a/addon/runmode/colorize.js +++ b/addon/runmode/colorize.js @@ -1,4 +1,12 @@ -CodeMirror.colorize = (function() { +(function(mod) { + if (typeof exports == "object" && typeof module == "object") // CommonJS + mod(require("../../lib/codemirror"), require("./runmode")); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror", "./runmode"], mod); + else // Plain browser env + mod(CodeMirror); +})(function(CodeMirror) { + "use strict"; var isBlock = /^(p|li|div|h\\d|pre|blockquote|td)$/; @@ -10,7 +18,7 @@ CodeMirror.colorize = (function() { } } - return function(collection, defaultMode) { + CodeMirror.colorize = function(collection, defaultMode) { if (!collection) collection = document.body.getElementsByTagName("pre"); for (var i = 0; i < collection.length; ++i) { @@ -26,4 +34,4 @@ CodeMirror.colorize = (function() { node.className += " cm-s-default"; } }; -})(); +}); diff --git a/addon/runmode/runmode-standalone.js b/addon/runmode/runmode-standalone.js index ec06ba11cb..eaa2b8f2fb 100644 --- a/addon/runmode/runmode-standalone.js +++ b/addon/runmode/runmode-standalone.js @@ -1,5 +1,3 @@ -/* Just enough of CodeMirror to run runMode under node.js */ - window.CodeMirror = {}; (function() { diff --git a/addon/runmode/runmode.js b/addon/runmode/runmode.js index 2cafa811f8..351840e08e 100644 --- a/addon/runmode/runmode.js +++ b/addon/runmode/runmode.js @@ -1,3 +1,13 @@ +(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.runMode = function(string, modespec, callback, options) { var mode = CodeMirror.getMode(CodeMirror.defaults, modespec); var ie = /MSIE \d/.test(navigator.userAgent); @@ -54,3 +64,5 @@ CodeMirror.runMode = function(string, modespec, callback, options) { } } }; + +}); diff --git a/addon/scroll/scrollpastend.js b/addon/scroll/scrollpastend.js index 58720ad413..467b7aa1cf 100644 --- a/addon/scroll/scrollpastend.js +++ b/addon/scroll/scrollpastend.js @@ -1,4 +1,11 @@ -(function() { +(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.defineOption("scrollPastEnd", false, function(cm, val, old) { @@ -33,4 +40,4 @@ cm.setSize(); } } -})(); +}); diff --git a/addon/search/match-highlighter.js b/addon/search/match-highlighter.js index a2eda2e614..d9c818b838 100644 --- a/addon/search/match-highlighter.js +++ b/addon/search/match-highlighter.js @@ -12,7 +12,16 @@ // actual CSS class name. showToken, when enabled, will cause the // current token to be highlighted when nothing is selected. -(function() { +(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"; + var DEFAULT_MIN_CHARS = 2; var DEFAULT_TOKEN_STYLE = "matchhighlight"; var DEFAULT_DELAY = 100; @@ -88,4 +97,4 @@ stream.skipTo(query.charAt(0)) || stream.skipToEnd(); }}; } -})(); +}); diff --git a/addon/search/search.js b/addon/search/search.js index 38b488522f..3df006d4b7 100644 --- a/addon/search/search.js +++ b/addon/search/search.js @@ -6,7 +6,14 @@ // replace by making sure the match is no longer selected when hitting // Ctrl-G. -(function() { +(function(mod) { + if (typeof exports == "object" && typeof module == "object") // CommonJS + mod(require("../../lib/codemirror"), require("./searchcursor"), require("../dialog/dialog")); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror", "./searchcursor", "../dialog/dialog"], mod); + else // Plain browser env + mod(CodeMirror); +})(function(CodeMirror) { "use strict"; function searchOverlay(query, caseInsensitive) { var startChar; @@ -139,4 +146,4 @@ CodeMirror.commands.clearSearch = clearSearch; CodeMirror.commands.replace = replace; CodeMirror.commands.replaceAll = function(cm) {replace(cm, true);}; -})(); +}); diff --git a/addon/search/searchcursor.js b/addon/search/searchcursor.js index 6afac80fb8..899f44c4ab 100644 --- a/addon/search/searchcursor.js +++ b/addon/search/searchcursor.js @@ -1,4 +1,12 @@ -(function(){ +(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"; var Pos = CodeMirror.Pos; function SearchCursor(doc, query, pos, caseFold) { @@ -175,4 +183,4 @@ if (ranges.length) this.setSelections(ranges, 0); }); -})(); +}); diff --git a/addon/selection/active-line.js b/addon/selection/active-line.js index c8b7001ced..a818f109b6 100644 --- a/addon/selection/active-line.js +++ b/addon/selection/active-line.js @@ -4,7 +4,14 @@ // active line's wrapping
    the CSS class "CodeMirror-activeline", // and gives its background
    the class "CodeMirror-activeline-background". -(function() { +(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"; var WRAP_CLASS = "CodeMirror-activeline"; var BACK_CLASS = "CodeMirror-activeline-background"; @@ -56,4 +63,4 @@ function selectionChange(cm, sel) { updateActiveLines(cm, sel.ranges); } -})(); +}); diff --git a/addon/selection/mark-selection.js b/addon/selection/mark-selection.js index c40a9c99bd..ae0d393143 100644 --- a/addon/selection/mark-selection.js +++ b/addon/selection/mark-selection.js @@ -4,7 +4,14 @@ // selected text the CSS class given as option value, or // "CodeMirror-selectedtext" when the value is not a string. -(function() { +(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.defineOption("styleSelectedText", false, function(cm, val, old) { @@ -105,4 +112,4 @@ } } } -})(); +}); diff --git a/addon/tern/tern.js b/addon/tern/tern.js index fa2a2c3528..1cc7e972e5 100644 --- a/addon/tern/tern.js +++ b/addon/tern/tern.js @@ -40,7 +40,14 @@ // load. Or, if you minified those into a single script and included // them in the workerScript, simply leave this undefined. -(function() { +(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"; // declare global: tern @@ -650,4 +657,4 @@ this.delFile = function(name) { send({type: "del", name: name}); }; this.request = function(body, c) { send({type: "req", body: body}, c); }; } -})(); +}); diff --git a/addon/wrap/hardwrap.js b/addon/wrap/hardwrap.js index f6d99212a8..f900d6e81b 100644 --- a/addon/wrap/hardwrap.js +++ b/addon/wrap/hardwrap.js @@ -1,4 +1,11 @@ -(function() { +(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"; var Pos = CodeMirror.Pos; @@ -108,4 +115,4 @@ }); return madeChange; }); -})(); +}); diff --git a/demo/btree.html b/demo/btree.html index 7635ca1bb4..b7bd39088d 100644 --- a/demo/btree.html +++ b/demo/btree.html @@ -58,7 +58,6 @@

    B-Tree visualization

    var gray = Math.min(line.text.length * 3, 230), col = gray.toString(16); if (col.length == 1) col = "0" + col; lineElt.style.background = "#" + col + col + col; - console.log(line.height, line); lineElt.style.width = Math.max(Math.round(line.height / 3), 1) + "px"; } } else { diff --git a/doc/compress.html b/doc/compress.html index 55e25f3e68..d4c108c516 100644 --- a/doc/compress.html +++ b/doc/compress.html @@ -128,8 +128,7 @@

    Script compression helper

    - - + diff --git a/doc/manual.html b/doc/manual.html index 3e81b94c3a..9a2424eb48 100644 --- a/doc/manual.html +++ b/doc/manual.html @@ -91,6 +91,9 @@

    Basic Usage

    <link rel="stylesheet" href="../lib/codemirror.css"> <script src="mode/javascript/javascript.js"></script> +

    (Alternatively, use a module loader. More + about that later.)

    +

    Having done this, an editor instance can be created like this:

    @@ -135,7 +138,41 @@

    Basic Usage

    of a form) is submitted. See the API reference for a full description of this method.

    +

    Module loaders

    + +

    The files in the CodeMirror distribution contain shims for + loading them (and their dependencies) in AMD or CommonJS + environments. If the variables exports + and module exist and have type object, CommonJS-style + require will be used. If not, but there is a + function define with an amd property + present, AMD-style (RequireJS) will be used.

    + +

    It is possible to + use Browserify or similar + tools to statically build modules using CodeMirror. Alternatively, + use RequireJS to dynamically + load dependencies at runtime. Both of these approaches have the + advantage that they don't use the global namespace and can, thus, + do things like load multiple versions of CodeMirror alongside each + other.

    + +

    Here's a simple example of using RequireJS to load CodeMirror:

    + +
    require([
    +  "cm/lib/codemirror", "cm/mode/htmlmixed/htmlmixed"
    +], function(CodeMirror) {
    +  CodeMirror.fromTextArea(document.getElementById("code"), {
    +    lineNumbers: true,
    +    mode: "htmlmixed"
    +  });
    +});
    + +

    It will automatically load the modes that the mixed HTML mode + depends on (XML, JavaScript, and CSS).

    + +

    Configuration

    @@ -2168,7 +2205,7 @@

    Addons

    "close" ()
    Fired when the completion is finished.
    - This addon depends styles + This addon depends on styles from addon/hint/show-hint.css. Check out the demo for an example. diff --git a/doc/upgrade_v4.html b/doc/upgrade_v4.html index 64a838ca26..d390228682 100644 --- a/doc/upgrade_v4.html +++ b/doc/upgrade_v4.html @@ -19,6 +19,7 @@
  • The beforeSelectionChange event
  • replaceSelection and collapsing
  • change event data +
  • Deprecated interfaces dropped @@ -77,5 +78,20 @@

    Upgrading to version 4

    multiple "change" events. Existing code will probably continue to work unmodified.

    + + +

    Deprecated interfaces dropped

    + +

    A few properties that have been deprecated for a while are now +gone. Most notably, the names for folding and completing functions +(CodeMirror.braceRangeFinder, CodeMirror.javascriptHint, +etc) are now gone +(use CodeMirror.fold.brace, CodeMirror.hint.javascript).

    + +

    The className property in the return value +of getTokenAt, which +has been superseded by the type property, is also no +longer present.

    +
    diff --git a/keymap/emacs.js b/keymap/emacs.js index c56d7eb7e7..35f199cb73 100644 --- a/keymap/emacs.js +++ b/keymap/emacs.js @@ -1,4 +1,11 @@ -(function() { +(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"; var Pos = CodeMirror.Pos; @@ -395,4 +402,4 @@ } for (var i = 0; i < 10; ++i) regPrefix(String(i)); regPrefix("-"); -})(); +}); diff --git a/keymap/multiselect.js b/keymap/multiselect.js index f45f27254a..46379484a6 100644 --- a/keymap/multiselect.js +++ b/keymap/multiselect.js @@ -1,7 +1,14 @@ // A number of extra keybindings for multiple-selection handling // Depends on addon/search/searchcursor.js and optionally addon/dialog/dialogs.js -(function() { +(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"; var pc = CodeMirror.keyMap.pcDefault, mac = CodeMirror.keyMap.macDefault; @@ -44,4 +51,4 @@ cm.selectMatches(query); }); }; -})(); +}); diff --git a/keymap/vim.js b/keymap/vim.js index 9e5b257f4f..720ef4a2c3 100644 --- a/keymap/vim.js +++ b/keymap/vim.js @@ -56,7 +56,14 @@ * 8. Set up Vim to work as a keymap for CodeMirror. */ -(function() { +(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'; var defaultKeymap = [ @@ -3800,5 +3807,4 @@ }; // Initialize Vim and make it available as an API. CodeMirror.Vim = Vim(); -} -)(); +}); diff --git a/lib/codemirror.js b/lib/codemirror.js index c5a332264f..c4adf99f65 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -1,5 +1,11 @@ -// CodeMirror is the only global var we claim -window.CodeMirror = (function() { +(function(mod) { + if (typeof exports == "object" && typeof module == "object") // CommonJS + module.exports = mod(); + else if (typeof define == "function" && define.amd) // AMD + return define([], mod); + else // Plain browser env + this.CodeMirror = mod(); +})(function() { "use strict"; // BROWSER SNIFFING @@ -3175,7 +3181,6 @@ window.CodeMirror = (function() { return {start: stream.start, end: stream.pos, string: stream.current(), - className: style || null, // Deprecated, use 'type' instead type: style || null, state: state}; }, @@ -6363,4 +6368,4 @@ window.CodeMirror = (function() { CodeMirror.version = "4.0.0"; return CodeMirror; -})(); +}); diff --git a/mode/apl/apl.js b/mode/apl/apl.js index 5c23af85da..2ba74c18c2 100644 --- a/mode/apl/apl.js +++ b/mode/apl/apl.js @@ -1,3 +1,13 @@ +(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.defineMode("apl", function() { var builtInOps = { ".": "innerProduct", @@ -158,3 +168,5 @@ CodeMirror.defineMode("apl", function() { }); CodeMirror.defineMIME("text/apl", "apl"); + +}); diff --git a/mode/asterisk/asterisk.js b/mode/asterisk/asterisk.js index 60b689d1d5..c56fc0b38a 100644 --- a/mode/asterisk/asterisk.js +++ b/mode/asterisk/asterisk.js @@ -14,6 +14,16 @@ * ===================================================================================== */ +(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.defineMode("asterisk", function() { var atoms = ["exten", "same", "include","ignorepat","switch"], dpcmd = ["#include","#exec"], @@ -181,3 +191,5 @@ CodeMirror.defineMode("asterisk", function() { }); CodeMirror.defineMIME("text/x-asterisk", "asterisk"); + +}); diff --git a/mode/clike/clike.js b/mode/clike/clike.js index 4e4988dd81..b869f72723 100644 --- a/mode/clike/clike.js +++ b/mode/clike/clike.js @@ -1,3 +1,13 @@ +(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.defineMode("clike", function(config, parserConfig) { var indentUnit = config.indentUnit, statementIndentUnit = parserConfig.statementIndentUnit || indentUnit, @@ -379,3 +389,5 @@ CodeMirror.defineMode("clike", function(config, parserConfig) { modeProps: {fold: ["brace", "include"]} }); }()); + +}); diff --git a/mode/clojure/clojure.js b/mode/clojure/clojure.js index e3d87d23a6..dd2e2ce1b8 100644 --- a/mode/clojure/clojure.js +++ b/mode/clojure/clojure.js @@ -2,6 +2,17 @@ * Author: Hans Engel * Branched from CodeMirror's Scheme mode (by Koh Zi Han, based on implementation by Koh Zi Chun) */ + +(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.defineMode("clojure", function (options) { var BUILTIN = "builtin", COMMENT = "comment", STRING = "string", CHARACTER = "string-2", ATOM = "atom", NUMBER = "number", BRACKET = "bracket", KEYWORD = "keyword"; @@ -223,3 +234,5 @@ CodeMirror.defineMode("clojure", function (options) { }); CodeMirror.defineMIME("text/x-clojure", "clojure"); + +}); diff --git a/mode/cobol/cobol.js b/mode/cobol/cobol.js index d92491dde8..e66e42a191 100644 --- a/mode/cobol/cobol.js +++ b/mode/cobol/cobol.js @@ -2,6 +2,16 @@ * Author: Gautam Mehta * Branched from CodeMirror's Scheme mode */ +(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.defineMode("cobol", function () { var BUILTIN = "builtin", COMMENT = "comment", STRING = "string", ATOM = "atom", NUMBER = "number", KEYWORD = "keyword", MODTAG = "header", @@ -238,3 +248,5 @@ CodeMirror.defineMode("cobol", function () { }); CodeMirror.defineMIME("text/x-cobol", "cobol"); + +}); diff --git a/mode/coffeescript/coffeescript.js b/mode/coffeescript/coffeescript.js index 0e9e6352f8..c6da8f2a29 100644 --- a/mode/coffeescript/coffeescript.js +++ b/mode/coffeescript/coffeescript.js @@ -2,6 +2,16 @@ * Link to the project's GitHub page: * https://github.com/pickhardt/coffeescript-codemirror-mode */ +(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.defineMode("coffeescript", function(conf) { var ERRORCLASS = "error"; @@ -351,3 +361,5 @@ CodeMirror.defineMode("coffeescript", function(conf) { }); CodeMirror.defineMIME("text/x-coffeescript", "coffeescript"); + +}); diff --git a/mode/commonlisp/commonlisp.js b/mode/commonlisp/commonlisp.js index 8fa08c8ac2..a0f0732bf6 100644 --- a/mode/commonlisp/commonlisp.js +++ b/mode/commonlisp/commonlisp.js @@ -1,3 +1,13 @@ +(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.defineMode("commonlisp", function (config) { var assumeBody = /^with|^def|^do|^prog|case$|^cond$|bind$|when$|unless$/; var numLiteral = /^(?:[+\-]?(?:\d+|\d*\.\d+)(?:[efd][+\-]?\d+)?|[+\-]?\d+(?:\/[+\-]?\d+)?|#b[+\-]?[01]+|#o[+\-]?[0-7]+|#x[+\-]?[\da-f]+)/; @@ -103,3 +113,5 @@ CodeMirror.defineMode("commonlisp", function (config) { }); CodeMirror.defineMIME("text/x-common-lisp", "commonlisp"); + +}); diff --git a/mode/css/css.js b/mode/css/css.js index 06d73455da..d63bdd0827 100644 --- a/mode/css/css.js +++ b/mode/css/css.js @@ -1,6 +1,14 @@ -CodeMirror.defineMode("css", function(config, parserConfig) { - "use strict"; +(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.defineMode("css", function(config, parserConfig) { if (!parserConfig.propertyKeywords) parserConfig = CodeMirror.resolveMode("text/css"); var indentUnit = config.indentUnit, @@ -334,7 +342,6 @@ CodeMirror.defineMode("css", function(config, parserConfig) { }; }); -(function() { function keySet(array) { var keys = {}; for (var i = 0; i < array.length; ++i) { @@ -689,4 +696,5 @@ CodeMirror.defineMode("css", function(config, parserConfig) { name: "css", helperType: "less" }); -})(); + +}); diff --git a/mode/d/d.js b/mode/d/d.js index ab345f1a0d..3ab8b42838 100644 --- a/mode/d/d.js +++ b/mode/d/d.js @@ -1,3 +1,13 @@ +(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.defineMode("d", function(config, parserConfig) { var indentUnit = config.indentUnit, statementIndentUnit = parserConfig.statementIndentUnit || indentUnit, @@ -173,7 +183,6 @@ CodeMirror.defineMode("d", function(config, parserConfig) { }; }); -(function() { function words(str) { var obj = {}, words = str.split(" "); for (var i = 0; i < words.length; ++i) obj[words[i]] = true; @@ -202,4 +211,5 @@ CodeMirror.defineMode("d", function(config, parserConfig) { } } }); -}()); + +}); diff --git a/mode/diff/diff.js b/mode/diff/diff.js index 9a0d90ea55..d43f15d51a 100644 --- a/mode/diff/diff.js +++ b/mode/diff/diff.js @@ -1,3 +1,13 @@ +(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.defineMode("diff", function() { var TOKEN_NAMES = { @@ -30,3 +40,5 @@ CodeMirror.defineMode("diff", function() { }); CodeMirror.defineMIME("text/x-diff", "diff"); + +}); diff --git a/mode/dtd/dtd.js b/mode/dtd/dtd.js index 7033bf0f8b..b4a6cb3155 100644 --- a/mode/dtd/dtd.js +++ b/mode/dtd/dtd.js @@ -5,6 +5,16 @@ GitHub: @peterkroon */ +(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.defineMode("dtd", function(config) { var indentUnit = config.indentUnit, type; function ret(style, tp) {type = tp; return style;} @@ -125,3 +135,5 @@ CodeMirror.defineMode("dtd", function(config) { }); CodeMirror.defineMIME("application/xml-dtd", "dtd"); + +}); diff --git a/mode/ecl/ecl.js b/mode/ecl/ecl.js index 7601b189a0..2b841ff5f1 100644 --- a/mode/ecl/ecl.js +++ b/mode/ecl/ecl.js @@ -1,3 +1,13 @@ +(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.defineMode("ecl", function(config) { function words(str) { @@ -190,3 +200,5 @@ CodeMirror.defineMode("ecl", function(config) { }); CodeMirror.defineMIME("text/x-ecl", "ecl"); + +}); diff --git a/mode/eiffel/eiffel.js b/mode/eiffel/eiffel.js index 15f34a9325..c6c3c84600 100644 --- a/mode/eiffel/eiffel.js +++ b/mode/eiffel/eiffel.js @@ -1,3 +1,13 @@ +(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.defineMode("eiffel", function() { function wordObj(words) { var o = {}; @@ -145,3 +155,5 @@ CodeMirror.defineMode("eiffel", function() { }); CodeMirror.defineMIME("text/x-eiffel", "eiffel"); + +}); diff --git a/mode/erlang/erlang.js b/mode/erlang/erlang.js index bc3bdce860..79693fca22 100644 --- a/mode/erlang/erlang.js +++ b/mode/erlang/erlang.js @@ -12,6 +12,16 @@ // old guard/bif/conversion clashes (e.g. "float/1") // type/spec/opaque +(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.defineMIME("text/x-erlang", "erlang"); CodeMirror.defineMode("erlang", function(cmCfg) { @@ -605,3 +615,5 @@ CodeMirror.defineMode("erlang", function(cmCfg) { lineComment: "%" }; }); + +}); diff --git a/mode/fortran/fortran.js b/mode/fortran/fortran.js index 83fd8fde85..58dac127c1 100644 --- a/mode/fortran/fortran.js +++ b/mode/fortran/fortran.js @@ -1,3 +1,13 @@ +(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.defineMode("fortran", function() { function words(array) { var keys = {}; @@ -171,3 +181,5 @@ CodeMirror.defineMode("fortran", function() { }); CodeMirror.defineMIME("text/x-fortran", "fortran"); + +}); diff --git a/mode/gas/gas.js b/mode/gas/gas.js index a6e6892908..a21d5bbe1b 100644 --- a/mode/gas/gas.js +++ b/mode/gas/gas.js @@ -1,3 +1,13 @@ +(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.defineMode("gas", function(_config, parserConfig) { 'use strict'; @@ -328,3 +338,5 @@ CodeMirror.defineMode("gas", function(_config, parserConfig) { blockCommentEnd: "*/" }; }); + +}); diff --git a/mode/gfm/gfm.js b/mode/gfm/gfm.js index 10d5e05c06..7bd5f5ab42 100644 --- a/mode/gfm/gfm.js +++ b/mode/gfm/gfm.js @@ -1,3 +1,13 @@ +(function(mod) { + if (typeof exports == "object" && typeof module == "object") // CommonJS + mod(require("../../lib/codemirror"), require("../markdown/markdown")); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror", "../markdown/markdown"], mod); + else // Plain browser env + mod(CodeMirror); +})(function(CodeMirror) { +"use strict"; + CodeMirror.defineMode("gfm", function(config, modeConfig) { var codeDepth = 0; function blankLine(state) { @@ -100,3 +110,5 @@ CodeMirror.defineMode("gfm", function(config, modeConfig) { CodeMirror.defineMIME("gfmBase", markdownConfig); return CodeMirror.overlayMode(CodeMirror.getMode(config, "gfmBase"), gfmOverlay); }, "markdown"); + +}); diff --git a/mode/gherkin/gherkin.js b/mode/gherkin/gherkin.js index 685b373df7..41003641ec 100644 --- a/mode/gherkin/gherkin.js +++ b/mode/gherkin/gherkin.js @@ -13,6 +13,16 @@ Report bugs/issues here: https://github.com/marijnh/CodeMirror/issues // keywords: /(Feature| {2}(Scenario|In order to|As|I)| {4}(Given|When|Then|And))/ //}; +(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.defineMode("gherkin", function () { return { startState: function () { @@ -161,3 +171,5 @@ CodeMirror.defineMode("gherkin", function () { }); CodeMirror.defineMIME("text/x-feature", "gherkin"); + +}); diff --git a/mode/go/go.js b/mode/go/go.js index 862c091120..7ba780ead8 100644 --- a/mode/go/go.js +++ b/mode/go/go.js @@ -1,3 +1,13 @@ +(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.defineMode("go", function(config) { var indentUnit = config.indentUnit; @@ -166,3 +176,5 @@ CodeMirror.defineMode("go", function(config) { }); CodeMirror.defineMIME("text/x-go", "go"); + +}); diff --git a/mode/groovy/groovy.js b/mode/groovy/groovy.js index 6800e0aaf5..399452d536 100644 --- a/mode/groovy/groovy.js +++ b/mode/groovy/groovy.js @@ -1,3 +1,13 @@ +(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.defineMode("groovy", function(config) { function words(str) { var obj = {}, words = str.split(" "); @@ -209,3 +219,5 @@ CodeMirror.defineMode("groovy", function(config) { }); CodeMirror.defineMIME("text/x-groovy", "groovy"); + +}); diff --git a/mode/haml/haml.js b/mode/haml/haml.js index 5ea4ed12c8..6b205b43e4 100644 --- a/mode/haml/haml.js +++ b/mode/haml/haml.js @@ -1,3 +1,13 @@ +(function(mod) { + if (typeof exports == "object" && typeof module == "object") // CommonJS + mod(require("../../lib/codemirror"), require("../htmlmixed/htmlmixed"), require("../ruby/ruby")); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror", "../htmlmixed/htmlmixed", "../ruby/ruby"], mod); + else // Plain browser env + mod(CodeMirror); +})(function(CodeMirror) { +"use strict"; + (function() { "use strict"; @@ -147,3 +157,5 @@ CodeMirror.defineMIME("text/x-haml", "haml"); })(); + +}); diff --git a/mode/haskell/haskell.js b/mode/haskell/haskell.js index facfd00a65..2876172a95 100644 --- a/mode/haskell/haskell.js +++ b/mode/haskell/haskell.js @@ -1,3 +1,13 @@ +(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.defineMode("haskell", function(_config, modeConfig) { function switchState(source, setState, f) { @@ -250,3 +260,5 @@ CodeMirror.defineMode("haskell", function(_config, modeConfig) { }); CodeMirror.defineMIME("text/x-haskell", "haskell"); + +}); diff --git a/mode/haxe/haxe.js b/mode/haxe/haxe.js index cb761ad1ce..3f78a8d674 100644 --- a/mode/haxe/haxe.js +++ b/mode/haxe/haxe.js @@ -1,3 +1,13 @@ +(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.defineMode("haxe", function(config, parserConfig) { var indentUnit = config.indentUnit; @@ -427,3 +437,5 @@ CodeMirror.defineMode("haxe", function(config, parserConfig) { }); CodeMirror.defineMIME("text/x-haxe", "haxe"); + +}); diff --git a/mode/htmlembedded/htmlembedded.js b/mode/htmlembedded/htmlembedded.js index c316cd3406..3a07c3432e 100644 --- a/mode/htmlembedded/htmlembedded.js +++ b/mode/htmlembedded/htmlembedded.js @@ -1,3 +1,13 @@ +(function(mod) { + if (typeof exports == "object" && typeof module == "object") // CommonJS + mod(require("../../lib/codemirror"), require("../htmlmixed/htmlmixed")); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror", "../htmlmixed/htmlmixed"], mod); + else // Plain browser env + mod(CodeMirror); +})(function(CodeMirror) { +"use strict"; + CodeMirror.defineMode("htmlembedded", function(config, parserConfig) { //config settings @@ -69,3 +79,5 @@ CodeMirror.defineMIME("application/x-ejs", { name: "htmlembedded", scriptingMode CodeMirror.defineMIME("application/x-aspx", { name: "htmlembedded", scriptingModeSpec:"text/x-csharp"}); CodeMirror.defineMIME("application/x-jsp", { name: "htmlembedded", scriptingModeSpec:"text/x-java"}); CodeMirror.defineMIME("application/x-erb", { name: "htmlembedded", scriptingModeSpec:"ruby"}); + +}); diff --git a/mode/htmlmixed/htmlmixed.js b/mode/htmlmixed/htmlmixed.js index e9eab3b92d..a2c3740d3d 100644 --- a/mode/htmlmixed/htmlmixed.js +++ b/mode/htmlmixed/htmlmixed.js @@ -1,3 +1,13 @@ +(function(mod) { + if (typeof exports == "object" && typeof module == "object") // CommonJS + mod(require("../../lib/codemirror"), require("../xml/xml"), require("../javascript/javascript"), require("../css/css")); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror", "../xml/xml", "../javascript/javascript", "../css/css"], mod); + else // Plain browser env + mod(CodeMirror); +})(function(CodeMirror) { +"use strict"; + CodeMirror.defineMode("htmlmixed", function(config, parserConfig) { var htmlMode = CodeMirror.getMode(config, {name: "xml", htmlMode: true}); var cssMode = CodeMirror.getMode(config, "css"); @@ -100,3 +110,5 @@ CodeMirror.defineMode("htmlmixed", function(config, parserConfig) { }, "xml", "javascript", "css"); CodeMirror.defineMIME("text/html", "htmlmixed"); + +}); diff --git a/mode/http/http.js b/mode/http/http.js index 5a51636027..d2ad5994b6 100644 --- a/mode/http/http.js +++ b/mode/http/http.js @@ -1,3 +1,13 @@ +(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.defineMode("http", function() { function failFirstLine(stream, state) { stream.skipToEnd(); @@ -96,3 +106,5 @@ CodeMirror.defineMode("http", function() { }); CodeMirror.defineMIME("message/http", "http"); + +}); diff --git a/mode/index.html b/mode/index.html index 7c1f740615..29d120d012 100644 --- a/mode/index.html +++ b/mode/index.html @@ -80,7 +80,7 @@

    Language modes

  • Python
  • Q
  • R
  • -
  • RPM spec and changelog
  • +
  • RPM
  • reStructuredText
  • Ruby
  • Rust
  • diff --git a/mode/jade/jade.js b/mode/jade/jade.js index 61abb27ab7..020b93ec5d 100644 --- a/mode/jade/jade.js +++ b/mode/jade/jade.js @@ -1,3 +1,13 @@ +(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.defineMode("jade", function () { var symbol_regex1 = /^(?:~|!|%|\^|\*|\+|=|\\|:|;|,|\/|\?|&|<|>|\|)/; var open_paren_regex = /^(\(|\[)/; @@ -88,3 +98,5 @@ CodeMirror.defineMode("jade", function () { }); CodeMirror.defineMIME('text/x-jade', 'jade'); + +}); diff --git a/mode/javascript/javascript.js b/mode/javascript/javascript.js index fbf574b4fe..8d6035de2c 100644 --- a/mode/javascript/javascript.js +++ b/mode/javascript/javascript.js @@ -1,5 +1,15 @@ // TODO actually recognize syntax of TypeScript constructs +(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.defineMode("javascript", function(config, parserConfig) { var indentUnit = config.indentUnit; var statementIndent = parserConfig.statementIndent; @@ -628,3 +638,5 @@ CodeMirror.defineMIME("application/json", {name: "javascript", json: true}); CodeMirror.defineMIME("application/x-json", {name: "javascript", json: true}); CodeMirror.defineMIME("text/typescript", { name: "javascript", typescript: true }); CodeMirror.defineMIME("application/typescript", { name: "javascript", typescript: true }); + +}); diff --git a/mode/jinja2/jinja2.js b/mode/jinja2/jinja2.js index b28af098d0..e30ce63478 100644 --- a/mode/jinja2/jinja2.js +++ b/mode/jinja2/jinja2.js @@ -1,4 +1,14 @@ -CodeMirror.defineMode("jinja2", function() { +(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.defineMode("jinja2", function() { var keywords = ["and", "as", "block", "endblock", "by", "cycle", "debug", "else", "elif", "extends", "filter", "endfilter", "firstof", "for", "endfor", "if", "endif", "ifchanged", "endifchanged", @@ -15,38 +25,39 @@ CodeMirror.defineMode("jinja2", function() { keywords = new RegExp("^((" + keywords.join(")|(") + "))\\b"); function tokenBase (stream, state) { - var ch = stream.next(); - if (ch == "{") { - if (ch = stream.eat(/\{|%|#/)) { - stream.eat("-"); - state.tokenize = inTag(ch); - return "tag"; - } + var ch = stream.next(); + if (ch == "{") { + if (ch = stream.eat(/\{|%|#/)) { + stream.eat("-"); + state.tokenize = inTag(ch); + return "tag"; } + } } function inTag (close) { - if (close == "{") { - close = "}"; + if (close == "{") { + close = "}"; + } + return function (stream, state) { + var ch = stream.next(); + if ((ch == close || (ch == "-" && stream.eat(close))) + && stream.eat("}")) { + state.tokenize = tokenBase; + return "tag"; } - return function (stream, state) { - var ch = stream.next(); - if ((ch == close || (ch == "-" && stream.eat(close))) - && stream.eat("}")) { - state.tokenize = tokenBase; - return "tag"; - } - if (stream.match(keywords)) { - return "keyword"; - } - return close == "#" ? "comment" : "string"; - }; + if (stream.match(keywords)) { + return "keyword"; + } + return close == "#" ? "comment" : "string"; + }; } return { - startState: function () { - return {tokenize: tokenBase}; - }, - token: function (stream, state) { - return state.tokenize(stream, state); - } + startState: function () { + return {tokenize: tokenBase}; + }, + token: function (stream, state) { + return state.tokenize(stream, state); + } }; + }); }); diff --git a/mode/julia/julia.js b/mode/julia/julia.js index 9ec2428cd4..b603713040 100644 --- a/mode/julia/julia.js +++ b/mode/julia/julia.js @@ -1,3 +1,13 @@ +(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.defineMode("julia", function(_conf, parserConf) { var ERRORCLASS = 'error'; @@ -260,3 +270,5 @@ CodeMirror.defineMode("julia", function(_conf, parserConf) { CodeMirror.defineMIME("text/x-julia", "julia"); + +}); diff --git a/mode/less/less.js b/mode/less/less.js index da681ea67b..9f0d43e938 100644 --- a/mode/less/less.js +++ b/mode/less/less.js @@ -5,6 +5,16 @@ GitHub: @peterkroon */ +(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.defineMode("less", function(config) { var indentUnit = config.indentUnit, type; function ret(style, tp) {type = tp; return style;} @@ -345,3 +355,5 @@ CodeMirror.defineMode("less", function(config) { CodeMirror.defineMIME("text/x-less", "less"); if (!CodeMirror.mimeModes.hasOwnProperty("text/css")) CodeMirror.defineMIME("text/css", "less"); + +}); diff --git a/mode/livescript/livescript.js b/mode/livescript/livescript.js index c000324b8c..9322ba8073 100644 --- a/mode/livescript/livescript.js +++ b/mode/livescript/livescript.js @@ -2,6 +2,17 @@ * Link to the project's GitHub page: * https://github.com/duralog/CodeMirror */ + +(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"; + (function() { CodeMirror.defineMode('livescript', function(){ var tokenBase, external; @@ -265,3 +276,5 @@ })(); CodeMirror.defineMIME('text/x-livescript', 'livescript'); + +}); diff --git a/mode/lua/lua.js b/mode/lua/lua.js index b8deaa2575..3673557c27 100644 --- a/mode/lua/lua.js +++ b/mode/lua/lua.js @@ -2,6 +2,16 @@ // CodeMirror 1 mode. // highlights keywords, strings, comments (no leveling supported! ("[==[")), tokens, basic indenting +(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.defineMode("lua", function(config, parserConfig) { var indentUnit = config.indentUnit; @@ -142,3 +152,5 @@ CodeMirror.defineMode("lua", function(config, parserConfig) { }); CodeMirror.defineMIME("text/x-lua", "lua"); + +}); diff --git a/mode/markdown/markdown.js b/mode/markdown/markdown.js index da2ba93fea..cfa56b911d 100644 --- a/mode/markdown/markdown.js +++ b/mode/markdown/markdown.js @@ -1,3 +1,13 @@ +(function(mod) { + if (typeof exports == "object" && typeof module == "object") // CommonJS + mod(require("../../lib/codemirror", require("../xml/xml"))); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror", "../xml/xml"], mod); + else // Plain browser env + mod(CodeMirror); +})(function(CodeMirror) { +"use strict"; + CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) { var htmlFound = CodeMirror.modes.hasOwnProperty("xml"); @@ -744,3 +754,5 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) { }, "xml"); CodeMirror.defineMIME("text/x-markdown", "markdown"); + +}); diff --git a/mode/mirc/mirc.js b/mode/mirc/mirc.js index fc88bc56fb..6b2a23a16c 100644 --- a/mode/mirc/mirc.js +++ b/mode/mirc/mirc.js @@ -1,4 +1,15 @@ //mIRC mode by Ford_Lawnmower :: Based on Velocity mode by Steve O'Hara + +(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.defineMIME("text/mirc", "mirc"); CodeMirror.defineMode("mirc", function() { function parseWords(str) { @@ -175,3 +186,5 @@ CodeMirror.defineMode("mirc", function() { } }; }); + +}); diff --git a/mode/mllike/mllike.js b/mode/mllike/mllike.js index 1d64789a19..d4d59fceb7 100644 --- a/mode/mllike/mllike.js +++ b/mode/mllike/mllike.js @@ -1,5 +1,14 @@ -CodeMirror.defineMode('mllike', function(_config, parserConfig) { +(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.defineMode('mllike', function(_config, parserConfig) { var words = { 'let': 'keyword', 'rec': 'keyword', @@ -189,3 +198,5 @@ CodeMirror.defineMIME('text/x-fsharp', { }, slashComments: true }); + +}); diff --git a/mode/nginx/nginx.js b/mode/nginx/nginx.js index c98c8a1dd3..4e17cdb3c4 100644 --- a/mode/nginx/nginx.js +++ b/mode/nginx/nginx.js @@ -1,3 +1,13 @@ +(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.defineMode("nginx", function(config) { function words(str) { @@ -161,3 +171,5 @@ CodeMirror.defineMode("nginx", function(config) { }); CodeMirror.defineMIME("text/nginx", "text/x-nginx-conf"); + +}); diff --git a/mode/ntriples/ntriples.js b/mode/ntriples/ntriples.js index ed0cee34b0..cd5eb24f07 100644 --- a/mode/ntriples/ntriples.js +++ b/mode/ntriples/ntriples.js @@ -25,6 +25,17 @@ -> ERROR } */ + +(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.defineMode("ntriples", function() { var Location = { @@ -168,3 +179,5 @@ CodeMirror.defineMode("ntriples", function() { }); CodeMirror.defineMIME("text/n-triples", "ntriples"); + +}); diff --git a/mode/octave/octave.js b/mode/octave/octave.js index 23cd2fe222..0d8f610d1d 100644 --- a/mode/octave/octave.js +++ b/mode/octave/octave.js @@ -1,3 +1,13 @@ +(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.defineMode("octave", function() { function wordRegexp(words) { return new RegExp("^((" + words.join(")|(") + "))\\b"); @@ -116,3 +126,5 @@ CodeMirror.defineMode("octave", function() { }); CodeMirror.defineMIME("text/x-octave", "octave"); + +}); diff --git a/mode/pascal/pascal.js b/mode/pascal/pascal.js index 09d9b0617b..642dd9bf79 100644 --- a/mode/pascal/pascal.js +++ b/mode/pascal/pascal.js @@ -1,3 +1,13 @@ +(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.defineMode("pascal", function() { function words(str) { var obj = {}, words = str.split(" "); @@ -92,3 +102,5 @@ CodeMirror.defineMode("pascal", function() { }); CodeMirror.defineMIME("text/x-pascal", "pascal"); + +}); diff --git a/mode/pegjs/pegjs.js b/mode/pegjs/pegjs.js index 6b2e273791..f74f2a4f22 100644 --- a/mode/pegjs/pegjs.js +++ b/mode/pegjs/pegjs.js @@ -1,3 +1,13 @@ +(function(mod) { + if (typeof exports == "object" && typeof module == "object") // CommonJS + mod(require("../../lib/codemirror"), require("../javascript/javascript")); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror", "../javascript/javascript"], mod); + else // Plain browser env + mod(CodeMirror); +})(function(CodeMirror) { +"use strict"; + CodeMirror.defineMode("pegjs", function (config) { var jsMode = CodeMirror.getMode(config, "javascript"); @@ -97,3 +107,5 @@ CodeMirror.defineMode("pegjs", function (config) { } }; }, "javascript"); + +}); diff --git a/mode/perl/perl.js b/mode/perl/perl.js index 5954b1a61c..84392e4a81 100644 --- a/mode/perl/perl.js +++ b/mode/perl/perl.js @@ -1,5 +1,16 @@ // CodeMirror2 mode/perl/perl.js (text/x-perl) beta 0.10 (2011-11-08) // This is a part of CodeMirror from https://github.com/sabaca/CodeMirror_mode_perl (mail@sabaca.com) + +(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.defineMode("perl",function(){ // http://perldoc.perl.org var PERL={ // null - magic touch @@ -509,7 +520,7 @@ CodeMirror.defineMode("perl",function(){ return tokenSOMETHING(stream,state,'=cut');} var ch=stream.next(); if(ch=='"'||ch=="'"){ // NOTE: ' or " or <<'SOMETHING'\n...\nSOMETHING\n or <<"SOMETHING"\n...\nSOMETHING\n - if(stream.prefix(3)=="<<"+ch){ + if(prefix(stream, 3)=="<<"+ch){ var p=stream.pos; stream.eatWhile(/\w/); var n=stream.current().substr(1); @@ -518,94 +529,94 @@ CodeMirror.defineMode("perl",function(){ stream.pos=p;} return tokenChain(stream,state,[ch],"string");} if(ch=="q"){ - var c=stream.look(-2); + var c=look(stream, -2); if(!(c&&/\w/.test(c))){ - c=stream.look(0); + c=look(stream, 0); if(c=="x"){ - c=stream.look(1); + c=look(stream, 1); if(c=="("){ - stream.eatSuffix(2); + eatSuffix(stream, 2); return tokenChain(stream,state,[")"],RXstyle,RXmodifiers);} if(c=="["){ - stream.eatSuffix(2); + eatSuffix(stream, 2); return tokenChain(stream,state,["]"],RXstyle,RXmodifiers);} if(c=="{"){ - stream.eatSuffix(2); + eatSuffix(stream, 2); return tokenChain(stream,state,["}"],RXstyle,RXmodifiers);} if(c=="<"){ - stream.eatSuffix(2); + eatSuffix(stream, 2); return tokenChain(stream,state,[">"],RXstyle,RXmodifiers);} if(/[\^'"!~\/]/.test(c)){ - stream.eatSuffix(1); + eatSuffix(stream, 1); return tokenChain(stream,state,[stream.eat(c)],RXstyle,RXmodifiers);}} else if(c=="q"){ - c=stream.look(1); + c=look(stream, 1); if(c=="("){ - stream.eatSuffix(2); + eatSuffix(stream, 2); return tokenChain(stream,state,[")"],"string");} if(c=="["){ - stream.eatSuffix(2); + eatSuffix(stream, 2); return tokenChain(stream,state,["]"],"string");} if(c=="{"){ -stream.eatSuffix(2); + eatSuffix(stream, 2); return tokenChain(stream,state,["}"],"string");} if(c=="<"){ - stream.eatSuffix(2); + eatSuffix(stream, 2); return tokenChain(stream,state,[">"],"string");} if(/[\^'"!~\/]/.test(c)){ - stream.eatSuffix(1); + eatSuffix(stream, 1); return tokenChain(stream,state,[stream.eat(c)],"string");}} else if(c=="w"){ - c=stream.look(1); + c=look(stream, 1); if(c=="("){ - stream.eatSuffix(2); + eatSuffix(stream, 2); return tokenChain(stream,state,[")"],"bracket");} if(c=="["){ - stream.eatSuffix(2); + eatSuffix(stream, 2); return tokenChain(stream,state,["]"],"bracket");} if(c=="{"){ - stream.eatSuffix(2); + eatSuffix(stream, 2); return tokenChain(stream,state,["}"],"bracket");} if(c=="<"){ - stream.eatSuffix(2); + eatSuffix(stream, 2); return tokenChain(stream,state,[">"],"bracket");} if(/[\^'"!~\/]/.test(c)){ - stream.eatSuffix(1); + eatSuffix(stream, 1); return tokenChain(stream,state,[stream.eat(c)],"bracket");}} else if(c=="r"){ - c=stream.look(1); + c=look(stream, 1); if(c=="("){ - stream.eatSuffix(2); + eatSuffix(stream, 2); return tokenChain(stream,state,[")"],RXstyle,RXmodifiers);} if(c=="["){ - stream.eatSuffix(2); + eatSuffix(stream, 2); return tokenChain(stream,state,["]"],RXstyle,RXmodifiers);} if(c=="{"){ - stream.eatSuffix(2); + eatSuffix(stream, 2); return tokenChain(stream,state,["}"],RXstyle,RXmodifiers);} if(c=="<"){ - stream.eatSuffix(2); + eatSuffix(stream, 2); return tokenChain(stream,state,[">"],RXstyle,RXmodifiers);} if(/[\^'"!~\/]/.test(c)){ - stream.eatSuffix(1); + eatSuffix(stream, 1); return tokenChain(stream,state,[stream.eat(c)],RXstyle,RXmodifiers);}} else if(/[\^'"!~\/(\[{<]/.test(c)){ if(c=="("){ - stream.eatSuffix(1); + eatSuffix(stream, 1); return tokenChain(stream,state,[")"],"string");} if(c=="["){ - stream.eatSuffix(1); + eatSuffix(stream, 1); return tokenChain(stream,state,["]"],"string");} if(c=="{"){ - stream.eatSuffix(1); + eatSuffix(stream, 1); return tokenChain(stream,state,["}"],"string");} if(c=="<"){ - stream.eatSuffix(1); + eatSuffix(stream, 1); return tokenChain(stream,state,[">"],"string");} if(/[\^'"!~\/]/.test(c)){ return tokenChain(stream,state,[stream.eat(c)],"string");}}}} if(ch=="m"){ - var c=stream.look(-2); + var c=look(stream, -2); if(!(c&&/\w/.test(c))){ c=stream.eat(/[(\[{<\^'"!~\/]/); if(c){ @@ -620,7 +631,7 @@ stream.eatSuffix(2); if(c=="<"){ return tokenChain(stream,state,[">"],RXstyle,RXmodifiers);}}}} if(ch=="s"){ - var c=/[\/>\]})\w]/.test(stream.look(-2)); + var c=/[\/>\]})\w]/.test(look(stream, -2)); if(!c){ c=stream.eat(/[(\[{<\^'"!~\/]/); if(c){ @@ -634,7 +645,7 @@ stream.eatSuffix(2); return tokenChain(stream,state,[")",")"],RXstyle,RXmodifiers); return tokenChain(stream,state,[c,c],RXstyle,RXmodifiers);}}} if(ch=="y"){ - var c=/[\/>\]})\w]/.test(stream.look(-2)); + var c=/[\/>\]})\w]/.test(look(stream, -2)); if(!c){ c=stream.eat(/[(\[{<\^'"!~\/]/); if(c){ @@ -648,7 +659,7 @@ stream.eatSuffix(2); return tokenChain(stream,state,[")",")"],RXstyle,RXmodifiers); return tokenChain(stream,state,[c,c],RXstyle,RXmodifiers);}}} if(ch=="t"){ - var c=/[\/>\]})\w]/.test(stream.look(-2)); + var c=/[\/>\]})\w]/.test(look(stream, -2)); if(!c){ c=stream.eat("r");if(c){ c=stream.eat(/[(\[{<\^'"!~\/]/); @@ -665,7 +676,7 @@ stream.eatSuffix(2); if(ch=="`"){ return tokenChain(stream,state,[ch],"variable-2");} if(ch=="/"){ - if(!/~\s*$/.test(stream.prefix())) + if(!/~\s*$/.test(prefix(stream))) return "operator"; else return tokenChain(stream,state,[ch],RXstyle,RXmodifiers);} @@ -677,7 +688,7 @@ stream.eatSuffix(2); stream.pos=p;} if(/[$@%]/.test(ch)){ var p=stream.pos; - if(stream.eat("^")&&stream.eat(/[A-Z]/)||!/[@$%&]/.test(stream.look(-2))&&stream.eat(/[=|\\\-#?@;:&`~\^!\[\]*'"$+.,\/<>()]/)){ + if(stream.eat("^")&&stream.eat(/[A-Z]/)||!/[@$%&]/.test(look(stream, -2))&&stream.eat(/[=|\\\-#?@;:&`~\^!\[\]*'"$+.,\/<>()]/)){ var c=stream.current(); if(PERL[c]) return "variable-2";} @@ -690,7 +701,7 @@ stream.eatSuffix(2); else return "variable";}} if(ch=="#"){ - if(stream.look(-2)!="$"){ + if(look(stream, -2)!="$"){ stream.skipToEnd(); return "comment";}} if(/[:+\-\^*$&%@=<>!?|\/~\.]/.test(ch)){ @@ -702,23 +713,23 @@ stream.eatSuffix(2); stream.pos=p;} if(ch=="_"){ if(stream.pos==1){ - if(stream.suffix(6)=="_END__"){ + if(suffix(stream, 6)=="_END__"){ return tokenChain(stream,state,['\0'],"comment");} - else if(stream.suffix(7)=="_DATA__"){ + else if(suffix(stream, 7)=="_DATA__"){ return tokenChain(stream,state,['\0'],"variable-2");} - else if(stream.suffix(7)=="_C__"){ + else if(suffix(stream, 7)=="_C__"){ return tokenChain(stream,state,['\0'],"string");}}} if(/\w/.test(ch)){ var p=stream.pos; - if(stream.look(-2)=="{"&&(stream.look(0)=="}"||stream.eatWhile(/\w/)&&stream.look(0)=="}")) + if(look(stream, -2)=="{"&&(look(stream, 0)=="}"||stream.eatWhile(/\w/)&&look(stream, 0)=="}")) return "string"; else stream.pos=p;} if(/[A-Z]/.test(ch)){ - var l=stream.look(-2); + var l=look(stream, -2); var p=stream.pos; stream.eatWhile(/[A-Z_]/); - if(/[\da-z]/.test(stream.look(0))){ + if(/[\da-z]/.test(look(stream, 0))){ stream.pos=p;} else{ var c=PERL[stream.current()]; @@ -742,7 +753,7 @@ stream.eatSuffix(2); else return "meta";}} if(/[a-zA-Z_]/.test(ch)){ - var l=stream.look(-2); + var l=look(stream, -2); stream.eatWhile(/\w/); var c=PERL[stream.current()]; if(!c) @@ -780,37 +791,37 @@ stream.eatSuffix(2); CodeMirror.defineMIME("text/x-perl", "perl"); // it's like "peek", but need for look-ahead or look-behind if index < 0 -CodeMirror.StringStream.prototype.look=function(c){ - return this.string.charAt(this.pos+(c||0));}; +function look(stream, c){ + return stream.string.charAt(stream.pos+(c||0)); +} // return a part of prefix of current stream from current position -CodeMirror.StringStream.prototype.prefix=function(c){ - if(c){ - var x=this.pos-c; - return this.string.substr((x>=0?x:0),c);} - else{ - return this.string.substr(0,this.pos-1);}}; +function prefix(stream, c){ + if(c){ + var x=stream.pos-c; + return stream.string.substr((x>=0?x:0),c);} + else{ + return stream.string.substr(0,stream.pos-1); + } +} // return a part of suffix of current stream from current position -CodeMirror.StringStream.prototype.suffix=function(c){ - var y=this.string.length; - var x=y-this.pos+1; - return this.string.substr(this.pos,(c&&c=(y=this.string.length-1)) - this.pos=y; - else - this.pos=x;}; +function eatSuffix(stream, c){ + var x=stream.pos+c; + var y; + if(x<=0) + stream.pos=0; + else if(x>=(y=stream.string.length-1)) + stream.pos=y; + else + stream.pos=x; +} + +}); diff --git a/mode/php/php.js b/mode/php/php.js index 946f770c9f..7156dbba6f 100644 --- a/mode/php/php.js +++ b/mode/php/php.js @@ -1,4 +1,13 @@ -(function() { +(function(mod) { + if (typeof exports == "object" && typeof module == "object") // CommonJS + mod(require("../../lib/codemirror"), require("../htmlmixed/htmlmixed"), require("../clike/clike")); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror", "../htmlmixed/htmlmixed", "../clike/clike"], mod); + else // Plain browser env + mod(CodeMirror); +})(function(CodeMirror) { + "use strict"; + function keywords(str) { var obj = {}, words = str.split(" "); for (var i = 0; i < words.length; ++i) obj[words[i]] = true; @@ -128,4 +137,4 @@ CodeMirror.defineMIME("application/x-httpd-php", "php"); CodeMirror.defineMIME("application/x-httpd-php-open", {name: "php", startOpen: true}); CodeMirror.defineMIME("text/x-php", phpConfig); -})(); +}); diff --git a/mode/pig/pig.js b/mode/pig/pig.js index 4b44e7ccc3..eaf525889c 100644 --- a/mode/pig/pig.js +++ b/mode/pig/pig.js @@ -4,6 +4,16 @@ * @link https://github.com/prasanthj/pig-codemirror-2 * This implementation is adapted from PL/SQL mode in CodeMirror 2. */ +(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.defineMode("pig", function(_config, parserConfig) { var keywords = parserConfig.keywords, builtins = parserConfig.builtins, @@ -169,3 +179,5 @@ CodeMirror.defineMode("pig", function(_config, parserConfig) { types: keywords(pTypes) }); }()); + +}); diff --git a/mode/properties/properties.js b/mode/properties/properties.js index d3a13c765d..6dfe06f128 100644 --- a/mode/properties/properties.js +++ b/mode/properties/properties.js @@ -1,3 +1,13 @@ +(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.defineMode("properties", function() { return { token: function(stream, state) { @@ -61,3 +71,5 @@ CodeMirror.defineMode("properties", function() { CodeMirror.defineMIME("text/x-properties", "properties"); CodeMirror.defineMIME("text/x-ini", "properties"); + +}); diff --git a/mode/python/python.js b/mode/python/python.js index 8bea5d19d1..36cf951bef 100644 --- a/mode/python/python.js +++ b/mode/python/python.js @@ -1,3 +1,14 @@ +(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.defineMode("python", function(conf, parserConf) { var ERRORCLASS = 'error'; @@ -361,14 +372,13 @@ CodeMirror.defineMode("python", function(conf, parserConf) { CodeMirror.defineMIME("text/x-python", "python"); -(function() { - "use strict"; - var words = function(str){return str.split(' ');}; - - CodeMirror.defineMIME("text/x-cython", { - name: "python", - extra_keywords: words("by cdef cimport cpdef ctypedef enum except"+ - "extern gil include nogil property public"+ - "readonly struct union DEF IF ELIF ELSE") - }); -})(); +var words = function(str){return str.split(' ');}; + +CodeMirror.defineMIME("text/x-cython", { + name: "python", + extra_keywords: words("by cdef cimport cpdef ctypedef enum except"+ + "extern gil include nogil property public"+ + "readonly struct union DEF IF ELIF ELSE") +}); + +}); diff --git a/mode/q/q.js b/mode/q/q.js index 56017e30ad..d6e3b66610 100644 --- a/mode/q/q.js +++ b/mode/q/q.js @@ -1,3 +1,13 @@ +(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.defineMode("q",function(config){ var indentUnit=config.indentUnit, curPunc, @@ -122,3 +132,5 @@ CodeMirror.defineMode("q",function(config){ }; }); CodeMirror.defineMIME("text/x-q","q"); + +}); diff --git a/mode/r/r.js b/mode/r/r.js index 690cf40502..7f4feb238b 100644 --- a/mode/r/r.js +++ b/mode/r/r.js @@ -1,3 +1,13 @@ +(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.defineMode("r", function(config) { function wordObj(str) { var words = str.split(" "), res = {}; @@ -143,3 +153,5 @@ CodeMirror.defineMode("r", function(config) { }); CodeMirror.defineMIME("text/x-rsrc", "r"); + +}); diff --git a/mode/rpm/changes/changes.js b/mode/rpm/changes/changes.js deleted file mode 100644 index 14a08d9700..0000000000 --- a/mode/rpm/changes/changes.js +++ /dev/null @@ -1,19 +0,0 @@ -CodeMirror.defineMode("changes", function() { - var headerSeperator = /^-+$/; - var headerLine = /^(Mon|Tue|Wed|Thu|Fri|Sat|Sun) (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) ?\d{1,2} \d{2}:\d{2}(:\d{2})? [A-Z]{3,4} \d{4} - /; - var simpleEmail = /^[\w+.-]+@[\w.-]+/; - - return { - token: function(stream) { - if (stream.sol()) { - if (stream.match(headerSeperator)) { return 'tag'; } - if (stream.match(headerLine)) { return 'tag'; } - } - if (stream.match(simpleEmail)) { return 'string'; } - stream.next(); - return null; - } - }; -}); - -CodeMirror.defineMIME("text/x-rpm-changes", "changes"); diff --git a/mode/rpm/changes/index.html b/mode/rpm/changes/index.html deleted file mode 100644 index 18fe7ab7bf..0000000000 --- a/mode/rpm/changes/index.html +++ /dev/null @@ -1,67 +0,0 @@ - - -CodeMirror: RPM changes mode - - - - - - - - - - - -
    -

    RPM changes mode

    - -
    - - -

    MIME types defined: text/x-rpm-changes.

    -
    diff --git a/mode/rpm/spec/index.html b/mode/rpm/index.html similarity index 60% rename from mode/rpm/spec/index.html rename to mode/rpm/index.html index 127b72ee9d..4257bc77e3 100644 --- a/mode/rpm/spec/index.html +++ b/mode/rpm/index.html @@ -1,34 +1,71 @@ -CodeMirror: RPM spec mode +CodeMirror: RPM changes mode - - - - - + + + +
    +

    RPM changes mode

    + +
    + +

    RPM spec mode

    -
    -

    MIME types defined: text/x-rpm-spec.

    - +

    MIME types defined: text/x-rpm-spec, text/x-rpm-changes.

    diff --git a/mode/rpm/spec/spec.js b/mode/rpm/rpm.js similarity index 70% rename from mode/rpm/spec/spec.js rename to mode/rpm/rpm.js index 0fab6c4891..497997c4ff 100644 --- a/mode/rpm/spec/spec.js +++ b/mode/rpm/rpm.js @@ -1,6 +1,36 @@ +(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.defineMode("rpm-changes", function() { + var headerSeperator = /^-+$/; + var headerLine = /^(Mon|Tue|Wed|Thu|Fri|Sat|Sun) (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) ?\d{1,2} \d{2}:\d{2}(:\d{2})? [A-Z]{3,4} \d{4} - /; + var simpleEmail = /^[\w+.-]+@[\w.-]+/; + + return { + token: function(stream) { + if (stream.sol()) { + if (stream.match(headerSeperator)) { return 'tag'; } + if (stream.match(headerLine)) { return 'tag'; } + } + if (stream.match(simpleEmail)) { return 'string'; } + stream.next(); + return null; + } + }; +}); + +CodeMirror.defineMIME("text/x-rpm-changes", "rpm-changes"); + // Quick and dirty spec file highlighting -CodeMirror.defineMode("spec", function() { +CodeMirror.defineMode("rpm-spec", function() { var arch = /^(i386|i586|i686|x86_64|ppc64|ppc|ia64|s390x|s390|sparc64|sparcv9|sparc|noarch|alphaev6|alpha|hppa|mipsel)/; var preamble = /^(Name|Version|Release|License|Summary|Url|Group|Source|BuildArch|BuildRequires|BuildRoot|AutoReqProv|Provides|Requires(\(\w+\))?|Obsoletes|Conflicts|Recommends|Source\d*|Patch\d*|ExclusiveArch|NoSource|Supplements):/; @@ -63,4 +93,6 @@ CodeMirror.defineMode("spec", function() { }; }); -CodeMirror.defineMIME("text/x-rpm-spec", "spec"); +CodeMirror.defineMIME("text/x-rpm-spec", "rpm-spec"); + +}); diff --git a/mode/rpm/spec/spec.css b/mode/rpm/spec/spec.css deleted file mode 100644 index d0a5d430ca..0000000000 --- a/mode/rpm/spec/spec.css +++ /dev/null @@ -1,5 +0,0 @@ -.cm-s-default span.cm-preamble {color: #b26818; font-weight: bold;} -.cm-s-default span.cm-macro {color: #b218b2;} -.cm-s-default span.cm-section {color: green; font-weight: bold;} -.cm-s-default span.cm-script {color: red;} -.cm-s-default span.cm-issue {color: yellow;} diff --git a/mode/rst/rst.js b/mode/rst/rst.js index 75563ba982..c53cbc36e8 100644 --- a/mode/rst/rst.js +++ b/mode/rst/rst.js @@ -1,3 +1,13 @@ +(function(mod) { + if (typeof exports == "object" && typeof module == "object") // CommonJS + mod(require("../../lib/codemirror"), require("../python/python"), require("../stex/stex")); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror", "../python/python", "../stex/stex"], mod); + else // Plain browser env + mod(CodeMirror); +})(function(CodeMirror) { +"use strict"; + CodeMirror.defineMode('rst-base', function (config) { /////////////////////////////////////////////////////////////////////////// @@ -558,3 +568,5 @@ CodeMirror.defineMIME('text/x-rst', 'rst'); /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// + +}); diff --git a/mode/ruby/ruby.js b/mode/ruby/ruby.js index 1cdc9a4e43..8ee9eec707 100644 --- a/mode/ruby/ruby.js +++ b/mode/ruby/ruby.js @@ -1,3 +1,13 @@ +(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.defineMode("ruby", function(config) { function wordObj(words) { var o = {}; @@ -247,3 +257,4 @@ CodeMirror.defineMode("ruby", function(config) { CodeMirror.defineMIME("text/x-ruby", "ruby"); +}); diff --git a/mode/rust/rust.js b/mode/rust/rust.js index c7530b6cc6..2e6e20b231 100644 --- a/mode/rust/rust.js +++ b/mode/rust/rust.js @@ -1,3 +1,13 @@ +(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.defineMode("rust", function() { var indentUnit = 4, altIndentUnit = 2; var valKeywords = { @@ -434,3 +444,5 @@ CodeMirror.defineMode("rust", function() { }); CodeMirror.defineMIME("text/x-rustsrc", "rust"); + +}); diff --git a/mode/sass/sass.js b/mode/sass/sass.js index 9c9a0dae07..74ae91db12 100644 --- a/mode/sass/sass.js +++ b/mode/sass/sass.js @@ -1,3 +1,13 @@ +(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.defineMode("sass", function(config) { var tokenRegexp = function(words){ return new RegExp("^" + words.join("|")); @@ -328,3 +338,5 @@ CodeMirror.defineMode("sass", function(config) { }); CodeMirror.defineMIME("text/x-sass", "sass"); + +}); diff --git a/mode/scheme/scheme.js b/mode/scheme/scheme.js index c5990ae92c..7124f7283b 100644 --- a/mode/scheme/scheme.js +++ b/mode/scheme/scheme.js @@ -1,6 +1,17 @@ /** * Author: Koh Zi Han, based on implementation by Koh Zi Chun */ + +(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.defineMode("scheme", function () { var BUILTIN = "builtin", COMMENT = "comment", STRING = "string", ATOM = "atom", NUMBER = "number", BRACKET = "bracket"; @@ -230,3 +241,5 @@ CodeMirror.defineMode("scheme", function () { }); CodeMirror.defineMIME("text/x-scheme", "scheme"); + +}); diff --git a/mode/shell/shell.js b/mode/shell/shell.js index abfd214454..7753411c98 100644 --- a/mode/shell/shell.js +++ b/mode/shell/shell.js @@ -1,3 +1,13 @@ +(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.defineMode('shell', function() { var words = {}; @@ -116,3 +126,5 @@ CodeMirror.defineMode('shell', function() { }); CodeMirror.defineMIME('text/x-sh', 'shell'); + +}); diff --git a/mode/sieve/sieve.js b/mode/sieve/sieve.js index 8ca2a4cb82..8256dda0a4 100644 --- a/mode/sieve/sieve.js +++ b/mode/sieve/sieve.js @@ -1,7 +1,12 @@ -/* - * See LICENSE in this directory for the license under which this code - * is released. - */ +(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.defineMode("sieve", function(config) { function words(str) { @@ -181,3 +186,5 @@ CodeMirror.defineMode("sieve", function(config) { }); CodeMirror.defineMIME("application/sieve", "sieve"); + +}); diff --git a/mode/smalltalk/smalltalk.js b/mode/smalltalk/smalltalk.js index 86f749b310..deb78a4f7a 100644 --- a/mode/smalltalk/smalltalk.js +++ b/mode/smalltalk/smalltalk.js @@ -1,3 +1,13 @@ +(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.defineMode('smalltalk', function(config) { var specialChars = /[+\-\/\\*~<>=@%|&?!.,:;^]/; @@ -151,3 +161,5 @@ CodeMirror.defineMode('smalltalk', function(config) { }); CodeMirror.defineMIME('text/x-stsrc', {name: 'smalltalk'}); + +}); diff --git a/mode/smarty/smarty.js b/mode/smarty/smarty.js index 826c2b966c..2a78c6d394 100644 --- a/mode/smarty/smarty.js +++ b/mode/smarty/smarty.js @@ -1,6 +1,17 @@ /** * Smarty 2 and 3 mode. */ + +(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.defineMode("smarty", function(config) { "use strict"; @@ -203,3 +214,5 @@ CodeMirror.defineMode("smarty", function(config) { }); CodeMirror.defineMIME("text/x-smarty", "smarty"); + +}); diff --git a/mode/smartymixed/smartymixed.js b/mode/smartymixed/smartymixed.js index 48dd1a6752..7e5e12c0ec 100644 --- a/mode/smartymixed/smartymixed.js +++ b/mode/smartymixed/smartymixed.js @@ -5,6 +5,17 @@ * @version 3.0 * @date 05.07.2013 */ + +(function(mod) { + if (typeof exports == "object" && typeof module == "object") // CommonJS + mod(require("../../lib/codemirror"), require("../htmlmixed/htmlmixed"), require("../smarty/smarty")); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror", "../htmlmixed/htmlmixed", "../smarty/smarty"], mod); + else // Plain browser env + mod(CodeMirror); +})(function(CodeMirror) { +"use strict"; + CodeMirror.defineMode("smartymixed", function(config) { var settings, regs, helpers, parsers, htmlMixedMode = CodeMirror.getMode(config, "htmlmixed"), @@ -166,8 +177,9 @@ CodeMirror.defineMode("smartymixed", function(config) { }; } }; -}, -"htmlmixed"); +}, "htmlmixed", "smarty"); CodeMirror.defineMIME("text/x-smarty", "smartymixed"); // vim: et ts=2 sts=2 sw=2 + +}); diff --git a/mode/sparql/sparql.js b/mode/sparql/sparql.js index 0329057f69..f228b1dffe 100644 --- a/mode/sparql/sparql.js +++ b/mode/sparql/sparql.js @@ -1,3 +1,13 @@ +(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.defineMode("sparql", function(config) { var indentUnit = config.indentUnit; var curPunc; @@ -143,3 +153,5 @@ CodeMirror.defineMode("sparql", function(config) { }); CodeMirror.defineMIME("application/x-sparql-query", "sparql"); + +}); diff --git a/mode/sql/sql.js b/mode/sql/sql.js index 903fa6740a..c43285f338 100644 --- a/mode/sql/sql.js +++ b/mode/sql/sql.js @@ -1,3 +1,13 @@ +(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.defineMode("sql", function(config, parserConfig) { "use strict"; @@ -334,6 +344,8 @@ CodeMirror.defineMode("sql", function(config, parserConfig) { }); }()); +}); + /* How Properties of Mime Types are used by SQL Mode ================================================= diff --git a/mode/stex/stex.js b/mode/stex/stex.js index ca04c24f22..59a395a0fe 100644 --- a/mode/stex/stex.js +++ b/mode/stex/stex.js @@ -3,6 +3,16 @@ * Licence: MIT */ +(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.defineMode("stex", function() { "use strict"; @@ -244,3 +254,5 @@ CodeMirror.defineMode("stex", function() { CodeMirror.defineMIME("text/x-stex", "stex"); CodeMirror.defineMIME("text/x-latex", "stex"); + +}); diff --git a/mode/tcl/tcl.js b/mode/tcl/tcl.js index ed2c697217..4c29ee7d98 100644 --- a/mode/tcl/tcl.js +++ b/mode/tcl/tcl.js @@ -1,4 +1,15 @@ //tcl mode by Ford_Lawnmower :: Based on Velocity mode by Steve O'Hara + +(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.defineMode("tcl", function() { function parseWords(str) { var obj = {}, words = str.split(" "); @@ -129,3 +140,5 @@ CodeMirror.defineMode("tcl", function() { }; }); CodeMirror.defineMIME("text/x-tcl", "tcl"); + +}); diff --git a/mode/tiddlywiki/tiddlywiki.js b/mode/tiddlywiki/tiddlywiki.js index 24a24786bc..ecd1d173c0 100644 --- a/mode/tiddlywiki/tiddlywiki.js +++ b/mode/tiddlywiki/tiddlywiki.js @@ -14,6 +14,17 @@ CoreVersion parameter is needed for TiddlyWiki only! ***/ //{{{ + +(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.defineMode("tiddlywiki", function () { // Tokenizer var textwords = {}; @@ -350,4 +361,6 @@ CodeMirror.defineMode("tiddlywiki", function () { }); CodeMirror.defineMIME("text/x-tiddlywiki", "tiddlywiki"); +}); + //}}} diff --git a/mode/tiki/tiki.js b/mode/tiki/tiki.js index e789163dc7..eb9a893fde 100644 --- a/mode/tiki/tiki.js +++ b/mode/tiki/tiki.js @@ -1,3 +1,13 @@ +(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.defineMode('tiki', function(config) { function inBlock(style, terminator, returnTokenizer) { return function(stream, state) { @@ -306,3 +316,5 @@ return { }); CodeMirror.defineMIME("text/tiki", "tiki"); + +}); diff --git a/mode/toml/toml.js b/mode/toml/toml.js index 1d163f13bf..552dd57b08 100644 --- a/mode/toml/toml.js +++ b/mode/toml/toml.js @@ -1,3 +1,13 @@ +(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.defineMode("toml", function () { return { startState: function () { @@ -69,3 +79,5 @@ CodeMirror.defineMode("toml", function () { }); CodeMirror.defineMIME('text/x-toml', 'toml'); + +}); diff --git a/mode/turtle/turtle.js b/mode/turtle/turtle.js index e118bfbced..de9fc2b6c7 100644 --- a/mode/turtle/turtle.js +++ b/mode/turtle/turtle.js @@ -1,3 +1,13 @@ +(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.defineMode("turtle", function(config) { var indentUnit = config.indentUnit; var curPunc; @@ -143,3 +153,5 @@ CodeMirror.defineMode("turtle", function(config) { }); CodeMirror.defineMIME("text/turtle", "turtle"); + +}); diff --git a/mode/vb/vb.js b/mode/vb/vb.js index 27b2271951..4fd80210fb 100644 --- a/mode/vb/vb.js +++ b/mode/vb/vb.js @@ -1,3 +1,13 @@ +(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.defineMode("vb", function(conf, parserConf) { var ERRORCLASS = 'error'; @@ -257,3 +267,5 @@ CodeMirror.defineMode("vb", function(conf, parserConf) { }); CodeMirror.defineMIME("text/x-vb", "vb"); + +}); diff --git a/mode/vbscript/vbscript.js b/mode/vbscript/vbscript.js index 0a97fb6405..4be7c7f2bb 100644 --- a/mode/vbscript/vbscript.js +++ b/mode/vbscript/vbscript.js @@ -8,6 +8,17 @@ E.G.: isASP: true }); */ + +(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.defineMode("vbscript", function(conf, parserConf) { var ERRORCLASS = 'error'; @@ -332,3 +343,5 @@ CodeMirror.defineMode("vbscript", function(conf, parserConf) { }); CodeMirror.defineMIME("text/vbscript", "vbscript"); + +}); diff --git a/mode/velocity/velocity.js b/mode/velocity/velocity.js index 968d8799e9..b64636bb43 100644 --- a/mode/velocity/velocity.js +++ b/mode/velocity/velocity.js @@ -1,3 +1,13 @@ +(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.defineMode("velocity", function() { function parseWords(str) { var obj = {}, words = str.split(" "); @@ -184,3 +194,5 @@ CodeMirror.defineMode("velocity", function() { }); CodeMirror.defineMIME("text/velocity", "velocity"); + +}); diff --git a/mode/verilog/verilog.js b/mode/verilog/verilog.js index 708de23f49..bc4fd4feee 100644 --- a/mode/verilog/verilog.js +++ b/mode/verilog/verilog.js @@ -1,3 +1,13 @@ +(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.defineMode("verilog", function(config, parserConfig) { var indentUnit = config.indentUnit, keywords = parserConfig.keywords || {}, @@ -146,7 +156,6 @@ CodeMirror.defineMode("verilog", function(config, parserConfig) { }; }); -(function() { function words(str) { var obj = {}, words = str.split(" "); for (var i = 0; i < words.length; ++i) obj[words[i]] = true; @@ -179,4 +188,5 @@ CodeMirror.defineMode("verilog", function(config, parserConfig) { atoms: words("null"), hooks: {"`": metaHook, "$": metaHook} }); -}()); + +}); diff --git a/mode/xml/xml.js b/mode/xml/xml.js index 96b51ff970..2e62b88346 100644 --- a/mode/xml/xml.js +++ b/mode/xml/xml.js @@ -1,3 +1,13 @@ +(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.defineMode("xml", function(config, parserConfig) { var indentUnit = config.indentUnit; var multilineTagIndentFactor = parserConfig.multilineTagIndentFactor || 1; @@ -330,3 +340,5 @@ CodeMirror.defineMIME("text/xml", "xml"); CodeMirror.defineMIME("application/xml", "xml"); if (!CodeMirror.mimeModes.hasOwnProperty("text/html")) CodeMirror.defineMIME("text/html", {name: "xml", htmlMode: true}); + +}); diff --git a/mode/xquery/xquery.js b/mode/xquery/xquery.js index be17984635..2c7faf425a 100644 --- a/mode/xquery/xquery.js +++ b/mode/xquery/xquery.js @@ -1,3 +1,13 @@ +(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.defineMode("xquery", function() { // The keywords object is set to the result of this self executing @@ -430,3 +440,5 @@ CodeMirror.defineMode("xquery", function() { }); CodeMirror.defineMIME("application/xquery", "xquery"); + +}); diff --git a/mode/yaml/yaml.js b/mode/yaml/yaml.js index efacd7d563..f7b3a90c03 100644 --- a/mode/yaml/yaml.js +++ b/mode/yaml/yaml.js @@ -1,3 +1,13 @@ +(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.defineMode("yaml", function() { var cons = ['true', 'false', 'on', 'off', 'yes', 'no']; @@ -95,3 +105,5 @@ CodeMirror.defineMode("yaml", function() { }); CodeMirror.defineMIME("text/x-yaml", "yaml"); + +}); diff --git a/mode/z80/z80.js b/mode/z80/z80.js index ff43d32b52..c778803072 100644 --- a/mode/z80/z80.js +++ b/mode/z80/z80.js @@ -1,3 +1,13 @@ +(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.defineMode('z80', function() { var keywords1 = /^(exx?|(ld|cp|in)([di]r?)?|pop|push|ad[cd]|cpl|daa|dec|inc|neg|sbc|sub|and|bit|[cs]cf|x?or|res|set|r[lr]c?a?|r[lr]d|s[lr]a|srl|djnz|nop|rst|[de]i|halt|im|ot[di]r|out[di]?)\b/i; var keywords2 = /^(call|j[pr]|ret[in]?)\b/i; @@ -83,3 +93,5 @@ CodeMirror.defineMode('z80', function() { }); CodeMirror.defineMIME("text/x-z80", "z80"); + +}); From 3e7781d99e330f24e07039735cb11b9647a17c29 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Wed, 13 Nov 2013 22:57:32 +0100 Subject: [PATCH 0220/4131] [javascript, xml, haxe modes] Fix strict-mode violations --- mode/haxe/haxe.js | 5 +++-- mode/javascript/javascript.js | 5 +++-- mode/xml/xml.js | 1 + 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/mode/haxe/haxe.js b/mode/haxe/haxe.js index 3f78a8d674..53d7b1d159 100644 --- a/mode/haxe/haxe.js +++ b/mode/haxe/haxe.js @@ -245,11 +245,12 @@ CodeMirror.defineMode("haxe", function(config, parserConfig) { poplex.lex = true; function expect(wanted) { - return function(type) { + function f(type) { if (type == wanted) return cont(); else if (wanted == ";") return pass(); - else return cont(arguments.callee); + else return cont(f); }; + return f; } function statement(type) { diff --git a/mode/javascript/javascript.js b/mode/javascript/javascript.js index 8d6035de2c..290c31fa6c 100644 --- a/mode/javascript/javascript.js +++ b/mode/javascript/javascript.js @@ -305,11 +305,12 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { poplex.lex = true; function expect(wanted) { - return function(type) { + function exp(type) { if (type == wanted) return cont(); else if (wanted == ";") return pass(); - else return cont(arguments.callee); + else return cont(exp); }; + return exp; } function statement(type, value) { diff --git a/mode/xml/xml.js b/mode/xml/xml.js index 2e62b88346..ea5fe61b13 100644 --- a/mode/xml/xml.js +++ b/mode/xml/xml.js @@ -229,6 +229,7 @@ CodeMirror.defineMode("xml", function(config, parserConfig) { return baseState; } } + function closeState(type, _stream, state) { if (type != "endTag") { setStyle = "error"; From 90450a9ee98dd6363b115c5524d8ab659836b13d Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Wed, 13 Nov 2013 23:10:02 +0100 Subject: [PATCH 0221/4131] Fix bug in triple-click handling Closes #1953 --- lib/codemirror.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/codemirror.js b/lib/codemirror.js index c4adf99f65..61a87538df 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -1928,7 +1928,7 @@ if (type == "double") var range = findWordAt(getLine(doc, pos.line).text, pos); else - var range = {from: Pos(pos.line, 0), to: clipPos(pos.line + 1, 0)}; + var range = {from: Pos(pos.line, 0), to: clipPos(doc, Pos(pos.line + 1, 0))}; if (cmp(range.from, anchor) < 0) { head = range.from; anchor = maxPos(oldRange.to(), range.to); From 269e3ff963df837b5e054060e48b6f20e5cc67a9 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Wed, 13 Nov 2013 23:10:49 +0100 Subject: [PATCH 0222/4131] Get rid of stray remaining copyPos call --- lib/codemirror.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/codemirror.js b/lib/codemirror.js index 61a87538df..f1a471029d 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -5230,7 +5230,7 @@ else if (start == "anchor") pos = range.anchor; else if (start == "end" || start == "to" || start === false) pos = range.to(); else pos = range.from(); - return copyPos(pos); + return pos; }, listSelections: function() { return this.sel.ranges; }, somethingSelected: function() {return this.sel.somethingSelected();}, From 7090abb14c1be99e54a40dcdaf9c862cf4623fcd Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 14 Nov 2013 13:36:50 +0100 Subject: [PATCH 0223/4131] Define 'singleSelection' command, bind Esc to it by default Issue #778 --- keymap/multiselect.js | 5 ----- lib/codemirror.js | 6 +++++- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/keymap/multiselect.js b/keymap/multiselect.js index 46379484a6..c258685ae3 100644 --- a/keymap/multiselect.js +++ b/keymap/multiselect.js @@ -36,11 +36,6 @@ cm.addSelection(cur.from(), cur.to()); }; - // Go to a single selection - pc["Alt-Esc"] = mac["Alt-Esc"] = function(cm) { - cm.setSelection(cm.getCursor("anchor"), cm.getCursor("head")); - }; - // Select matching parts of current selection var dialogText = 'Match: (Use /re/ syntax for regexp)'; pc["Alt-F"] = mac["Alt-F"] = function(cm) { diff --git a/lib/codemirror.js b/lib/codemirror.js index f1a471029d..6e4bf30ba8 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -3760,6 +3760,9 @@ var commands = CodeMirror.commands = { selectAll: function(cm) {cm.setSelection(Pos(cm.firstLine(), 0), Pos(cm.lastLine()));}, + singleSelection: function(cm) { + cm.setSelection(cm.getCursor("anchor"), cm.getCursor("head")); + }, killLine: function(cm) { deleteNearSelection(cm, function(range) { if (range.empty()) { @@ -3879,7 +3882,8 @@ "End": "goLineEnd", "Home": "goLineStartSmart", "PageUp": "goPageUp", "PageDown": "goPageDown", "Delete": "delCharAfter", "Backspace": "delCharBefore", "Shift-Backspace": "delCharBefore", "Tab": "defaultTab", "Shift-Tab": "indentAuto", - "Enter": "newlineAndIndent", "Insert": "toggleOverwrite" + "Enter": "newlineAndIndent", "Insert": "toggleOverwrite", + "Esc": "singleSelection" }; // Note that the save and find-related commands aren't defined by // default. Unknown commands are simply ignored. From 25278eaf7285e6c770378f56e2aa17c78f35f8e9 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 14 Nov 2013 13:38:09 +0100 Subject: [PATCH 0224/4131] [multiselect demo] Update binding list to reflect new Esc binding --- demo/multiselect.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/demo/multiselect.html b/demo/multiselect.html index 3babdb9353..aff0aebeb8 100644 --- a/demo/multiselect.html +++ b/demo/multiselect.html @@ -38,7 +38,7 @@

    Multiple Selection Keybindings

    Ctrl-D / Cmd-D: Add next occurrence of current selection as another selection. -Alt-Esc / Alt-Esc: +Esc: Deselect all but the primary selection. Alt-F: From 59941dadc24891303afd104b9327f8bf5fce17cc Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Sat, 16 Nov 2013 10:56:58 +0100 Subject: [PATCH 0225/4131] Check for empty history in setSelectionAddToHistory Issue #1961 --- lib/codemirror.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/codemirror.js b/lib/codemirror.js index 6e4bf30ba8..ad4fdabee7 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -2734,7 +2734,8 @@ function setSelectionAddToHistory(doc, sel) { setSelection(doc, sel); - lst(doc.history.done).selAfter = sel; + var lstSel = lst(doc.history.done); + if (lstSel) lstSel.selAfter = sel; } function filterSelectionChange(doc, sel) { From 6d14685784908e76cdbebd542bea3a33ed7e2409 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Tue, 19 Nov 2013 19:03:19 +0100 Subject: [PATCH 0226/4131] Fix right-click menu --- lib/codemirror.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/codemirror.js b/lib/codemirror.js index ad4fdabee7..c4ddc491ac 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -2349,8 +2349,8 @@ // Reset the current text selection only if the click is done outside of the selection // and 'resetSelectionOnContextMenu' option is true. var reset = cm.options.resetSelectionOnContextMenu; - if (reset && !cm.doc.sel.contains(pos) > -1) - operation(cm, setSelection)(cm.doc, pos, pos); + if (reset && cm.doc.sel.contains(pos) == -1) + operation(cm, setSelection)(cm.doc, simpleSelection(pos)); var oldCSS = display.input.style.cssText; display.inputDiv.style.position = "absolute"; From 25aee733d7a8af3cb1e31f19496ed4274b13afa4 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 25 Nov 2013 16:23:53 +0100 Subject: [PATCH 0227/4131] Remove stray call to ES5-style indexOf Closes #1989 --- lib/codemirror.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/codemirror.js b/lib/codemirror.js index c4ddc491ac..22860064a4 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -821,7 +821,7 @@ function normalizeSelection(ranges, primIndex) { var prim = ranges[primIndex]; ranges.sort(function(a, b) { return cmp(a.from(), b.from()); }); - primIndex = ranges.indexOf(prim); + primIndex = indexOf(ranges, prim); for (var i = 1; i < ranges.length; i++) { var cur = ranges[i], prev = ranges[i - 1]; if (cmp(prev.to(), cur.from()) >= 0) { From 07a8e563d6e5d960346e8ee03f8cdd50a3b05f37 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Fri, 29 Nov 2013 21:51:16 +0100 Subject: [PATCH 0228/4131] [gfm and rst modes] Mark dependencies on overlay addon Closes #2015 --- mode/gfm/gfm.js | 4 ++-- mode/rst/rst.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/mode/gfm/gfm.js b/mode/gfm/gfm.js index 7bd5f5ab42..8fcc9f70a7 100644 --- a/mode/gfm/gfm.js +++ b/mode/gfm/gfm.js @@ -1,8 +1,8 @@ (function(mod) { if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror"), require("../markdown/markdown")); + mod(require("../../lib/codemirror"), require("../markdown/markdown"), require("../../addon/mode/overlay")); else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror", "../markdown/markdown"], mod); + define(["../../lib/codemirror", "../markdown/markdown", "../../addon/mode/overlay"], mod); else // Plain browser env mod(CodeMirror); })(function(CodeMirror) { diff --git a/mode/rst/rst.js b/mode/rst/rst.js index c53cbc36e8..01c6a05650 100644 --- a/mode/rst/rst.js +++ b/mode/rst/rst.js @@ -1,8 +1,8 @@ (function(mod) { if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror"), require("../python/python"), require("../stex/stex")); + mod(require("../../lib/codemirror"), require("../python/python"), require("../stex/stex"), require("../../addon/mode/overlay")); else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror", "../python/python", "../stex/stex"], mod); + define(["../../lib/codemirror", "../python/python", "../stex/stex", "../../addon/mode/overlay"], mod); else // Plain browser env mod(CodeMirror); })(function(CodeMirror) { From 0014d6621c986ebb06afebf8a2a751b855835da8 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 9 Dec 2013 18:53:26 +0100 Subject: [PATCH 0229/4131] Fix unintended change in anchor/head orientation on double-click Issue #2038 --- lib/codemirror.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/codemirror.js b/lib/codemirror.js index 22860064a4..3c790f88e9 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -1929,12 +1929,12 @@ var range = findWordAt(getLine(doc, pos.line).text, pos); else var range = {from: Pos(pos.line, 0), to: clipPos(doc, Pos(pos.line + 1, 0))}; - if (cmp(range.from, anchor) < 0) { - head = range.from; - anchor = maxPos(oldRange.to(), range.to); - } else { + if (cmp(range.to, anchor) > 0) { head = range.to; anchor = minPos(oldRange.from(), range.from); + } else { + head = range.from; + anchor = maxPos(oldRange.to(), range.to); } } var ranges = startSel.ranges.slice(0); From c35d06a8d5a4070f64cf05e356f7679e947646d8 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 12 Dec 2013 13:51:28 +0100 Subject: [PATCH 0230/4131] Remove onDragEvent and onKeyEvent options --- doc/manual.html | 37 +------------------------------------ doc/upgrade_v4.html | 8 +++++--- lib/codemirror.js | 21 +++++---------------- 3 files changed, 11 insertions(+), 55 deletions(-) diff --git a/doc/manual.html b/doc/manual.html index 9a2424eb48..88ed81ef70 100644 --- a/doc/manual.html +++ b/doc/manual.html @@ -361,38 +361,6 @@

    Configuration

    dragDrop: boolean
    Controls whether drag-and-drop is enabled. On by default.
    -
    onDragEvent: function(instance: CodeMirror, event: Event) → boolean
    -
    Deprecated! See these event - handlers for the current recommended approach.
    When given, - this will be called when the editor is handling - a dragenter, dragover, - or drop event. It will be passed the editor - instance and the event object as arguments. The callback can - choose to handle the event itself, in which case it should - return true to indicate that CodeMirror should not - do anything further.
    - -
    onKeyEvent: function(instance: CodeMirror, event: Event) → boolean
    -
    Deprecated! See these event - handlers for the current recommended approach.
    This - provides a rather low-level hook into CodeMirror's key handling. - If provided, this function will be called on - every keydown, keyup, - and keypress event that CodeMirror captures. It - will be passed two arguments, the editor instance and the key - event. This key event is pretty much the raw key event, except - that a stop() method is always added to it. You - could feed it to, for example, jQuery.Event to - further normalize it.
    This function can inspect the key - event, and handle it if it wants to. It may return true to tell - CodeMirror to ignore the event. Be wary that, on some browsers, - stopping a keydown does not stop - the keypress from firing, whereas on others it - does. If you respond to an event, you should probably inspect - its type property and only do something when it - is keydown (or keypress for actions - that need character data).
    -
    cursorBlinkRate: number
    Half-period in milliseconds used for cursor blinking. The default blink rate is 530ms. By setting this to zero, blinking can be disabled.
    @@ -414,16 +382,13 @@

    Configuration

    click outside of the current selection, the cursor is moved to the point of the click. Defaults to true. -
    workTime, workDelay: number
    +
    workTime, workDelay: number
    Highlighting is done by a pseudo background-thread that will work for workTime milliseconds, and then use timeout to sleep for workDelay milliseconds. The defaults are 200 and 300, you can change these options to make the highlighting more or less aggressive.
    -
    workDelay: number
    -
    See workTime.
    -
    pollInterval: number
    Indicates how quickly CodeMirror should poll its input textarea for changes (when focused). Most input is captured by diff --git a/doc/upgrade_v4.html b/doc/upgrade_v4.html index d390228682..55dbbda305 100644 --- a/doc/upgrade_v4.html +++ b/doc/upgrade_v4.html @@ -82,10 +82,12 @@

    Upgrading to version 4

    Deprecated interfaces dropped

    -

    A few properties that have been deprecated for a while are now -gone. Most notably, the names for folding and completing functions +

    A few properties and methods that have been deprecated for a while +are now gone. Most notably, the onKeyEvent and onDragEvent options (use the corresponding events instead).

    + +

    The long names for folding and completing functions (CodeMirror.braceRangeFinder, CodeMirror.javascriptHint, -etc) are now gone +etc) are also gone (use CodeMirror.fold.brace, CodeMirror.hint.javascript).

    The className property in the return value diff --git a/lib/codemirror.js b/lib/codemirror.js index 3c790f88e9..aaa989dfc6 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -1719,7 +1719,7 @@ setTimeout(unregister, 5000); on(d.input, "keyup", operation(cm, function(e) { - if (signalDOMEvent(cm, e) || cm.options.onKeyEvent && cm.options.onKeyEvent(cm, addStop(e))) return; + if (signalDOMEvent(cm, e)) return; if (e.keyCode == 16) cm.display.shift = false; })); on(d.input, "input", function() { @@ -1732,7 +1732,7 @@ on(d.input, "blur", bind(onBlur, cm)); function drag_(e) { - if (signalDOMEvent(cm, e) || cm.options.onDragEvent && cm.options.onDragEvent(cm, addStop(e))) return; + if (signalDOMEvent(cm, e)) return; e_stop(e); } if (cm.options.dragDrop) { @@ -2030,7 +2030,7 @@ function onDrop(e) { var cm = this; - if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e) || (cm.options.onDragEvent && cm.options.onDragEvent(cm, addStop(e)))) + if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e)) return; e_preventDefault(e); if (ie) lastDrop = +new Date; @@ -2285,12 +2285,11 @@ function onKeyDown(e) { var cm = this; if (!cm.state.focused) onFocus(cm); - if (signalDOMEvent(cm, e) || cm.options.onKeyEvent && cm.options.onKeyEvent(cm, addStop(e))) return; + if (signalDOMEvent(cm, e)) return; if (old_ie && e.keyCode == 27) e.returnValue = false; var code = e.keyCode; // IE does strange things with escape. cm.display.shift = code == 16 || e.shiftKey; - // First give onKeyEvent option a chance to handle this. var handled = handleKeyBinding(cm, e); if (opera) { lastStoppedKey = handled ? code : null; @@ -2302,7 +2301,7 @@ function onKeyPress(e) { var cm = this; - if (signalDOMEvent(cm, e) || cm.options.onKeyEvent && cm.options.onKeyEvent(cm, addStop(e))) return; + if (signalDOMEvent(cm, e)) return; var keyCode = e.keyCode, charCode = e.charCode; if (opera && keyCode == lastStoppedKey) {lastStoppedKey = null; e_preventDefault(e); return;} if (((opera && (!e.which || e.which < 10)) || khtml) && handleKeyBinding(cm, e)) return; @@ -3576,9 +3575,6 @@ option("keyMap", "default", keyMapChanged); option("extraKeys", null); - option("onKeyEvent", null); - option("onDragEvent", null); - option("lineWrapping", false, wrappingChanged, true); option("gutters", [], function(cm) { setGuttersForLineNumbers(cm.options); @@ -5738,13 +5734,6 @@ // EVENT OPERATORS - function stopMethod() {e_stop(this);} - // Ensure an event has a stop method. - function addStop(event) { - if (!event.stop) event.stop = stopMethod; - return event; - } - function e_preventDefault(e) { if (e.preventDefault) e.preventDefault(); else e.returnValue = false; From 06220807ee4d80f7142ff3c343a360d19b4b74a5 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Fri, 13 Dec 2013 16:12:13 +0100 Subject: [PATCH 0231/4131] Change TextMarker.find to allow more control over result And use this to cut some indirection in its callers. --- lib/codemirror.js | 111 ++++++++++++++++++++++++---------------------- 1 file changed, 58 insertions(+), 53 deletions(-) diff --git a/lib/codemirror.js b/lib/codemirror.js index aaa989dfc6..5996ecb111 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -283,19 +283,19 @@ gutters.style.display = i ? "" : "none"; } - function lineLength(doc, line) { + function lineLength(line) { if (line.height == 0) return 0; var len = line.text.length, merged, cur = line; while (merged = collapsedSpanAtStart(cur)) { - var found = merged.find(); - cur = getLine(doc, found.from.line); + var found = merged.find(0, true); + cur = found.from.line; len += found.from.ch - found.to.ch; } cur = line; while (merged = collapsedSpanAtEnd(cur)) { - var found = merged.find(); + var found = merged.find(0, true); len -= cur.text.length - found.from.ch; - cur = getLine(doc, found.to.line); + cur = found.to.line; len += cur.text.length - found.to.ch; } return len; @@ -304,10 +304,10 @@ function computeMaxLength(cm) { var d = cm.display, doc = cm.doc; d.maxLine = getLine(doc, doc.first); - d.maxLineLength = lineLength(doc, d.maxLine); + d.maxLineLength = lineLength(d.maxLine); d.maxLineChanged = true; doc.iter(function(line) { - var len = lineLength(doc, line); + var len = lineLength(line); if (len > d.maxLineLength) { d.maxLineLength = len; d.maxLine = line; @@ -489,7 +489,7 @@ if (display.showingFrom < from && from - display.showingFrom < 20) from = Math.max(doc.first, display.showingFrom); if (display.showingTo > to && display.showingTo - to < 20) to = Math.min(end, display.showingTo); if (sawCollapsedSpans) { - from = lineNo(visualLine(doc, getLine(doc, from))); + from = lineNo(visualLine(getLine(doc, from))); while (to < end && lineIsHidden(doc, getLine(doc, to))) ++to; } @@ -506,7 +506,7 @@ for (var i = 0; i < intact.length; ++i) { var range = intact[i], merged; while (merged = collapsedSpanAtEnd(getLine(doc, range.to - 1))) { - var newTo = merged.find().from.line; + var newTo = merged.find(-1).line; if (newTo > range.from) range.to = newTo; else { intact.splice(i--, 1); break; } } @@ -577,7 +577,7 @@ } function updateViewOffset(cm) { - var off = cm.display.viewOffset = heightAtLine(cm, getLine(cm.doc, cm.display.showingFrom)); + var off = cm.display.viewOffset = heightAtLine(getLine(cm.doc, cm.display.showingFrom)); // Position the mover div to align with the current virtual scroll position cm.display.mover.style.top = off + "px"; } @@ -951,7 +951,7 @@ drawForLine(sFrom.line, sFrom.ch, sTo.ch); } else { var fromLine = getLine(doc, sFrom.line), toLine = getLine(doc, sTo.line); - var singleVLine = visualLine(doc, fromLine) == visualLine(doc, toLine); + var singleVLine = visualLine(fromLine) == visualLine(toLine); var leftEnd = drawForLine(sFrom.line, sFrom.ch, singleVLine ? fromLine.text.length : null).end; var rightStart = drawForLine(sTo.line, singleVLine ? 0 : null, sTo.ch).start; if (singleVLine) { @@ -1258,7 +1258,7 @@ } if (context == "line") return rect; if (!context) context = "local"; - var yOff = heightAtLine(cm, lineObj); + var yOff = heightAtLine(lineObj); if (context == "local") yOff += paddingTop(cm.display); else yOff -= cm.display.viewOffset; if (context == "page" || context == "window") { @@ -1337,25 +1337,25 @@ var doc = cm.doc; y += cm.display.viewOffset; if (y < 0) return PosWithInfo(doc.first, 0, true, -1); - var lineNo = lineAtHeight(doc, y), last = doc.first + doc.size - 1; - if (lineNo > last) + var lineN = lineAtHeight(doc, y), last = doc.first + doc.size - 1; + if (lineN > last) return PosWithInfo(doc.first + doc.size - 1, getLine(doc, last).text.length, true, 1); if (x < 0) x = 0; + var lineObj = getLine(doc, lineN); for (;;) { - var lineObj = getLine(doc, lineNo); - var found = coordsCharInner(cm, lineObj, lineNo, x, y); + var found = coordsCharInner(cm, lineObj, lineN, x, y); var merged = collapsedSpanAtEnd(lineObj); - var mergedPos = merged && merged.find(); + var mergedPos = merged && merged.find(0, true); if (merged && (found.ch > mergedPos.from.ch || found.ch == mergedPos.from.ch && found.xRel > 0)) - lineNo = mergedPos.to.line; + lineN = lineNo(lineObj = mergedPos.to.line); else return found; } } function coordsCharInner(cm, lineObj, lineNo, x, y) { - var innerOff = y - heightAtLine(cm, lineObj); + var innerOff = y - heightAtLine(lineObj); var wrongLine = false, adjust = 2 * cm.display.wrapper.clientWidth; var measurement = measureLine(cm, lineObj); @@ -2601,7 +2601,7 @@ var recomputeMaxLength = false, checkWidthStart = from.line; if (!cm.options.lineWrapping) { - checkWidthStart = lineNo(visualLine(doc, getLine(doc, from.line))); + checkWidthStart = lineNo(visualLine(getLine(doc, from.line))); doc.iter(checkWidthStart, to.line + 1, function(line) { if (line == display.maxLine) { recomputeMaxLength = true; @@ -2617,7 +2617,7 @@ if (!cm.options.lineWrapping) { doc.iter(checkWidthStart, from.line + change.text.length, function(line) { - var len = lineLength(doc, line); + var len = lineLength(line); if (len > display.maxLineLength) { display.maxLine = line; display.maxLineLength = len; @@ -2814,7 +2814,7 @@ } } if (!m.atomic) continue; - var newPos = m.find()[dir < 0 ? "from" : "to"]; + var newPos = m.find(dir < 0 ? -1 : 1); if (cmp(newPos, curPos) == 0) { newPos.ch += dir; if (newPos.ch < 0) { @@ -4123,7 +4123,7 @@ updateLineHeight(line, textHeight(cm.display)); } if (cm && this.collapsed && !cm.options.lineWrapping) for (var i = 0; i < this.lines.length; ++i) { - var visual = visualLine(cm.doc, this.lines[i]), len = lineLength(cm.doc, visual); + var visual = visualLine(this.lines[i]), len = lineLength(visual); if (len > cm.display.maxLineLength) { cm.display.maxLine = visual; cm.display.maxLineLength = len; @@ -4141,28 +4141,31 @@ if (withOp) endOperation(cm); }; - TextMarker.prototype.find = function(bothSides) { + // Side can be 0 (both), -1 (left), 1 (right) + TextMarker.prototype.find = function(side, lineObj) { + if (side == null && this.type == "bookmark") side = 1; var from, to; for (var i = 0; i < this.lines.length; ++i) { var line = this.lines[i]; var span = getMarkedSpanFor(line.markedSpans, this); - if (span.from != null || span.to != null) { - var found = lineNo(line); - if (span.from != null) from = Pos(found, span.from); - if (span.to != null) to = Pos(found, span.to); + if (span.from != null) { + from = Pos(lineObj ? line : lineNo(line), span.from); + if (side == -1) return from; + } + if (span.to != null) { + to = Pos(lineObj ? line : lineNo(line), span.to); + if (side == 1) return to; } } - if (this.type == "bookmark" && !bothSides) return from; return from && {from: from, to: to}; }; TextMarker.prototype.changed = function() { - var pos = this.find(), cm = this.doc.cm; + var pos = this.find(-1, true), cm = this.doc.cm; if (!pos || !cm) return; - if (this.type != "bookmark") pos = pos.from; - var line = getLine(this.doc, pos.line); + var line = pos.line, lineN = lineNo(pos.line); clearCachedMeasurement(cm, line); - if (pos.line >= cm.display.showingFrom && pos.line < cm.display.showingTo) { + if (lineN >= cm.display.showingFrom && lineN < cm.display.showingTo) { for (var node = cm.display.lineDiv.firstChild; node; node = node.nextSibling) if (node.lineObj == line) { if (node.offsetHeight != line.height) updateLineHeight(line, node.offsetHeight); break; @@ -4216,7 +4219,7 @@ var curLine = from.line, cm = doc.cm, updateMaxLine; doc.iter(curLine, to.line + 1, function(line) { - if (cm && marker.collapsed && !cm.options.lineWrapping && visualLine(doc, line) == cm.display.maxLine) + if (cm && marker.collapsed && !cm.options.lineWrapping && visualLine(line) == cm.display.maxLine) updateMaxLine = true; var span = {from: null, to: null, marker: marker}; if (curLine == from.line) span.from = from.ch; @@ -4269,8 +4272,8 @@ this.markers[i].clear(); signalLater(this, "clear"); }; - SharedTextMarker.prototype.find = function() { - return this.primary.find(); + SharedTextMarker.prototype.find = function(side, lineObj) { + return this.primary.find(side, lineObj); }; function markTextShared(doc, from, to, options, type) { @@ -4437,7 +4440,7 @@ if (!markers) return null; var parts = [{from: from, to: to}]; for (var i = 0; i < markers.length; ++i) { - var mk = markers[i], m = mk.find(); + var mk = markers[i], m = mk.find(0); for (var j = 0; j < parts.length; ++j) { var p = parts[j]; if (cmp(p.to, m.from) < 0 || cmp(p.from, m.to) > 0) continue; @@ -4486,7 +4489,7 @@ if (sps) for (var i = 0; i < sps.length; ++i) { var sp = sps[i]; if (!sp.marker.collapsed) continue; - var found = sp.marker.find(true); + var found = sp.marker.find(0); var fromCmp = cmp(found.from, from) || extraLeft(sp.marker) - extraLeft(marker); var toCmp = cmp(found.to, to) || extraRight(sp.marker) - extraRight(marker); if (fromCmp >= 0 && toCmp <= 0 || fromCmp <= 0 && toCmp >= 0) continue; @@ -4496,10 +4499,10 @@ } } - function visualLine(doc, line) { + function visualLine(line) { var merged; while (merged = collapsedSpanAtStart(line)) - line = getLine(doc, merged.find().from.line); + line = merged.find(-1, true).line; return line; } @@ -4516,8 +4519,8 @@ } function lineIsHiddenInner(doc, line, span) { if (span.to == null) { - var end = span.marker.find().to, endLine = getLine(doc, end.line); - return lineIsHiddenInner(doc, endLine, getMarkedSpanFor(endLine.markedSpans, span.marker)); + var end = span.marker.find(1, true); + return lineIsHiddenInner(doc, end.line, getMarkedSpanFor(end.line.markedSpans, span.marker)); } if (span.marker.inclusiveRight && span.to == line.text.length) return true; @@ -4568,7 +4571,7 @@ if (no == null || !ws) return; for (var i = 0; i < ws.length; ++i) if (ws[i] == this) ws.splice(i--, 1); if (!ws.length) this.line.widgets = null; - var aboveVisible = heightAtLine(this.cm, this.line) < this.cm.doc.scrollTop; + var aboveVisible = heightAtLine(this.line) < this.cm.doc.scrollTop; updateLineHeight(this.line, Math.max(0, this.line.height - widgetHeight(this))); if (aboveVisible) addToScrollPos(this.cm, 0, -this.height); regChange(this.cm, no, no + 1); @@ -4599,7 +4602,7 @@ else widgets.splice(Math.min(widgets.length - 1, Math.max(0, widget.insertAt)), 0, widget); widget.line = line; if (!lineIsHidden(cm.doc, line) || widget.showIfHidden) { - var aboveVisible = heightAtLine(cm, line) < cm.doc.scrollTop; + var aboveVisible = heightAtLine(line) < cm.doc.scrollTop; updateLineHeight(line, line.height + widgetHeight(widget)); if (aboveVisible) addToScrollPos(cm, 0, widget.height); } @@ -4751,7 +4754,7 @@ function buildLineContent(cm, realLine, measure, copyWidgets) { var merged, line = realLine, empty = true; while (merged = collapsedSpanAtStart(line)) - line = getLine(cm.doc, merged.find().from.line); + line = merged.find(-1, true).line; var builder = {pre: elt("pre"), col: 0, pos: 0, measure: null, measuredSomething: false, cm: cm, @@ -5216,7 +5219,7 @@ getLineHandleVisualStart: function(line) { if (typeof line == "number") line = getLine(this, line); - return visualLine(this, line); + return visualLine(line); }, lineCount: function() {return this.size;}, @@ -5534,8 +5537,8 @@ return n + i; } - function heightAtLine(cm, lineObj) { - lineObj = visualLine(cm.doc, lineObj); + function heightAtLine(lineObj) { + lineObj = visualLine(lineObj); var h = 0, chunk = lineObj.parent; for (var i = 0; i < chunk.lines.length; ++i) { @@ -6112,19 +6115,21 @@ function lineStart(cm, lineN) { var line = getLine(cm.doc, lineN); - var visual = visualLine(cm.doc, line); + var visual = visualLine(line); if (visual != line) lineN = lineNo(visual); var order = getOrder(visual); var ch = !order ? 0 : order[0].level % 2 ? lineRight(visual) : lineLeft(visual); return Pos(lineN, ch); } function lineEnd(cm, lineN) { - var merged, line; - while (merged = collapsedSpanAtEnd(line = getLine(cm.doc, lineN))) - lineN = merged.find().to.line; + var merged, line = getLine(cm.doc, lineN); + while (merged = collapsedSpanAtEnd(line)) { + line = merged.find(1, true).line; + lineN = null; + } var order = getOrder(line); var ch = !order ? line.text.length : order[0].level % 2 ? lineLeft(line) : lineRight(line); - return Pos(lineN, ch); + return Pos(lineN == null ? lineNo(line) : lineN, ch); } function compareBidiLevel(order, a, b) { From b9c1db55da9e2b0228d2ecc4804de7b6764580ad Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Fri, 13 Dec 2013 20:37:50 +0100 Subject: [PATCH 0232/4131] Upgrade in-tree acorn --- test/lint/acorn.js | 636 +++++++++++++++++++++++++++++---------------- test/lint/walk.js | 203 +++++++++++---- 2 files changed, 555 insertions(+), 284 deletions(-) diff --git a/test/lint/acorn.js b/test/lint/acorn.js index 6323b1fc6a..bbd32cfcea 100644 --- a/test/lint/acorn.js +++ b/test/lint/acorn.js @@ -12,13 +12,24 @@ // Please use the [github bug tracker][ghbt] to report issues. // // [ghbt]: https://github.com/marijnh/acorn/issues - -(function(exports) { +// +// This file defines the main parser interface. The library also comes +// with a [error-tolerant parser][dammit] and an +// [abstract syntax tree walker][walk], defined in other files. +// +// [dammit]: acorn_loose.js +// [walk]: util/walk.js + +(function(root, mod) { + if (typeof exports == "object" && typeof module == "object") return mod(exports); // CommonJS + if (typeof define == "function" && define.amd) return define(["exports"], mod); // AMD + mod(root.acorn || (root.acorn = {})); // Plain browser env +})(this, function(exports) { "use strict"; - exports.version = "0.0.1"; + exports.version = "0.4.1"; - // The main exported interface (under `window.acorn` when in the + // The main exported interface (under `self.acorn` when in the // browser) is a `parse` function that takes a code string and // returns an abstract syntax tree as specified by [Mozilla parser // API][api], with the caveat that the SpiderMonkey-specific syntax @@ -30,10 +41,8 @@ exports.parse = function(inpt, opts) { input = String(inpt); inputLen = input.length; - options = opts || {}; - for (var opt in defaultOptions) if (!options.hasOwnProperty(opt)) - options[opt] = defaultOptions[opt]; - sourceFile = options.sourceFile || null; + setOptions(opts); + initTokenState(); return parseTopLevel(options.program); }; @@ -55,18 +64,22 @@ // By default, reserved words are not enforced. Enable // `forbidReserved` to enforce them. forbidReserved: false, - // When `trackComments` is turned on, the parser will attach - // `commentsBefore` and `commentsAfter` properties to AST nodes - // holding arrays of strings. A single comment may appear in both - // a `commentsBefore` and `commentsAfter` array (of the nodes - // after and before it), but never twice in the before (or after) - // array of different nodes. - trackComments: false, // When `locations` is on, `loc` properties holding objects with // `start` and `end` properties in `{line, column}` form (with // line being 1-based and column 0-based) will be attached to the // nodes. locations: false, + // A function can be passed as `onComment` option, which will + // cause Acorn to call that function with `(block, text, start, + // end)` parameters whenever a comment is skipped. `block` is a + // boolean indicating whether this is a block (`/* */`) comment, + // `text` is the content of the comment, and `start` and `end` are + // character offsets that denote the start and end of the comment. + // When the `locations` option is on, two more parameters are + // passed, the full `{line, column}` locations of the start and + // end of the comments. Note that you are not allowed to call the + // parser from the callback—that will corrupt its internal state. + onComment: null, // Nodes have their start and end characters offsets recorded in // `start` and `end` properties (directly on the node, rather than // the `loc` object, which holds line/column data. To also add a @@ -82,11 +95,21 @@ // toplevel forms of the parsed file to the `Program` (top) node // of an existing parse tree. program: null, - // When `location` is on, you can pass this to record the source + // When `locations` is on, you can pass this to record the source // file in every node's `loc` object. - sourceFile: null + sourceFile: null, + // This value, if given, is stored in every node, whether + // `locations` is on or off. + directSourceFile: null }; + function setOptions(opts) { + options = opts || {}; + for (var opt in defaultOptions) if (!Object.prototype.hasOwnProperty.call(options, opt)) + options[opt] = defaultOptions[opt]; + sourceFile = options.sourceFile || null; + } + // The `getLineInfo` function is mostly useful when the // `locations` option is off (for performance reasons) and you // want to find the line/column position for a given character @@ -106,9 +129,44 @@ }; // Acorn is organized as a tokenizer and a recursive-descent parser. - // Both use (closure-)global variables to keep their state and - // communicate. We already saw the `options`, `input`, and - // `inputLen` variables above (set in `parse`). + // The `tokenize` export provides an interface to the tokenizer. + // Because the tokenizer is optimized for being efficiently used by + // the Acorn parser itself, this interface is somewhat crude and not + // very modular. Performing another parse or call to `tokenize` will + // reset the internal state, and invalidate existing tokenizers. + + exports.tokenize = function(inpt, opts) { + input = String(inpt); inputLen = input.length; + setOptions(opts); + initTokenState(); + + var t = {}; + function getToken(forceRegexp) { + readToken(forceRegexp); + t.start = tokStart; t.end = tokEnd; + t.startLoc = tokStartLoc; t.endLoc = tokEndLoc; + t.type = tokType; t.value = tokVal; + return t; + } + getToken.jumpTo = function(pos, reAllowed) { + tokPos = pos; + if (options.locations) { + tokCurLine = 1; + tokLineStart = lineBreak.lastIndex = 0; + var match; + while ((match = lineBreak.exec(input)) && match.index < pos) { + ++tokCurLine; + tokLineStart = match.index + match[0].length; + } + } + tokRegexpAllowed = reAllowed; + skipSpace(); + }; + return getToken; + }; + + // State is kept in (closure-)global variables. We already saw the + // `options`, `input`, and `inputLen` variables above. // The current position of the tokenizer in the input. @@ -133,11 +191,6 @@ var tokType, tokVal; - // These are used to hold arrays of comments when - // `options.trackComments` is true. - - var tokCommentsBefore, tokCommentsAfter; - // Interal state for the tokenizer. To distinguish between division // operators and regular expressions, it remembers whether the last // token was one that is allowed to be followed by an expression. @@ -145,13 +198,13 @@ // division operator. See the `parseStatement` function for a // caveat.) - var tokRegexpAllowed, tokComments; + var tokRegexpAllowed; // When `options.locations` is true, these are used to keep // track of the current line, and know when a new line has been - // entered. See the `curLineLoc` function. + // entered. - var tokCurLine, tokLineStart, tokLineStartNext; + var tokCurLine, tokLineStart; // These store the position of the previous token, which is useful // when finishing a node and assigning its `end` position. @@ -166,17 +219,23 @@ var inFunction, labels, strict; // This function is used to raise exceptions on parse errors. It - // takes either a `{line, column}` object or an offset integer (into - // the current `input`) as `pos` argument. It attaches the position - // to the end of the error message, and then raises a `SyntaxError` - // with that message. + // takes an offset integer (into the current `input`) to indicate + // the location of the error, attaches the position to the end + // of the error message, and then raises a `SyntaxError` with that + // message. function raise(pos, message) { - if (typeof pos == "number") pos = getLineInfo(input, pos); - message += " (" + pos.line + ":" + pos.column + ")"; - throw new SyntaxError(message); + var loc = getLineInfo(input, pos); + message += " (" + loc.line + ":" + loc.column + ")"; + var err = new SyntaxError(message); + err.pos = pos; err.loc = loc; err.raisedAt = tokPos; + throw err; } + // Reused empty array added for node fields that are always empty. + + var empty = []; + // ## Token types // The assignment of fine-grained, information-carrying type objects @@ -233,10 +292,10 @@ "function": _function, "if": _if, "return": _return, "switch": _switch, "throw": _throw, "try": _try, "var": _var, "while": _while, "with": _with, "null": _null, "true": _true, "false": _false, "new": _new, "in": _in, - "instanceof": {keyword: "instanceof", binop: 7}, "this": _this, - "typeof": {keyword: "typeof", prefix: true}, - "void": {keyword: "void", prefix: true}, - "delete": {keyword: "delete", prefix: true}}; + "instanceof": {keyword: "instanceof", binop: 7, beforeExpr: true}, "this": _this, + "typeof": {keyword: "typeof", prefix: true, beforeExpr: true}, + "void": {keyword: "void", prefix: true, beforeExpr: true}, + "delete": {keyword: "delete", prefix: true, beforeExpr: true}}; // Punctuation token types. Again, the `type` property is purely for debugging. @@ -262,13 +321,27 @@ // in AssignmentExpression nodes. var _slash = {binop: 10, beforeExpr: true}, _eq = {isAssign: true, beforeExpr: true}; - var _assign = {isAssign: true, beforeExpr: true}, _plusmin = {binop: 9, prefix: true, beforeExpr: true}; - var _incdec = {postfix: true, prefix: true, isUpdate: true}, _prefix = {prefix: true, beforeExpr: true}; - var _bin1 = {binop: 1, beforeExpr: true}, _bin2 = {binop: 2, beforeExpr: true}; - var _bin3 = {binop: 3, beforeExpr: true}, _bin4 = {binop: 4, beforeExpr: true}; - var _bin5 = {binop: 5, beforeExpr: true}, _bin6 = {binop: 6, beforeExpr: true}; - var _bin7 = {binop: 7, beforeExpr: true}, _bin8 = {binop: 8, beforeExpr: true}; - var _bin10 = {binop: 10, beforeExpr: true}; + var _assign = {isAssign: true, beforeExpr: true}; + var _incDec = {postfix: true, prefix: true, isUpdate: true}, _prefix = {prefix: true, beforeExpr: true}; + var _logicalOR = {binop: 1, beforeExpr: true}; + var _logicalAND = {binop: 2, beforeExpr: true}; + var _bitwiseOR = {binop: 3, beforeExpr: true}; + var _bitwiseXOR = {binop: 4, beforeExpr: true}; + var _bitwiseAND = {binop: 5, beforeExpr: true}; + var _equality = {binop: 6, beforeExpr: true}; + var _relational = {binop: 7, beforeExpr: true}; + var _bitShift = {binop: 8, beforeExpr: true}; + var _plusMin = {binop: 9, prefix: true, beforeExpr: true}; + var _multiplyModulo = {binop: 10, beforeExpr: true}; + + // Provide access to the token types for external users of the + // tokenizer. + + exports.tokTypes = {bracketL: _bracketL, bracketR: _bracketR, braceL: _braceL, braceR: _braceR, + parenL: _parenL, parenR: _parenR, comma: _comma, semi: _semi, colon: _colon, + dot: _dot, question: _question, slash: _slash, eq: _eq, name: _name, eof: _eof, + num: _num, regexp: _regexp, string: _string}; + for (var kw in keywordTypes) exports.tokTypes["_" + kw] = keywordTypes[kw]; // This is a trick taken from Esprima. It turns out that, on // non-Chrome browsers, to check whether a string is in a set, a @@ -345,9 +418,9 @@ // are only applied when a character is found to actually have a // code point above 128. - var nonASCIIwhitespace = /[\u1680\u180e\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff]/; + var nonASCIIwhitespace = /[\u1680\u180e\u2000-\u200a\u202f\u205f\u3000\ufeff]/; var nonASCIIidentifierStartChars = "\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05d0-\u05ea\u05f0-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u08a0\u08a2-\u08ac\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0977\u0979-\u097f\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d\u0c58\u0c59\u0c60\u0c61\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d60\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f0\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1877\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191c\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19c1-\u19c7\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4b\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1ce9-\u1cec\u1cee-\u1cf1\u1cf5\u1cf6\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2e2f\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fcc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua697\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua793\ua7a0-\ua7aa\ua7f8-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa80-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc"; - var nonASCIIidentifierChars = "\u0371-\u0374\u0483-\u0487\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u0620-\u0649\u0672-\u06d3\u06e7-\u06e8\u06fb-\u06fc\u0730-\u074a\u0800-\u0814\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0840-\u0857\u08e4-\u08fe\u0900-\u0903\u093a-\u093c\u093e-\u094f\u0951-\u0957\u0962-\u0963\u0966-\u096f\u0981-\u0983\u09bc\u09be-\u09c4\u09c7\u09c8\u09d7\u09df-\u09e0\u0a01-\u0a03\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a66-\u0a71\u0a75\u0a81-\u0a83\u0abc\u0abe-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ae2-\u0ae3\u0ae6-\u0aef\u0b01-\u0b03\u0b3c\u0b3e-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b56\u0b57\u0b5f-\u0b60\u0b66-\u0b6f\u0b82\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd7\u0be6-\u0bef\u0c01-\u0c03\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62-\u0c63\u0c66-\u0c6f\u0c82\u0c83\u0cbc\u0cbe-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0ce2-\u0ce3\u0ce6-\u0cef\u0d02\u0d03\u0d46-\u0d48\u0d57\u0d62-\u0d63\u0d66-\u0d6f\u0d82\u0d83\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0df2\u0df3\u0e34-\u0e3a\u0e40-\u0e45\u0e50-\u0e59\u0eb4-\u0eb9\u0ec8-\u0ecd\u0ed0-\u0ed9\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f41-\u0f47\u0f71-\u0f84\u0f86-\u0f87\u0f8d-\u0f97\u0f99-\u0fbc\u0fc6\u1000-\u1029\u1040-\u1049\u1067-\u106d\u1071-\u1074\u1082-\u108d\u108f-\u109d\u135d-\u135f\u170e-\u1710\u1720-\u1730\u1740-\u1750\u1772\u1773\u1780-\u17b2\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819\u1920-\u192b\u1930-\u193b\u1951-\u196d\u19b0-\u19c0\u19c8-\u19c9\u19d0-\u19d9\u1a00-\u1a15\u1a20-\u1a53\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1b46-\u1b4b\u1b50-\u1b59\u1b6b-\u1b73\u1bb0-\u1bb9\u1be6-\u1bf3\u1c00-\u1c22\u1c40-\u1c49\u1c5b-\u1c7d\u1cd0-\u1cd2\u1d00-\u1dbe\u1e01-\u1f15\u200c\u200d\u203f\u2040\u2054\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2d81-\u2d96\u2de0-\u2dff\u3021-\u3028\u3099\u309a\ua640-\ua66d\ua674-\ua67d\ua69f\ua6f0-\ua6f1\ua7f8-\ua800\ua806\ua80b\ua823-\ua827\ua880-\ua881\ua8b4-\ua8c4\ua8d0-\ua8d9\ua8f3-\ua8f7\ua900-\ua909\ua926-\ua92d\ua930-\ua945\ua980-\ua983\ua9b3-\ua9c0\uaa00-\uaa27\uaa40-\uaa41\uaa4c-\uaa4d\uaa50-\uaa59\uaa7b\uaae0-\uaae9\uaaf2-\uaaf3\uabc0-\uabe1\uabec\uabed\uabf0-\uabf9\ufb20-\ufb28\ufe00-\ufe0f\ufe20-\ufe26\ufe33\ufe34\ufe4d-\ufe4f\uff10-\uff19\uff3f"; + var nonASCIIidentifierChars = "\u0300-\u036f\u0483-\u0487\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u0620-\u0649\u0672-\u06d3\u06e7-\u06e8\u06fb-\u06fc\u0730-\u074a\u0800-\u0814\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0840-\u0857\u08e4-\u08fe\u0900-\u0903\u093a-\u093c\u093e-\u094f\u0951-\u0957\u0962-\u0963\u0966-\u096f\u0981-\u0983\u09bc\u09be-\u09c4\u09c7\u09c8\u09d7\u09df-\u09e0\u0a01-\u0a03\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a66-\u0a71\u0a75\u0a81-\u0a83\u0abc\u0abe-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ae2-\u0ae3\u0ae6-\u0aef\u0b01-\u0b03\u0b3c\u0b3e-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b56\u0b57\u0b5f-\u0b60\u0b66-\u0b6f\u0b82\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd7\u0be6-\u0bef\u0c01-\u0c03\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62-\u0c63\u0c66-\u0c6f\u0c82\u0c83\u0cbc\u0cbe-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0ce2-\u0ce3\u0ce6-\u0cef\u0d02\u0d03\u0d46-\u0d48\u0d57\u0d62-\u0d63\u0d66-\u0d6f\u0d82\u0d83\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0df2\u0df3\u0e34-\u0e3a\u0e40-\u0e45\u0e50-\u0e59\u0eb4-\u0eb9\u0ec8-\u0ecd\u0ed0-\u0ed9\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f41-\u0f47\u0f71-\u0f84\u0f86-\u0f87\u0f8d-\u0f97\u0f99-\u0fbc\u0fc6\u1000-\u1029\u1040-\u1049\u1067-\u106d\u1071-\u1074\u1082-\u108d\u108f-\u109d\u135d-\u135f\u170e-\u1710\u1720-\u1730\u1740-\u1750\u1772\u1773\u1780-\u17b2\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819\u1920-\u192b\u1930-\u193b\u1951-\u196d\u19b0-\u19c0\u19c8-\u19c9\u19d0-\u19d9\u1a00-\u1a15\u1a20-\u1a53\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1b46-\u1b4b\u1b50-\u1b59\u1b6b-\u1b73\u1bb0-\u1bb9\u1be6-\u1bf3\u1c00-\u1c22\u1c40-\u1c49\u1c5b-\u1c7d\u1cd0-\u1cd2\u1d00-\u1dbe\u1e01-\u1f15\u200c\u200d\u203f\u2040\u2054\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2d81-\u2d96\u2de0-\u2dff\u3021-\u3028\u3099\u309a\ua640-\ua66d\ua674-\ua67d\ua69f\ua6f0-\ua6f1\ua7f8-\ua800\ua806\ua80b\ua823-\ua827\ua880-\ua881\ua8b4-\ua8c4\ua8d0-\ua8d9\ua8f3-\ua8f7\ua900-\ua909\ua926-\ua92d\ua930-\ua945\ua980-\ua983\ua9b3-\ua9c0\uaa00-\uaa27\uaa40-\uaa41\uaa4c-\uaa4d\uaa50-\uaa59\uaa7b\uaae0-\uaae9\uaaf2-\uaaf3\uabc0-\uabe1\uabec\uabed\uabf0-\uabf9\ufb20-\ufb28\ufe00-\ufe0f\ufe20-\ufe26\ufe33\ufe34\ufe4d-\ufe4f\uff10-\uff19\uff3f"; var nonASCIIidentifierStart = new RegExp("[" + nonASCIIidentifierStartChars + "]"); var nonASCIIidentifier = new RegExp("[" + nonASCIIidentifierStartChars + nonASCIIidentifierChars + "]"); @@ -362,17 +435,17 @@ // Test whether a given character code starts an identifier. - function isIdentifierStart(code) { + var isIdentifierStart = exports.isIdentifierStart = function(code) { if (code < 65) return code === 36; if (code < 91) return true; if (code < 97) return code === 95; if (code < 123)return true; return code >= 0xaa && nonASCIIidentifierStart.test(String.fromCharCode(code)); - } + }; // Test whether a given character is part of an identifier. - function isIdentifierChar(code) { + var isIdentifierChar = exports.isIdentifierChar = function(code) { if (code < 48) return code === 36; if (code < 58) return true; if (code < 65) return false; @@ -380,27 +453,16 @@ if (code < 97) return code === 95; if (code < 123)return true; return code >= 0xaa && nonASCIIidentifier.test(String.fromCharCode(code)); - } + }; // ## Tokenizer - // These are used when `options.locations` is on, in order to track - // the current line number and start of line offset, in order to set - // `tokStartLoc` and `tokEndLoc`. - - function nextLineStart() { - lineBreak.lastIndex = tokLineStart; - var match = lineBreak.exec(input); - return match ? match.index + match[0].length : input.length + 1; - } + // These are used when `options.locations` is on, for the + // `tokStartLoc` and `tokEndLoc` properties. - function curLineLoc() { - while (tokLineStartNext <= tokPos) { - ++tokCurLine; - tokLineStart = tokLineStartNext; - tokLineStartNext = nextLineStart(); - } - return {line: tokCurLine, column: tokPos - tokLineStart}; + function line_loc_t() { + this.line = tokCurLine; + this.column = tokPos - tokLineStart; } // Reset the token state. Used at the start of a parse. @@ -408,63 +470,88 @@ function initTokenState() { tokCurLine = 1; tokPos = tokLineStart = 0; - tokLineStartNext = nextLineStart(); tokRegexpAllowed = true; - tokComments = null; skipSpace(); } - // Called at the end of every token. Sets `tokEnd`, `tokVal`, - // `tokCommentsAfter`, and `tokRegexpAllowed`, and skips the space - // after the token, so that the next one's `tokStart` will point at - // the right position. + // Called at the end of every token. Sets `tokEnd`, `tokVal`, and + // `tokRegexpAllowed`, and skips the space after the token, so that + // the next one's `tokStart` will point at the right position. function finishToken(type, val) { tokEnd = tokPos; - if (options.locations) tokEndLoc = curLineLoc(); + if (options.locations) tokEndLoc = new line_loc_t; tokType = type; skipSpace(); tokVal = val; - tokCommentsAfter = tokComments; tokRegexpAllowed = type.beforeExpr; } function skipBlockComment() { - var end = input.indexOf("*/", tokPos += 2); + var startLoc = options.onComment && options.locations && new line_loc_t; + var start = tokPos, end = input.indexOf("*/", tokPos += 2); if (end === -1) raise(tokPos - 2, "Unterminated comment"); - if (options.trackComments) - (tokComments || (tokComments = [])).push(input.slice(tokPos, end)); tokPos = end + 2; + if (options.locations) { + lineBreak.lastIndex = start; + var match; + while ((match = lineBreak.exec(input)) && match.index < tokPos) { + ++tokCurLine; + tokLineStart = match.index + match[0].length; + } + } + if (options.onComment) + options.onComment(true, input.slice(start + 2, end), start, tokPos, + startLoc, options.locations && new line_loc_t); } function skipLineComment() { var start = tokPos; + var startLoc = options.onComment && options.locations && new line_loc_t; var ch = input.charCodeAt(tokPos+=2); - while (tokPos < inputLen && ch !== 10 && ch !== 13 && ch !== 8232 && ch !== 8329) { + while (tokPos < inputLen && ch !== 10 && ch !== 13 && ch !== 8232 && ch !== 8233) { ++tokPos; ch = input.charCodeAt(tokPos); } - (tokComments || (tokComments = [])).push(input.slice(start, tokPos)); + if (options.onComment) + options.onComment(false, input.slice(start + 2, tokPos), start, tokPos, + startLoc, options.locations && new line_loc_t); } // Called at the start of the parse and after every token. Skips - // whitespace and comments, and, if `options.trackComments` is on, - // will store all skipped comments in `tokComments`. + // whitespace and comments, and. function skipSpace() { - tokComments = null; while (tokPos < inputLen) { var ch = input.charCodeAt(tokPos); - if (ch === 47) { // '/' - var next = input.charCodeAt(tokPos+1); + if (ch === 32) { // ' ' + ++tokPos; + } else if (ch === 13) { + ++tokPos; + var next = input.charCodeAt(tokPos); + if (next === 10) { + ++tokPos; + } + if (options.locations) { + ++tokCurLine; + tokLineStart = tokPos; + } + } else if (ch === 10 || ch === 8232 || ch === 8233) { + ++tokPos; + if (options.locations) { + ++tokCurLine; + tokLineStart = tokPos; + } + } else if (ch > 8 && ch < 14) { + ++tokPos; + } else if (ch === 47) { // '/' + var next = input.charCodeAt(tokPos + 1); if (next === 42) { // '*' skipBlockComment(); } else if (next === 47) { // '/' skipLineComment(); } else break; - } else if (ch < 14 && ch > 8) { - ++tokPos; - } else if (ch === 32 || ch === 160) { // ' ', '\xa0' + } else if (ch === 160) { // '\xa0' ++tokPos; } else if (ch >= 5760 && nonASCIIwhitespace.test(String.fromCharCode(ch))) { ++tokPos; @@ -486,26 +573,89 @@ // The `forceRegexp` parameter is used in the one case where the // `tokRegexpAllowed` trick does not work. See `parseStatement`. - function readToken(forceRegexp) { - tokStart = tokPos; - if (options.locations) tokStartLoc = curLineLoc(); - tokCommentsBefore = tokComments; - if (forceRegexp) return readRegexp(); - if (tokPos >= inputLen) return finishToken(_eof); + function readToken_dot() { + var next = input.charCodeAt(tokPos + 1); + if (next >= 48 && next <= 57) return readNumber(true); + ++tokPos; + return finishToken(_dot); + } - var code = input.charCodeAt(tokPos); - // Identifier or keyword. '\uXXXX' sequences are allowed in - // identifiers, so '\' also dispatches to that. - if (isIdentifierStart(code) || code === 92 /* '\' */) return readWord(); - var next = input.charCodeAt(tokPos+1); + function readToken_slash() { // '/' + var next = input.charCodeAt(tokPos + 1); + if (tokRegexpAllowed) {++tokPos; return readRegexp();} + if (next === 61) return finishOp(_assign, 2); + return finishOp(_slash, 1); + } + + function readToken_mult_modulo() { // '%*' + var next = input.charCodeAt(tokPos + 1); + if (next === 61) return finishOp(_assign, 2); + return finishOp(_multiplyModulo, 1); + } + + function readToken_pipe_amp(code) { // '|&' + var next = input.charCodeAt(tokPos + 1); + if (next === code) return finishOp(code === 124 ? _logicalOR : _logicalAND, 2); + if (next === 61) return finishOp(_assign, 2); + return finishOp(code === 124 ? _bitwiseOR : _bitwiseAND, 1); + } + + function readToken_caret() { // '^' + var next = input.charCodeAt(tokPos + 1); + if (next === 61) return finishOp(_assign, 2); + return finishOp(_bitwiseXOR, 1); + } + + function readToken_plus_min(code) { // '+-' + var next = input.charCodeAt(tokPos + 1); + if (next === code) { + if (next == 45 && input.charCodeAt(tokPos + 2) == 62 && + newline.test(input.slice(lastEnd, tokPos))) { + // A `-->` line comment + tokPos += 3; + skipLineComment(); + skipSpace(); + return readToken(); + } + return finishOp(_incDec, 2); + } + if (next === 61) return finishOp(_assign, 2); + return finishOp(_plusMin, 1); + } + function readToken_lt_gt(code) { // '<>' + var next = input.charCodeAt(tokPos + 1); + var size = 1; + if (next === code) { + size = code === 62 && input.charCodeAt(tokPos + 2) === 62 ? 3 : 2; + if (input.charCodeAt(tokPos + size) === 61) return finishOp(_assign, size + 1); + return finishOp(_bitShift, size); + } + if (next == 33 && code == 60 && input.charCodeAt(tokPos + 2) == 45 && + input.charCodeAt(tokPos + 3) == 45) { + // `", From ee9f33b981a49d02beeed2243bb7006342e5cc44 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Wed, 2 Apr 2014 16:08:02 +0200 Subject: [PATCH 0575/4131] [xml-hint addon] Filter out !attrs from top level completions --- addon/hint/xml-hint.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/addon/hint/xml-hint.js b/addon/hint/xml-hint.js index 9ebec05344..9cfd1e884f 100644 --- a/addon/hint/xml-hint.js +++ b/addon/hint/xml-hint.js @@ -38,8 +38,9 @@ for (var i = 0; i < childList.length; ++i) if (!prefix || childList[i].lastIndexOf(prefix, 0) == 0) result.push("<" + childList[i]); } else if (tagType != "close") { - for (var name in tags) if (tags.hasOwnProperty(name) && name != "!top" && (!prefix || name.lastIndexOf(prefix, 0) == 0)) - result.push("<" + name); + for (var name in tags) + if (tags.hasOwnProperty(name) && name != "!top" && name != "!attrs" && (!prefix || name.lastIndexOf(prefix, 0) == 0)) + result.push("<" + name); } if (cx && (!prefix || tagType == "close" && cx.tagName.lastIndexOf(prefix, 0) == 0)) result.push(""); From 91e02be407d8ccff5928d2b9ad4f590b803ca321 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 3 Apr 2014 11:31:40 +0200 Subject: [PATCH 0576/4131] Work around Webkit bug where sometimes the sizer gets the wrong width (It'll leave space for a scrollbar to the right of the sizer, though the scroller does not actually have a scrollbar.) Issue #2420 --- lib/codemirror.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lib/codemirror.js b/lib/codemirror.js index 41bf2e6658..ea58167227 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -652,6 +652,13 @@ function setDocumentHeight(cm, measure) { cm.display.sizer.style.minHeight = cm.display.heightForcer.style.top = measure.docHeight + "px"; cm.display.gutters.style.height = Math.max(measure.docHeight, measure.clientHeight - scrollerCutOff) + "px"; + // Work around Webkit bug where it sometimes reserves space for a + // non-existing phantom scrollbar in the scroller (Issue #2420) + if (webkit && cm.options.lineWrapping && + cm.display.sizer.offsetWidth + cm.display.gutters.offsetWidth < cm.display.scroller.clientWidth - 1) { + cm.display.sizer.style.minHeight = cm.display.heightForcer.style.top = "0px"; + cm.display.gutters.style.height = measure.docHeight + "px"; + } } // Read the actual heights of the rendered lines, and update their From 17a9de99ed61dbcc78fc54bc77bfe5b4ea140e9f Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 3 Apr 2014 11:32:13 +0200 Subject: [PATCH 0577/4131] Set forceUpdate flag in refresh method Closes #2431 --- lib/codemirror.js | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/codemirror.js b/lib/codemirror.js index ea58167227..2e7735bb4f 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -4214,6 +4214,7 @@ refresh: methodOp(function() { var oldHeight = this.display.cachedTextHeight; regChange(this); + this.curOp.forceUpdate = true; clearCaches(this); this.scrollTo(this.doc.scrollLeft, this.doc.scrollTop); updateGutterSpace(this); From 6b8ddd012f0d10f18f59355ee5bd5bc6c8e58457 Mon Sep 17 00:00:00 2001 From: Doug Wikle Date: Fri, 7 Mar 2014 09:01:19 -0500 Subject: [PATCH 0578/4131] [verilog mode] Rewrite --- mode/index.html | 2 +- mode/meta.js | 1 + mode/verilog/index.html | 190 ++++++++++++------------ mode/verilog/test.js | 114 +++++++++++++++ mode/verilog/verilog.js | 315 ++++++++++++++++++++++++++++++---------- test/index.html | 2 + 6 files changed, 444 insertions(+), 180 deletions(-) create mode 100644 mode/verilog/test.js diff --git a/mode/index.html b/mode/index.html index 8b043b9cfc..4dc5fea180 100644 --- a/mode/index.html +++ b/mode/index.html @@ -108,7 +108,7 @@

    Language modes

  • VB.NET
  • VBScript
  • Velocity
  • -
  • Verilog
  • +
  • Verilog/SystemVerilog
  • XML/HTML
  • XQuery
  • YAML
  • diff --git a/mode/meta.js b/mode/meta.js index bada12c712..b8bfebda2e 100644 --- a/mode/meta.js +++ b/mode/meta.js @@ -89,6 +89,7 @@ CodeMirror.modeInfo = [ {name: 'MariaDB', mime: 'text/x-mariadb', mode: 'sql'}, {name: 'sTeX', mime: 'text/x-stex', mode: 'stex'}, {name: 'LaTeX', mime: 'text/x-latex', mode: 'stex'}, + {name: 'SystemVerilog', mime: 'text/x-systemverilog', mode: 'verilog'}, {name: 'Tcl', mime: 'text/x-tcl', mode: 'tcl'}, {name: 'TiddlyWiki ', mime: 'text/x-tiddlywiki', mode: 'tiddlywiki'}, {name: 'Tiki wiki', mime: 'text/tiki', mode: 'tiki'}, diff --git a/mode/verilog/index.html b/mode/verilog/index.html index cc71056446..4c06cdaecf 100644 --- a/mode/verilog/index.html +++ b/mode/verilog/index.html @@ -1,13 +1,14 @@ -CodeMirror: Verilog mode +CodeMirror: Verilog/SystemVerilog mode + - +
    -

    Verilog mode

    - - +// Class definition +class test; + + /** + * Sum two integers + */ + function int sum(int a, int b); + int result = a + b; + string msg = $sformatf("%d + %d = %d", a, b, result); + $display(msg); + return result; + endfunction + + task delay(int num_cycles); + repeat(num_cycles) #1; + endtask + +endclass + + -

    Simple mode that tries to handle Verilog-like languages as well as it - can. Takes one configuration parameters: keywords, an - object whose property names are the keywords in the language.

    + + +

    +Syntax highlighting and indentation for the Verilog and SystemVerilog languages (IEEE 1800). +

    Configuration options:

    +
      +
    • noIndentKeywords - List of keywords which should not cause identation to increase. E.g. ["package", "module"]. Default: None
    • +
    +

    -

    MIME types defined: text/x-verilog (Verilog code).

    -
    +

    MIME types defined: text/x-verilog and text/x-systemverilog.

    + diff --git a/mode/verilog/test.js b/mode/verilog/test.js new file mode 100644 index 0000000000..6f5770b848 --- /dev/null +++ b/mode/verilog/test.js @@ -0,0 +1,114 @@ +(function() { + var mode = CodeMirror.getMode({indentUnit: 4}, "verilog"); + function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); } + + MT("Binary literals", + "[number 1'b0]", + "[number 1'b1]", + "[number 1'bx]", + "[number 1'bz]", + "[number 1'bX]", + "[number 1'bZ]", + "[number 1'B0]", + "[number 1'B1]", + "[number 1'Bx]", + "[number 1'Bz]", + "[number 1'BX]", + "[number 1'BZ]", + "[number 1'b0]", + "[number 1'b1]", + "[number 2'b01]", + "[number 2'bxz]", + "[number 2'b11]", + "[number 2'b10]", + "[number 2'b1Z]", + "[number 12'b0101_0101_0101]", + "[number 1'b 0]", + "[number 'b0101]" + ); + + MT("Octal literals", + "[number 3'o7]", + "[number 3'O7]", + "[number 3'so7]", + "[number 3'SO7]" + ); + + MT("Decimal literals", + "[number 0]", + "[number 1]", + "[number 7]", + "[number 123_456]", + "[number 'd33]", + "[number 8'd255]", + "[number 8'D255]", + "[number 8'sd255]", + "[number 8'SD255]", + "[number 32'd123]", + "[number 32 'd123]", + "[number 32 'd 123]" + ); + + MT("Hex literals", + "[number 4'h0]", + "[number 4'ha]", + "[number 4'hF]", + "[number 4'hx]", + "[number 4'hz]", + "[number 4'hX]", + "[number 4'hZ]", + "[number 32'hdc78]", + "[number 32'hDC78]", + "[number 32 'hDC78]", + "[number 32'h DC78]", + "[number 32 'h DC78]", + "[number 32'h44x7]", + "[number 32'hFFF?]" + ); + + MT("Real number literals", + "[number 1.2]", + "[number 0.1]", + "[number 2394.26331]", + "[number 1.2E12]", + "[number 1.2e12]", + "[number 1.30e-2]", + "[number 0.1e-0]", + "[number 23E10]", + "[number 29E-2]", + "[number 236.123_763_e-12]" + ); + + MT("Operators", + "[meta ^]" + ); + + MT("Keywords", + "[keyword logic]", + "[keyword logic] [variable foo]", + "[keyword reg] [variable abc]" + ); + + MT("Variables", + "[variable _leading_underscore]", + "[variable _if]", + "[number 12] [variable foo]", + "[variable foo] [number 14]" + ); + + MT("Tick defines", + "[def `FOO]", + "[def `foo]", + "[def `FOO_bar]" + ); + + MT("System calls", + "[meta $display]", + "[meta $vpi_printf]" + ); + + MT("Line comment", "[comment // Hello world]"); + + + +})(); diff --git a/mode/verilog/verilog.js b/mode/verilog/verilog.js index bc4fd4feee..d52ecea2a3 100644 --- a/mode/verilog/verilog.js +++ b/mode/verilog/verilog.js @@ -9,35 +9,141 @@ "use strict"; CodeMirror.defineMode("verilog", function(config, parserConfig) { + var indentUnit = config.indentUnit, - keywords = parserConfig.keywords || {}, - blockKeywords = parserConfig.blockKeywords || {}, - atoms = parserConfig.atoms || {}, - hooks = parserConfig.hooks || {}, + statementIndentUnit = parserConfig.statementIndentUnit || indentUnit, + dontAlignCalls = parserConfig.dontAlignCalls, + noIndentKeywords = parserConfig.noIndentKeywords || [], multiLineStrings = parserConfig.multiLineStrings; - var isOperatorChar = /[&|~> | >= | & | | | ^ | ^~ | ~^ | >> | << | >>> | <<< + | -> | <-> + inc_or_dec_operator ::= ++ | -- + unary_module_path_operator ::= + ! | ~ | & | ~& | | | ~| | ^ | ~^ | ^~ + binary_module_path_operator ::= + == | != | && | || | & | | | ^ | ^~ | ~^ + */ + var isOperatorChar = /[\+\-\*\/!~&|^%=?:]/; + var isBracketChar = /[\[\]{}()]/; + + var unsignedNumber = /\d[0-9_]*/; + var decimalLiteral = /\d*\s*'s?d\s*\d[0-9_]*/i; + var binaryLiteral = /\d*\s*'s?b\s*[xz01][xz01_]*/i; + var octLiteral = /\d*\s*'s?o\s*[xz0-7][xz0-7_]*/i; + var hexLiteral = /\d*\s*'s?h\s*[0-9a-fxz?][0-9a-fxz?_]*/i; + var realLiteral = /(\d[\d_]*(\.\d[\d_]*)?E-?[\d_]+)|(\d[\d_]*\.\d[\d_]*)/i; + + var closingBracketOrWord = /^((\w+)|[)}\]])/; + var closingBracket = /[)}\]]/; var curPunc; + var curKeyword; + + // Block openings which are closed by a matching keyword in the form of ("end" + keyword) + // E.g. "task" => "endtask" + var blockKeywords = words( + "case checker class clocking config function generate group interface module package" + + "primitive program property specify sequence table task" + ); + + // Opening/closing pairs + var openClose = {}; + for (var keyword in blockKeywords) { + openClose[keyword] = "end" + keyword; + } + openClose["begin"] = "end"; + openClose["casex"] = "endcase"; + openClose["casez"] = "endcase"; + openClose["do" ] = "while"; + openClose["fork" ] = "join;join_any;join_none"; + + for (var i in noIndentKeywords) { + var keyword = noIndentKeywords[i]; + if (openClose[keyword]) { + openClose[keyword] = undefined; + } + } + + var statementKeywords = words("always always_comb always_ff always_latch assert assign assume else for foreach forever if initial repeat while"); function tokenBase(stream, state) { - var ch = stream.next(); - if (hooks[ch]) { - var result = hooks[ch](stream, state); - if (result !== false) return result; + var ch = stream.peek(); + if (/[,;:\.]/.test(ch)) { + curPunc = stream.next(); + return null; + } + if (isBracketChar.test(ch)) { + curPunc = stream.next(); + return "bracket"; + } + // Macros (tick-defines) + if (ch == '`') { + stream.next(); + if (stream.eatWhile(/[\w\$_]/)) { + return "def"; + } else { + return null; + } + } + // System calls + if (ch == '$') { + stream.next(); + if (stream.eatWhile(/[\w\$_]/)) { + return "meta"; + } else { + return null; + } } + // Time literals + if (ch == '#') { + stream.next(); + stream.eatWhile(/[\d_.]/); + return "def"; + } + // Strings if (ch == '"') { + stream.next(); state.tokenize = tokenString(ch); return state.tokenize(stream, state); } - if (/[\[\]{}\(\),;\:\.]/.test(ch)) { - curPunc = ch; - return null; - } - if (/[\d']/.test(ch)) { - stream.eatWhile(/[\w\.']/); - return "number"; - } + // Comments if (ch == "/") { + stream.next(); if (stream.eat("*")) { state.tokenize = tokenComment; return tokenComment(stream, state); @@ -46,19 +152,43 @@ CodeMirror.defineMode("verilog", function(config, parserConfig) { stream.skipToEnd(); return "comment"; } + stream.backUp(1); + } + + // Numeric literals + if (stream.match(realLiteral) || + stream.match(decimalLiteral) || + stream.match(binaryLiteral) || + stream.match(octLiteral) || + stream.match(hexLiteral) || + stream.match(unsignedNumber) || + stream.match(realLiteral)) { + return "number"; } - if (isOperatorChar.test(ch)) { - stream.eatWhile(isOperatorChar); - return "operator"; + + // Operators + if (stream.eatWhile(isOperatorChar)) { + return "meta"; } - stream.eatWhile(/[\w\$_]/); - var cur = stream.current(); - if (keywords.propertyIsEnumerable(cur)) { - if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement"; - return "keyword"; + + // Keywords / plain variables + if (stream.eatWhile(/[\w\$_]/)) { + var cur = stream.current(); + if (keywords[cur]) { + if (openClose[cur]) { + curPunc = "newblock"; + } + if (statementKeywords[cur]) { + curPunc = "newstatement"; + } + curKeyword = cur; + return "keyword"; + } + return "variable"; } - if (atoms.propertyIsEnumerable(cur)) return "atom"; - return "variable"; + + stream.next(); + return null; } function tokenString(quote) { @@ -94,18 +224,56 @@ CodeMirror.defineMode("verilog", function(config, parserConfig) { this.prev = prev; } function pushContext(state, col, type) { - return state.context = new Context(state.indented, col, type, null, state.context); + var indent = state.indented; + var c = new Context(indent, col, type, null, state.context); + return state.context = c; } function popContext(state) { var t = state.context.type; - if (t == ")" || t == "]" || t == "}") + if (t == ")" || t == "]" || t == "}") { state.indented = state.context.indented; + } return state.context = state.context.prev; } - // Interface + function isClosing(text, contextClosing) { + if (text == contextClosing) { + return true; + } else { + // contextClosing may be mulitple keywords separated by ; + var closingKeywords = contextClosing.split(";"); + for (var i in closingKeywords) { + if (text == closingKeywords[i]) { + return true; + } + } + return false; + } + } + + function buildElectricInputRegEx() { + // Reindentation should occur on any bracket char: {}()[] + // or on a match of any of the block closing keywords, at + // the end of a line + var allClosings = []; + for (var i in openClose) { + if (openClose[i]) { + var closings = openClose[i].split(";"); + for (var j in closings) { + allClosings.push(closings[j]); + } + } + } + var re = new RegExp("[{}()\\[\\]]|(" + allClosings.join("|") + ")$"); + return re; + } + // Interface return { + + // Regex to force current line to reindent + electricInput: buildElectricInputRegEx(), + startState: function(basecolumn) { return { tokenize: null, @@ -124,69 +292,60 @@ CodeMirror.defineMode("verilog", function(config, parserConfig) { } if (stream.eatSpace()) return null; curPunc = null; + curKeyword = null; var style = (state.tokenize || tokenBase)(stream, state); - if (style == "comment" || style == "meta") return style; + if (style == "comment" || style == "meta" || style == "variable") return style; if (ctx.align == null) ctx.align = true; - if ((curPunc == ";" || curPunc == ":") && ctx.type == "statement") popContext(state); - else if (curPunc == "{") pushContext(state, stream.column(), "}"); - else if (curPunc == "[") pushContext(state, stream.column(), "]"); - else if (curPunc == "(") pushContext(state, stream.column(), ")"); - else if (curPunc == "}") { - while (ctx.type == "statement") ctx = popContext(state); - if (ctx.type == "}") ctx = popContext(state); - while (ctx.type == "statement") ctx = popContext(state); + if (curPunc == ctx.type) { + popContext(state); + } + else if ((curPunc == ";" && ctx.type == "statement") || + (ctx.type && isClosing(curKeyword, ctx.type))) { + ctx = popContext(state); + while (ctx && ctx.type == "statement") ctx = popContext(state); } - else if (curPunc == ctx.type) popContext(state); - else if (ctx.type == "}" || ctx.type == "top" || (ctx.type == "statement" && curPunc == "newstatement")) + else if (curPunc == "{") { pushContext(state, stream.column(), "}"); } + else if (curPunc == "[") { pushContext(state, stream.column(), "]"); } + else if (curPunc == "(") { pushContext(state, stream.column(), ")"); } + else if (ctx && ctx.type == "endcase" && curPunc == ":") { pushContext(state, stream.column(), "statement"); } + else if (curPunc == "newstatement") { pushContext(state, stream.column(), "statement"); + } else if (curPunc == "newblock") { + var close = openClose[curKeyword]; + pushContext(state, stream.column(), close); + } + state.startOfLine = false; return style; }, indent: function(state, textAfter) { - if (state.tokenize != tokenBase && state.tokenize != null) return 0; - var firstChar = textAfter && textAfter.charAt(0), ctx = state.context, closing = firstChar == ctx.type; - if (ctx.type == "statement") return ctx.indented + (firstChar == "{" ? 0 : indentUnit); - else if (ctx.align) return ctx.column + (closing ? 0 : 1); + if (state.tokenize != tokenBase && state.tokenize != null) return CodeMirror.Pass; + var ctx = state.context, firstChar = textAfter && textAfter.charAt(0); + if (ctx.type == "statement" && firstChar == "}") ctx = ctx.prev; + var closing = false; + var possibleClosing = textAfter.match(closingBracketOrWord); + if (possibleClosing) { + closing = isClosing(possibleClosing[0], ctx.type); + } + if (ctx.type == "statement") return ctx.indented + (firstChar == "{" ? 0 : statementIndentUnit); + else if (closingBracket.test(ctx.type) && ctx.align && !dontAlignCalls) return ctx.column + (closing ? 0 : 1); + else if (ctx.type == ")" && !closing) return ctx.indented + statementIndentUnit; else return ctx.indented + (closing ? 0 : indentUnit); }, - electricChars: "{}" + blockCommentStart: "/*", + blockCommentEnd: "*/", + lineComment: "//" }; }); - function words(str) { - var obj = {}, words = str.split(" "); - for (var i = 0; i < words.length; ++i) obj[words[i]] = true; - return obj; - } - - var verilogKeywords = "always and assign automatic begin buf bufif0 bufif1 case casex casez cell cmos config " + - "deassign default defparam design disable edge else end endcase endconfig endfunction endgenerate endmodule " + - "endprimitive endspecify endtable endtask event for force forever fork function generate genvar highz0 " + - "highz1 if ifnone incdir include initial inout input instance integer join large liblist library localparam " + - "macromodule medium module nand negedge nmos nor noshowcancelled not notif0 notif1 or output parameter pmos " + - "posedge primitive pull0 pull1 pulldown pullup pulsestyle_onevent pulsestyle_ondetect rcmos real realtime " + - "reg release repeat rnmos rpmos rtran rtranif0 rtranif1 scalared showcancelled signed small specify specparam " + - "strong0 strong1 supply0 supply1 table task time tran tranif0 tranif1 tri tri0 tri1 triand trior trireg " + - "unsigned use vectored wait wand weak0 weak1 while wire wor xnor xor"; - - var verilogBlockKeywords = "begin bufif0 bufif1 case casex casez config else end endcase endconfig endfunction " + - "endgenerate endmodule endprimitive endspecify endtable endtask for forever function generate if ifnone " + - "macromodule module primitive repeat specify table task while"; - - function metaHook(stream) { - stream.eatWhile(/[\w\$_]/); - return "meta"; - } - - CodeMirror.defineMIME("text/x-verilog", { - name: "verilog", - keywords: words(verilogKeywords), - blockKeywords: words(verilogBlockKeywords), - atoms: words("null"), - hooks: {"`": metaHook, "$": metaHook} - }); +CodeMirror.defineMIME("text/x-verilog", { + name: "verilog" +}); +CodeMirror.defineMIME("text/x-systemverilog", { + name: "systemverilog" +}); }); diff --git a/test/index.html b/test/index.html index 4fcc028dce..76fd835f28 100644 --- a/test/index.html +++ b/test/index.html @@ -95,6 +95,8 @@

    Test Suite

    + + From 66b842d064a95f37047fe1823582df9285dd99a1 Mon Sep 17 00:00:00 2001 From: as3boyan Date: Tue, 1 Apr 2014 23:03:46 +0300 Subject: [PATCH 0579/4131] [haxe mode] Support imports with wildcards Haxe supports imports with willcard http://haxe.org/manual/modules#import-whole-package --- mode/haxe/haxe.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mode/haxe/haxe.js b/mode/haxe/haxe.js index b8f8408d14..83224d86e4 100644 --- a/mode/haxe/haxe.js +++ b/mode/haxe/haxe.js @@ -316,7 +316,7 @@ CodeMirror.defineMode("haxe", function(config, parserConfig) { function importdef (type, value) { if(type == "variable" && /[A-Z]/.test(value.charAt(0))) { registerimport(value); return cont(); } - else if(type == "variable" || type == "property" || type == ".") return cont(importdef); + else if(type == "variable" || type == "property" || type == "." || value == "*") return cont(importdef); } function typedef (type, value) From 82fbd5d6f4acf0b81677ba937811f27b45bb6e29 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 7 Apr 2014 10:17:37 +0200 Subject: [PATCH 0580/4131] Throw an error when a tokenizer doesn't advance the stream Issue #2427 --- lib/codemirror.js | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/lib/codemirror.js b/lib/codemirror.js index 2e7735bb4f..90b827365c 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -3882,7 +3882,7 @@ var stream = new StringStream(line.text, this.options.tabSize); while (stream.pos < pos.ch && !stream.eol()) { stream.start = stream.pos; - var style = mode.token(stream, state); + var style = readToken(mode, stream, state); } return {start: stream.start, end: stream.pos, @@ -5548,6 +5548,13 @@ if (inner.mode.blankLine) return inner.mode.blankLine(inner.state); } + function readToken(mode, stream, state) { + var style = mode.token(stream, state); + if (stream.pos <= stream.start) + throw new Error("Mode " + mode.name + " failed to advance stream."); + return style; + } + // 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; @@ -5562,7 +5569,7 @@ stream.pos = text.length; style = null; } else { - style = extractLineClasses(mode.token(stream, state), lineClasses); + style = extractLineClasses(readToken(mode, stream, state), lineClasses); } if (cm.options.addModeClass) { var mName = CodeMirror.innerMode(mode, state).mode.name; @@ -5643,7 +5650,7 @@ stream.start = stream.pos = startAt || 0; if (text == "") callBlankLine(mode, state); while (!stream.eol() && stream.pos <= cm.options.maxHighlightLength) { - mode.token(stream, state); + readToken(mode, stream, state); stream.start = stream.pos; } } From 264ae319a31af6d79846c570a35fddb4413be6e2 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 7 Apr 2014 11:01:36 +0200 Subject: [PATCH 0581/4131] [javascript mode] Improve indentation of hanging else clauses Closes #2429 --- mode/javascript/javascript.js | 10 +++++++--- mode/javascript/test.js | 16 ++++++++++++++++ 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/mode/javascript/javascript.js b/mode/javascript/javascript.js index c45e04bb8c..9318aabe99 100644 --- a/mode/javascript/javascript.js +++ b/mode/javascript/javascript.js @@ -325,7 +325,11 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { if (type == "keyword b") return cont(pushlex("form"), statement, poplex); if (type == "{") return cont(pushlex("}"), block, poplex); if (type == ";") return cont(); - if (type == "if") return cont(pushlex("form"), expression, statement, poplex, maybeelse); + if (type == "if") { + if (cx.state.lexical.info == "else" && cx.state.cc[cx.state.cc.length - 1] == poplex) + cx.state.cc.pop()(); + return cont(pushlex("form"), expression, statement, poplex, maybeelse); + } if (type == "function") return cont(functiondef); if (type == "for") return cont(pushlex("form"), forspec, statement, poplex); if (type == "variable") return cont(pushlex("stat"), maybelabel); @@ -493,7 +497,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { if (type == ",") return cont(vardef); } function maybeelse(type, value) { - if (type == "keyword b" && value == "else") return cont(pushlex("form"), statement, poplex); + if (type == "keyword b" && value == "else") return cont(pushlex("form", "else"), statement, poplex); } function forspec(type) { if (type == "(") return cont(pushlex(")"), forspec1, expect(")"), poplex); @@ -606,7 +610,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { if (state.tokenize != tokenBase) return 0; var firstChar = textAfter && textAfter.charAt(0), lexical = state.lexical; // Kludge to prevent 'maybelse' from blocking lexical scope pops - for (var i = state.cc.length - 1; i >= 0; --i) { + if (!/^\s*else\b/.test(textAfter)) for (var i = state.cc.length - 1; i >= 0; --i) { var c = state.cc[i]; if (c == poplex) lexical = lexical.prev; else if (c != maybeelse) break; diff --git a/mode/javascript/test.js b/mode/javascript/test.js index 3f73196118..36341862f0 100644 --- a/mode/javascript/test.js +++ b/mode/javascript/test.js @@ -104,6 +104,22 @@ " [keyword debugger];", "}"); + MT("indent_else", + "[keyword for] (;;)", + " [keyword if] ([variable foo])", + " [keyword if] ([variable bar])", + " [number 1];", + " [keyword else]", + " [number 2];", + " [keyword else]", + " [number 3];"); + + MT("indent_below_if", + "[keyword for] (;;)", + " [keyword if] ([variable foo])", + " [number 1];", + "[number 2];"); + MT("multilinestring", "[keyword var] [variable x] [operator =] [string 'foo\\]", "[string bar'];"); From a1432781943d8499e76f8f7e51124747b1ea54b3 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 7 Apr 2014 11:10:06 +0200 Subject: [PATCH 0582/4131] Fix extra layout round-trip introduced by fix for issue #2420 --- lib/codemirror.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/codemirror.js b/lib/codemirror.js index 90b827365c..a37c921391 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -547,6 +547,8 @@ updateSelection(cm); setDocumentHeight(cm, barMeasure); updateScrollbars(cm, barMeasure); + if (webkit && cm.options.lineWrapping) + checkForWebkitWidthBug(cm, barMeasure); // (Issue #2420) if (first && cm.options.lineWrapping && oldWidth != cm.display.scroller.clientWidth) { forced = true; continue; @@ -652,10 +654,13 @@ function setDocumentHeight(cm, measure) { cm.display.sizer.style.minHeight = cm.display.heightForcer.style.top = measure.docHeight + "px"; cm.display.gutters.style.height = Math.max(measure.docHeight, measure.clientHeight - scrollerCutOff) + "px"; + } + + + function checkForWebkitWidthBug(cm, measure) { // Work around Webkit bug where it sometimes reserves space for a // non-existing phantom scrollbar in the scroller (Issue #2420) - if (webkit && cm.options.lineWrapping && - cm.display.sizer.offsetWidth + cm.display.gutters.offsetWidth < cm.display.scroller.clientWidth - 1) { + if (cm.display.sizer.offsetWidth + cm.display.gutters.offsetWidth < cm.display.scroller.clientWidth - 1) { cm.display.sizer.style.minHeight = cm.display.heightForcer.style.top = "0px"; cm.display.gutters.style.height = measure.docHeight + "px"; } From e496a0d880a2e0f18af79d7cb081fae544c0fb79 Mon Sep 17 00:00:00 2001 From: mauricio Date: Thu, 3 Apr 2014 23:12:26 -0300 Subject: [PATCH 0583/4131] [xml mode] Fix closing tag regexp --- mode/xml/xml.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mode/xml/xml.js b/mode/xml/xml.js index 3fc0cb5056..b8c4297976 100644 --- a/mode/xml/xml.js +++ b/mode/xml/xml.js @@ -334,7 +334,7 @@ CodeMirror.defineMode("xml", function(config, parserConfig) { return state.tagStart + indentUnit * multilineTagIndentFactor; } if (alignCDATA && / Date: Mon, 7 Apr 2014 11:20:38 +0200 Subject: [PATCH 0584/4131] [merge addon] Verify that diff is up to date in left/rightChunks Issue #2438 --- addon/merge/merge.js | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/addon/merge/merge.js b/addon/merge/merge.js index fc1cb2f5a1..c8619e7394 100644 --- a/addon/merge/merge.js +++ b/addon/merge/merge.js @@ -53,6 +53,14 @@ } }; + function ensureDiff(dv) { + if (dv.diffOutOfDate) { + dv.diff = getDiff(dv.orig.getValue(), dv.edit.getValue()); + dv.diffOutOfDate = false; + CodeMirror.signal(dv.edit, "updateDiff", dv.diff); + } + } + function registerUpdate(dv) { var edit = {from: 0, to: 0, marked: []}; var orig = {from: 0, to: 0, marked: []}; @@ -65,11 +73,7 @@ clearMarks(dv.orig, orig.marked, dv.classes); edit.from = edit.to = orig.from = orig.to = 0; } - if (dv.diffOutOfDate) { - dv.diff = getDiff(dv.orig.getValue(), dv.edit.getValue()); - dv.diffOutOfDate = false; - CodeMirror.signal(dv.edit, "updateDiff", dv.diff); - } + ensureDiff(dv); if (dv.showDifferences) { updateMarks(dv.edit, dv.diff, edit, DIFF_INSERT, dv.classes); updateMarks(dv.orig, dv.diff, orig, DIFF_DELETE, dv.classes); @@ -362,10 +366,10 @@ if (this.left) this.left.setShowDifferences(val); }, rightChunks: function() { - return this.right && getChunks(this.right.diff); + return this.right && getChunks(this.right); }, leftChunks: function() { - return this.left && getChunks(this.left.diff); + return this.left && getChunks(this.left); } }; @@ -416,9 +420,10 @@ f(startOrig, orig.line + 1, startEdit, edit.line + 1); } - function getChunks(diff) { + function getChunks(dv) { + ensureDiff(dv); var collect = []; - iterateChunks(diff, function(topOrig, botOrig, topEdit, botEdit) { + iterateChunks(dv.diff, function(topOrig, botOrig, topEdit, botEdit) { collect.push({origFrom: topOrig, origTo: botOrig, editFrom: topEdit, editTo: botEdit}); }); From 72f00862d3487bc76c07a987ef7a9dce3365c26e Mon Sep 17 00:00:00 2001 From: Vincent Woo Date: Sun, 6 Apr 2014 15:09:30 -0700 Subject: [PATCH 0585/4131] [r mode] Add lineComment property --- mode/r/r.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mode/r/r.js b/mode/r/r.js index 7f4feb238b..281d7fa40f 100644 --- a/mode/r/r.js +++ b/mode/r/r.js @@ -148,7 +148,9 @@ CodeMirror.defineMode("r", function(config) { if (ctx.type == "block") return ctx.indent + (firstChar == "{" ? 0 : config.indentUnit); else if (ctx.align) return ctx.column + (closing ? 0 : 1); else return ctx.indent + (closing ? 0 : config.indentUnit); - } + }, + + lineComment: "#" }; }); From 1eafe973de552c1c70163d3fa60ce23e2d1952ba Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 7 Apr 2014 16:10:51 +0200 Subject: [PATCH 0586/4131] List punctuation in default theme, don't set color for default color styles Also fix Erlang mode to not return a non-standard token type. Issue #2435 --- lib/codemirror.css | 7 ++++--- mode/erlang/erlang.js | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/codemirror.css b/lib/codemirror.css index 13eb137918..098a317a22 100644 --- a/lib/codemirror.css +++ b/lib/codemirror.css @@ -70,11 +70,12 @@ div.CodeMirror-overwrite div.CodeMirror-cursor {} .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 {color: black;} +.cm-s-default .cm-variable, +.cm-s-default .cm-punctuation, +.cm-s-default .cm-property, +.cm-s-default .cm-operator {} .cm-s-default .cm-variable-2 {color: #05a;} .cm-s-default .cm-variable-3 {color: #085;} -.cm-s-default .cm-property {color: black;} -.cm-s-default .cm-operator {color: black;} .cm-s-default .cm-comment {color: #a50;} .cm-s-default .cm-string {color: #a11;} .cm-s-default .cm-string-2 {color: #f50;} diff --git a/mode/erlang/erlang.js b/mode/erlang/erlang.js index 79693fca22..3d4b1ba92e 100644 --- a/mode/erlang/erlang.js +++ b/mode/erlang/erlang.js @@ -358,7 +358,7 @@ CodeMirror.defineMode("erlang", function(cmCfg) { switch (type) { case "atom": return "atom"; case "attribute": return "attribute"; - case "boolean": return "special"; + case "boolean": return "atom"; case "builtin": return "builtin"; case "close_paren": return null; case "colon": return null; From 3be0f06e00f1afc0868b5d52a68214dc236ea3b4 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 7 Apr 2014 21:29:43 +0200 Subject: [PATCH 0587/4131] [rulers addon] Fix bug where rulers cause unnecessary vertical scroll Issue #2439 --- addon/display/rulers.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addon/display/rulers.js b/addon/display/rulers.js index eb0ff06e3a..a5386aa510 100644 --- a/addon/display/rulers.js +++ b/addon/display/rulers.js @@ -31,7 +31,7 @@ var val = cm.getOption("rulers"); var cw = cm.defaultCharWidth(); var left = cm.charCoords(CodeMirror.Pos(cm.firstLine(), 0), "div").left; - var bot = -cm.display.scroller.offsetHeight; + var minH = cm.display.scroller.offsetHeight + 30; for (var i = 0; i < val.length; i++) { var elt = document.createElement("div"); var col, cls = null; @@ -42,7 +42,7 @@ cls = val[i].className; } elt.className = "CodeMirror-ruler" + (cls ? " " + cls : ""); - elt.style.cssText = "left: " + (left + col * cw) + "px; top: -50px; bottom: " + bot + "px"; + elt.style.cssText = "left: " + (left + col * cw) + "px; top: -50px; bottom: -20px; min-height: " + minH + "px"; cm.display.lineSpace.insertBefore(elt, cm.display.cursorDiv); } } From df33eaf3b7cc3c9cffe42e6276564b837528d66d Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 7 Apr 2014 21:50:57 +0200 Subject: [PATCH 0588/4131] [markdown mode] Fix for token sometimes not advancing the stream Issue #2447 --- mode/markdown/markdown.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/mode/markdown/markdown.js b/mode/markdown/markdown.js index 199c7a7155..ff466be86f 100644 --- a/mode/markdown/markdown.js +++ b/mode/markdown/markdown.js @@ -709,7 +709,8 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) { if (forceBlankLine) { state.prevLineHasContent = false; - return blankLine(state); + blankLine(state); + return this.token(stream, state); } else { state.prevLineHasContent = state.thisLineHasContent; state.thisLineHasContent = true; @@ -737,7 +738,9 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) { state.indentation = adjustedIndentation; if (indentation > 0) return null; } - return state.f(stream, state); + var result = state.f(stream, state); + if (stream.start == stream.pos) return this.token(stream, state); + else return result; }, innerMode: function(state) { From 72f0e188def243041e4e748a193c29f5b38d660b Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 7 Apr 2014 21:51:20 +0200 Subject: [PATCH 0589/4131] Add check for stream advancement to mode test runner Issue #2447 --- test/mode_test.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/mode_test.js b/test/mode_test.js index 46174e1f78..dc20a0523e 100644 --- a/test/mode_test.js +++ b/test/mode_test.js @@ -120,6 +120,8 @@ /* Start copied code from CodeMirror.highlight */ while (!stream.eol()) { var compare = mode.token(stream, state), substr = stream.current(); + if (stream.start >= stream.pos) + throw new Failure("Failed to advance the stream." + stream.string + " " + stream.pos); if (compare && compare.indexOf(" ") > -1) compare = compare.split(' ').sort().join(' '); stream.start = stream.pos; if (pos && st[pos-2] == compare && !newLine) { From a97d436143f0346091fd391f4d682e30ab206437 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 7 Apr 2014 21:58:46 +0200 Subject: [PATCH 0590/4131] [haml mode] Fix tokenizer not advancing stream when switching modes --- mode/haml/haml.js | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/mode/haml/haml.js b/mode/haml/haml.js index 6b205b43e4..59a86e7cec 100644 --- a/mode/haml/haml.js +++ b/mode/haml/haml.js @@ -8,9 +8,6 @@ })(function(CodeMirror) { "use strict"; -(function() { - "use strict"; - // full haml mode. This handled embeded ruby and html fragments too CodeMirror.defineMode("haml", function(config) { var htmlMode = CodeMirror.getMode(config, {name: "htmlmixed"}); @@ -75,7 +72,7 @@ // donot handle --> as valid ruby, make it HTML close comment instead if (state.startOfLine && !stream.match("-->", false) && (ch == "=" || ch == "-" )) { state.tokenize = ruby; - return null; + return state.tokenize(stream, state); } if (state.previousToken.style == "hamlTag" || @@ -83,10 +80,10 @@ state.previousToken.style == "hamlAttribute") { if (ch == "(") { state.tokenize = rubyInQuote(")"); - return null; + return state.tokenize(stream, state); } else if (ch == "{") { state.tokenize = rubyInQuote("}"); - return null; + return state.tokenize(stream, state); } } @@ -156,6 +153,4 @@ }, "htmlmixed", "ruby"); CodeMirror.defineMIME("text/x-haml", "haml"); -})(); - }); From 90e0c283f7ba61f45b3c9d632de98a1c9a7ce538 Mon Sep 17 00:00:00 2001 From: B Krishna Chaitanya Date: Tue, 8 Apr 2014 00:53:20 +0530 Subject: [PATCH 0591/4131] [sublime keymap] Keep cursor in view while scrolling with Ctrl+Up or Ctrl+Down --- keymap/sublime.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/keymap/sublime.js b/keymap/sublime.js index 4d9211533e..ae33d48d5a 100644 --- a/keymap/sublime.js +++ b/keymap/sublime.js @@ -52,9 +52,23 @@ cmds[map["Alt-Right"] = "goSubwordRight"] = function(cm) { moveSubword(cm, 1); }; cmds[map[ctrl + "Up"] = "scrollLineUp"] = function(cm) { + if(!cm.somethingSelected()){ + var visibleBottomLine = cm.lineAtHeight(cm.getScrollInfo().top + cm.getScrollInfo().clientHeight, "local"); + var cur = cm.getCursor(); + if(cur.line >= visibleBottomLine){ + cm.setCursor({line:visibleBottomLine-1, ch:cur.ch}); + } + } cm.scrollTo(null, cm.getScrollInfo().top - cm.defaultTextHeight()); }; cmds[map[ctrl + "Down"] = "scrollLineDown"] = function(cm) { + if(!cm.somethingSelected()){ + var visibleTopLine = cm.lineAtHeight(cm.getScrollInfo().top, "local")+1; + var cur = cm.getCursor(); + if(cur.line-1 < visibleTopLine){ + cm.setCursor({line:visibleTopLine+1, ch:cur.ch}); + } + } cm.scrollTo(null, cm.getScrollInfo().top + cm.defaultTextHeight()); }; From 0cb9b1daa7f40f9eb58e94a1520ad06fdb1446de Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Tue, 8 Apr 2014 08:50:25 +0200 Subject: [PATCH 0592/4131] Clean up 90e0c283f7ba61f45b3c9d632de98a1c9a7ce538 Issue #2448 --- keymap/sublime.js | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/keymap/sublime.js b/keymap/sublime.js index ae33d48d5a..eea46347fd 100644 --- a/keymap/sublime.js +++ b/keymap/sublime.js @@ -52,24 +52,22 @@ cmds[map["Alt-Right"] = "goSubwordRight"] = function(cm) { moveSubword(cm, 1); }; cmds[map[ctrl + "Up"] = "scrollLineUp"] = function(cm) { - if(!cm.somethingSelected()){ - var visibleBottomLine = cm.lineAtHeight(cm.getScrollInfo().top + cm.getScrollInfo().clientHeight, "local"); - var cur = cm.getCursor(); - if(cur.line >= visibleBottomLine){ - cm.setCursor({line:visibleBottomLine-1, ch:cur.ch}); - } + var info = cm.getScrollInfo(); + if (!cm.somethingSelected()) { + var visibleBottomLine = cm.lineAtHeight(info.top + info.clientHeight, "local"); + if (cm.getCursor().line >= visibleBottomLine) + cm.execCommand("goLineUp"); } - cm.scrollTo(null, cm.getScrollInfo().top - cm.defaultTextHeight()); + cm.scrollTo(null, info.top - cm.defaultTextHeight()); }; cmds[map[ctrl + "Down"] = "scrollLineDown"] = function(cm) { - if(!cm.somethingSelected()){ - var visibleTopLine = cm.lineAtHeight(cm.getScrollInfo().top, "local")+1; - var cur = cm.getCursor(); - if(cur.line-1 < visibleTopLine){ - cm.setCursor({line:visibleTopLine+1, ch:cur.ch}); - } + var info = cm.getScrollInfo(); + if (!cm.somethingSelected()) { + var visibleTopLine = cm.lineAtHeight(info.top, "local")+1; + if (cm.getCursor().line <= visibleTopLine) + cm.execCommand("goLineDown"); } - cm.scrollTo(null, cm.getScrollInfo().top + cm.defaultTextHeight()); + cm.scrollTo(null, info.top + cm.defaultTextHeight()); }; cmds[map["Shift-" + ctrl + "L"] = "splitSelectionByLine"] = function(cm) { From d77a0440c3ed1d3ac5f5e2877346528c51330751 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Tue, 8 Apr 2014 10:29:38 +0200 Subject: [PATCH 0593/4131] [merge addon] Don't try to remove line class on lines that aren't in doc anymore Issue #2438 --- addon/merge/merge.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addon/merge/merge.js b/addon/merge/merge.js index c8619e7394..fe3fcf4282 100644 --- a/addon/merge/merge.js +++ b/addon/merge/merge.js @@ -169,7 +169,7 @@ var mark = arr[i]; if (mark instanceof CodeMirror.TextMarker) { mark.clear(); - } else { + } else if (mark.parent) { editor.removeLineClass(mark, "background", classes.chunk); editor.removeLineClass(mark, "background", classes.start); editor.removeLineClass(mark, "background", classes.end); From aa90eb2f8c1bc5c73c6255ce7733b8cd351e0036 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Tue, 8 Apr 2014 10:37:19 +0200 Subject: [PATCH 0594/4131] [clike mode] Remove obsolete function namespace --- mode/clike/clike.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/mode/clike/clike.js b/mode/clike/clike.js index 0e61020845..ff0c91d9fe 100644 --- a/mode/clike/clike.js +++ b/mode/clike/clike.js @@ -173,7 +173,6 @@ CodeMirror.defineMode("clike", function(config, parserConfig) { }; }); -(function() { function words(str) { var obj = {}, words = str.split(" "); for (var i = 0; i < words.length; ++i) obj[words[i]] = true; @@ -432,6 +431,5 @@ CodeMirror.defineMode("clike", function(config, parserConfig) { hooks: {"#": cppHook}, modeProps: {fold: ["brace", "include"]} }); -}()); }); From 3d5211dff75aabaab56f148a60d8fbaa14c29205 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Tue, 8 Apr 2014 10:39:42 +0200 Subject: [PATCH 0595/4131] [clike mode] Enable autocompletion in mode demo --- mode/clike/index.html | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/mode/clike/index.html b/mode/clike/index.html index d892fddbdb..d1abf9359d 100644 --- a/mode/clike/index.html +++ b/mode/clike/index.html @@ -7,6 +7,8 @@ + + -

    MIME types defined: text/x-haxe.

    +

    MIME types defined: text/x-haxe, text/x-hxml.

    From 08b4d1e27f67fe1d86d2be526a646e82909b295c Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Wed, 9 Apr 2014 15:53:29 +0200 Subject: [PATCH 0600/4131] [runmode addon] Call blankLine when available --- addon/runmode/runmode-standalone.js | 1 + addon/runmode/runmode.js | 1 + addon/runmode/runmode.node.js | 1 + 3 files changed, 3 insertions(+) diff --git a/addon/runmode/runmode-standalone.js b/addon/runmode/runmode-standalone.js index eaa2b8f2fb..aba6f0e139 100644 --- a/addon/runmode/runmode-standalone.js +++ b/addon/runmode/runmode-standalone.js @@ -139,6 +139,7 @@ CodeMirror.runMode = function (string, modespec, callback, options) { for (var i = 0, e = lines.length; i < e; ++i) { if (i) callback("\n"); var stream = new CodeMirror.StringStream(lines[i]); + if (!stream.string && mode.blankLine) mode.blankLine(); while (!stream.eol()) { var style = mode.token(stream, state); callback(stream.current(), style, i, stream.start, state); diff --git a/addon/runmode/runmode.js b/addon/runmode/runmode.js index 351840e08e..44c17b1a48 100644 --- a/addon/runmode/runmode.js +++ b/addon/runmode/runmode.js @@ -57,6 +57,7 @@ CodeMirror.runMode = function(string, modespec, callback, options) { for (var i = 0, e = lines.length; i < e; ++i) { if (i) callback("\n"); var stream = new CodeMirror.StringStream(lines[i]); + if (!stream.string && mode.blankLine) mode.blankLine(); while (!stream.eol()) { var style = mode.token(stream, state); callback(stream.current(), style, i, stream.start, state); diff --git a/addon/runmode/runmode.node.js b/addon/runmode/runmode.node.js index 74c39be7e7..54be6e930a 100644 --- a/addon/runmode/runmode.node.js +++ b/addon/runmode/runmode.node.js @@ -107,6 +107,7 @@ exports.runMode = function(string, modespec, callback, options) { for (var i = 0, e = lines.length; i < e; ++i) { if (i) callback("\n"); var stream = new exports.StringStream(lines[i]); + if (!stream.string && mode.blankLine) mode.blankLine(); while (!stream.eol()) { var style = mode.token(stream, state); callback(stream.current(), style, i, stream.start, state); From 8a6778baf496da5c80fe785304fdd0e3d5ec8adb Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Wed, 9 Apr 2014 22:26:50 +0200 Subject: [PATCH 0601/4131] Revert "Remove fakedLastChar hack" This reverts commit 475b2be0da668724fa910dc70579820eb3ad905e. Issue #2452 Issue #2384 --- lib/codemirror.js | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/lib/codemirror.js b/lib/codemirror.js index 1a70cd68de..911d0aa21c 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -2225,6 +2225,11 @@ // will be the case when there is a lot of text in the textarea, // in which case reading its value would be expensive. if (!cm.state.focused || hasSelection(input) || isReadOnly(cm) || cm.options.disableInput) return false; + // See paste handler for more on the fakedLastChar kludge + if (cm.state.pasteIncoming && cm.state.fakedLastChar) { + input.value = input.value.substring(0, input.value.length - 1); + cm.state.fakedLastChar = false; + } var text = input.value; // If nothing changed, bail. if (text == prevInput && !cm.somethingSelected()) return false; @@ -2424,6 +2429,16 @@ fastPoll(cm); }); on(d.input, "paste", function() { + // Workaround for webkit bug https://bugs.webkit.org/show_bug.cgi?id=90206 + // Add a char to the end of textarea before paste occur so that + // selection doesn't span to the end of textarea. + if (webkit && !cm.state.fakedLastChar && !(new Date - cm.state.lastMiddleDown < 200)) { + var start = d.input.selectionStart, end = d.input.selectionEnd; + d.input.value += "$"; + d.input.selectionStart = start; + d.input.selectionEnd = end; + cm.state.fakedLastChar = true; + } cm.state.pasteIncoming = true; fastPoll(cm); }); From 17eb93d8cce970ebc62a4a7589a5204b6aa74dc4 Mon Sep 17 00:00:00 2001 From: mtaran-google Date: Thu, 10 Apr 2014 15:40:38 -0700 Subject: [PATCH 0602/4131] [go mode] Set Go mode to use brace folding --- mode/go/go.js | 1 + 1 file changed, 1 insertion(+) diff --git a/mode/go/go.js b/mode/go/go.js index 7ba780ead8..82463052f6 100644 --- a/mode/go/go.js +++ b/mode/go/go.js @@ -169,6 +169,7 @@ CodeMirror.defineMode("go", function(config) { }, electricChars: "{}):", + fold: "brace", blockCommentStart: "/*", blockCommentEnd: "*/", lineComment: "//" From 2d8719ac5732f7d66d58d8c95bdf028dc2cc8f4c Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Wed, 16 Apr 2014 11:24:47 +0200 Subject: [PATCH 0603/4131] Prevent overlay token types from showing up in getTokenTypeAt output Issue #2457 --- lib/codemirror.js | 13 ++++++++----- test/test.js | 13 +++++++++++++ 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/lib/codemirror.js b/lib/codemirror.js index 911d0aa21c..50a20b657c 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -3914,13 +3914,16 @@ pos = clipPos(this.doc, pos); var styles = getLineStyles(this, getLine(this.doc, pos.line)); var before = 0, after = (styles.length - 1) / 2, ch = pos.ch; - if (ch == 0) return styles[2]; - for (;;) { + var type; + if (ch == 0) type = styles[2]; + else for (;;) { var mid = (before + after) >> 1; if ((mid ? styles[mid * 2 - 1] : 0) >= ch) after = mid; else if (styles[mid * 2 + 1] < ch) before = mid + 1; - else return styles[mid * 2 + 2]; + else { type = styles[mid * 2 + 2]; break; } } + var cut = type ? type.indexOf("cm-overlay ") : -1; + return cut < 0 ? type : cut == 0 ? null : type.slice(0, cut - 1); }, getModeAt: function(pos) { @@ -5636,12 +5639,12 @@ } if (!style) return; if (overlay.opaque) { - st.splice(start, i - start, end, style); + st.splice(start, i - start, end, "cm-overlay " + style); i = start + 2; } else { for (; start < i; start += 2) { var cur = st[start+1]; - st[start+1] = cur ? cur + " " + style : style; + st[start+1] = (cur ? cur + " " : "") + "cm-overlay " + style; } } }, lineClasses); diff --git a/test/test.js b/test/test.js index 8c3a307d53..7d597688a8 100644 --- a/test/test.js +++ b/test/test.js @@ -1890,3 +1890,16 @@ testCM("alwaysMergeSelEventWithChangeOrigin", function(cm) { cm.undoSelection(); eq(cm.getValue(), "Va"); }, {value: "a"}); + +testCM("getTokenTypeAt", function(cm) { + eq(cm.getTokenTypeAt(Pos(0, 0)), "number"); + eq(cm.getTokenTypeAt(Pos(0, 6)), "string"); + cm.addOverlay({ + token: function(stream) { + if (stream.match("foo")) return "foo"; + else stream.next(); + } + }); + eq(byClassName(cm.getWrapperElement(), "cm-foo").length, 1); + eq(cm.getTokenTypeAt(Pos(0, 6)), "string"); +}, {value: "1 + 'foo'", mode: "javascript"}); From 6c4d1054e162d8cd862505ed20d161327f81b735 Mon Sep 17 00:00:00 2001 From: Takuji Shimokawa Date: Sat, 29 Mar 2014 15:57:59 +0900 Subject: [PATCH 0604/4131] Refines the text selection detection in readInput function. This change is for enabling the display update while inputting text via the input method. --- lib/codemirror.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/codemirror.js b/lib/codemirror.js index 50a20b657c..f655e27b61 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -2224,7 +2224,8 @@ // possible when it is clear that nothing happened. hasSelection // will be the case when there is a lot of text in the textarea, // in which case reading its value would be expensive. - if (!cm.state.focused || hasSelection(input) || isReadOnly(cm) || cm.options.disableInput) return false; + if (!cm.state.focused || (hasSelection(input) && !prevInput) || isReadOnly(cm) || cm.options.disableInput) + return false; // See paste handler for more on the fakedLastChar kludge if (cm.state.pasteIncoming && cm.state.fakedLastChar) { input.value = input.value.substring(0, input.value.length - 1); From 9d2eeed774cfcf93393ff56530c4f9d3d1a37e69 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Wed, 16 Apr 2014 12:09:54 +0200 Subject: [PATCH 0605/4131] Fix context menu select-all in IE11 Issue #2463 --- lib/codemirror.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/codemirror.js b/lib/codemirror.js index f655e27b61..9a47f3aa46 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -3104,7 +3104,10 @@ signal(cm, "focus", cm); cm.state.focused = true; addClass(cm.display.wrapper, "CodeMirror-focused"); - if (!cm.curOp) { + // The prevInput test prevents this from firing when a context + // menu is closed (since the resetInput would kill the + // select-all detection hack) + if (!cm.curOp && cm.display.prevInput != "\u200b") { resetInput(cm); if (webkit) setTimeout(bind(resetInput, cm, true), 0); // Issue #1730 } @@ -3173,7 +3176,7 @@ if (display.input.selectionStart != null) { if (!ie || ie_upto8) prepareSelectAllHack(); clearTimeout(detectingSelectAll); - var i = 0, poll = function(){ + var i = 0, poll = function() { if (display.prevInput == "\u200b" && display.input.selectionStart == 0) operation(cm, commands.selectAll)(cm); else if (i++ < 10) detectingSelectAll = setTimeout(poll, 500); From e546c8e4fffe67b918761617291e15ccae23544a Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Wed, 16 Apr 2014 12:34:44 +0200 Subject: [PATCH 0606/4131] Be more accurate about which handlers to fire change events for I.e. don't fire for a handler that wasn't registered when the change happened. --- lib/codemirror.js | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/lib/codemirror.js b/lib/codemirror.js index 9a47f3aa46..33b9811599 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -1955,11 +1955,8 @@ delayedCallbacks = null; } // Fire change events, and delayed event handlers - if (op.changeObjs) { - for (var i = 0; i < op.changeObjs.length; i++) - signal(cm, "change", cm, op.changeObjs[i]); + if (op.changeObjs) signal(cm, "changes", cm, op.changeObjs); - } if (op.cursorActivity) signal(cm, "cursorActivity", cm, op.origin); if (delayed) for (var i = 0; i < delayed.length; ++i) delayed[i](); } @@ -3481,13 +3478,17 @@ else regChange(cm, from.line, to.line + 1, lendiff); - if (hasHandler(cm, "change") || hasHandler(cm, "changes")) - (cm.curOp.changeObjs || (cm.curOp.changeObjs = [])).push({ + var changesHandler = hasHandler(cm, "changes"), changeHandler = hasHandler(cm, "change"); + if (changeHandler || changesHandler) { + var obj = { from: from, to: to, text: change.text, removed: change.removed, origin: change.origin - }); + }; + if (changeHandler) signalLater(cm, "change", cm, obj); + if (changesHandler) (cm.curOp.changeObjs || (cm.curOp.changeObjs = [])).push(obj); + } } function replaceRange(doc, code, from, to, origin) { From 8b1a5bb7b72e4987893f2402aa36fbf79d09b905 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Wed, 16 Apr 2014 13:06:22 +0200 Subject: [PATCH 0607/4131] Be more precise about which cursorActivity handlers to fire Issue #2464 --- keymap/vim.js | 4 ++-- lib/codemirror.js | 25 +++++++++++++++++-------- 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/keymap/vim.js b/keymap/vim.js index 6fedf93292..42e4522693 100644 --- a/keymap/vim.js +++ b/keymap/vim.js @@ -4062,7 +4062,7 @@ /** * Listens for any kind of cursor activity on CodeMirror. */ - function onCursorActivity(cm, origin) { + function onCursorActivity(cm) { var vim = cm.state.vim; if (vim.insertMode) { // Tracking cursor activity in insert mode (for macro support). @@ -4075,7 +4075,7 @@ // Cursor moved outside the context of an edit. Reset the change. lastChange.changes = []; } - } else if (origin == '*mouse') { + } else if (cm.doc.history.lastSelOrigin == '*mouse') { // Reset lastHPos if mouse click was done in normal mode. vim.lastHPos = cm.doc.getCursor().ch; } diff --git a/lib/codemirror.js b/lib/codemirror.js index 33b9811599..cb80d8c7c0 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -1131,7 +1131,6 @@ // Set a new selection. function setSelection(doc, sel, options) { - if (options && options.origin && doc.cm) doc.cm.curOp.origin = options.origin; setSelectionNoUndo(doc, sel, options); addSelectionToHistory(doc, doc.sel, doc.cm ? doc.cm.curOp.id : NaN, options); } @@ -1152,9 +1151,10 @@ doc.sel = sel; - if (doc.cm) - doc.cm.curOp.updateInput = doc.cm.curOp.selectionChanged = - doc.cm.curOp.cursorActivity = true; + if (doc.cm) { + doc.cm.curOp.updateInput = doc.cm.curOp.selectionChanged = true; + signalCursorActivity(doc.cm); + } signalLater(doc, "cursorActivity", doc); } @@ -1889,8 +1889,7 @@ updateInput: null, // Whether to reset the input textarea typing: false, // Whether this reset should be careful to leave existing text (for compositing) changeObjs: null, // Accumulated changes, for firing change events - origin: null, // Selection's origin - cursorActivity: false, // Whether to fire a cursorActivity event + cursorActivityHandlers: null, // Set of handlers to fire cursorActivity on selectionChanged: false, // Whether the selection needs to be redrawn updateMaxLine: false, // Set when the widest line needs to be determined anew scrollLeft: null, scrollTop: null, // Intermediate scroll position, not pushed to DOM yet @@ -1957,7 +1956,9 @@ // Fire change events, and delayed event handlers if (op.changeObjs) signal(cm, "changes", cm, op.changeObjs); - if (op.cursorActivity) signal(cm, "cursorActivity", cm, op.origin); + if (op.cursorActivityHandlers) + for (var i = 0; i < op.cursorActivityHandlers.length; i++) + op.cursorActivityHandlers[i](cm); if (delayed) for (var i = 0; i < delayed.length; ++i) delayed[i](); } @@ -3450,7 +3451,7 @@ } if (doc.sel.contains(change.from, change.to) > -1) - cm.curOp.cursorActivity = true; + signalCursorActivity(cm); updateDoc(doc, change, spans, estimateHeight(cm)); @@ -6919,6 +6920,14 @@ return e_defaultPrevented(e) || e.codemirrorIgnore; } + function signalCursorActivity(cm) { + var arr = cm._handlers && cm._handlers.cursorActivity; + if (!arr) return; + var set = cm.curOp.cursorActivityHandlers || (cm.curOp.cursorActivityHandlers = []); + for (var i = 0; i < arr.length; ++i) if (indexOf(set, arr[i]) == -1) + set.push(arr[i]); + } + function hasHandler(emitter, type) { var arr = emitter._handlers && emitter._handlers[type]; return arr && arr.length > 0; From 357cf2d9652f495d741c129b63ff7892a5caf3ef Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Wed, 16 Apr 2014 13:18:59 +0200 Subject: [PATCH 0608/4131] [css mode] Fix tokenizing of empty url() token Issue #2465 --- mode/css/css.js | 2 +- mode/css/test.js | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/mode/css/css.js b/mode/css/css.js index 3426732cdc..7a396ee451 100644 --- a/mode/css/css.js +++ b/mode/css/css.js @@ -92,7 +92,7 @@ CodeMirror.defineMode("css", function(config, parserConfig) { function tokenParenthesized(stream, state) { stream.next(); // Must be '(' - if (!stream.match(/\s*[\"\']/, false)) + if (!stream.match(/\s*[\"\')]/, false)) state.tokenize = tokenString(")"); else state.tokenize = null; diff --git a/mode/css/test.js b/mode/css/test.js index b3f47767e6..f9f667295c 100644 --- a/mode/css/test.js +++ b/mode/css/test.js @@ -116,4 +116,7 @@ " [property src]: [atom url]([string http://blah]),", " [atom url]([string http://foo]);", "}"); + + MT("empty_url", + "[def @import] [tag url]() [tag screen];"); })(); From 973b776d04ac40fc434731488786cca37dc5e5cc Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Wed, 16 Apr 2014 13:26:11 +0200 Subject: [PATCH 0609/4131] Guard against NaN when computing horiz padding Issue #2467 --- lib/codemirror.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/codemirror.js b/lib/codemirror.js index cb80d8c7c0..cfac7fab7c 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -1454,8 +1454,9 @@ if (display.cachedPaddingH) return display.cachedPaddingH; var e = removeChildrenAndAdd(display.measure, elt("pre", "x")); var style = window.getComputedStyle ? window.getComputedStyle(e) : e.currentStyle; - return display.cachedPaddingH = {left: parseInt(style.paddingLeft), - right: parseInt(style.paddingRight)}; + var data = {left: parseInt(style.paddingLeft), right: parseInt(style.paddingRight)}; + if (!isNaN(data.left) && !isNaN(data.right)) display.cachedPaddingH = data; + return data; } // Ensure the lineView.wrapping.heights array is populated. This is From eed9a2c8c782711fc25c0002d643f016f20061ef Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Wed, 16 Apr 2014 14:21:53 +0200 Subject: [PATCH 0610/4131] Call cursorActivity handlers after other handlers To preserve existing change/cursorActivity handler ordering --- lib/codemirror.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/codemirror.js b/lib/codemirror.js index cfac7fab7c..bd03fdb36f 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -1957,10 +1957,10 @@ // Fire change events, and delayed event handlers if (op.changeObjs) signal(cm, "changes", cm, op.changeObjs); + if (delayed) for (var i = 0; i < delayed.length; ++i) delayed[i](); if (op.cursorActivityHandlers) for (var i = 0; i < op.cursorActivityHandlers.length; i++) op.cursorActivityHandlers[i](cm); - if (delayed) for (var i = 0; i < delayed.length; ++i) delayed[i](); } // Run the given function in an operation From 6f7127d685174d44fbe956193c8a4cdf32c17658 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Wed, 16 Apr 2014 17:02:24 +0200 Subject: [PATCH 0611/4131] [r mode] Remove license link All of the distribution is under a single license. --- mode/r/index.html | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/mode/r/index.html b/mode/r/index.html index f73e13d621..397d5858a3 100644 --- a/mode/r/index.html +++ b/mode/r/index.html @@ -80,7 +80,6 @@

    R mode

    MIME types defined: text/x-rsrc.

    Development of the CodeMirror R mode was kindly sponsored - by Ubalo, who hold - the license.

    + by Ubalo.

    From 306a09020ff570c2a75216da470ed6b1e7c6f452 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 17 Apr 2014 09:37:21 +0200 Subject: [PATCH 0612/4131] [javascript mode] Properly parse quasi quotes without prefix Closes #2472 --- mode/javascript/javascript.js | 10 ++++++---- mode/javascript/test.js | 3 +++ 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/mode/javascript/javascript.js b/mode/javascript/javascript.js index 9318aabe99..daf138ba8d 100644 --- a/mode/javascript/javascript.js +++ b/mode/javascript/javascript.js @@ -366,6 +366,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { if (type == "operator" || type == "spread") return cont(noComma ? expressionNoComma : expression); if (type == "[") return cont(pushlex("]"), arrayLiteral, poplex, maybeop); if (type == "{") return contCommasep(objprop, "}", null, maybeop); + if (type == "quasi") { return pass(quasi, maybeop); } return cont(); } function maybeexpression(type) { @@ -390,21 +391,22 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { if (value == "?") return cont(expression, expect(":"), expr); return cont(expr); } - if (type == "quasi") { cx.cc.push(me); return quasi(value); } + if (type == "quasi") { return pass(quasi, me); } if (type == ";") return; if (type == "(") return contCommasep(expressionNoComma, ")", "call", me); if (type == ".") return cont(property, me); if (type == "[") return cont(pushlex("]"), maybeexpression, expect("]"), poplex, me); } - function quasi(value) { - if (value.slice(value.length - 2) != "${") return cont(); + function quasi(type, value) { + if (type != "quasi") return pass(); + if (value.slice(value.length - 2) != "${") return cont(quasi); return cont(expression, continueQuasi); } function continueQuasi(type) { if (type == "}") { cx.marked = "string-2"; cx.state.tokenize = tokenQuasi; - return cont(); + return cont(quasi); } } function arrowBody(type) { diff --git a/mode/javascript/test.js b/mode/javascript/test.js index 36341862f0..782f0457f9 100644 --- a/mode/javascript/test.js +++ b/mode/javascript/test.js @@ -70,6 +70,9 @@ MT("quasi", "[variable re][string-2 `fofdlakj${][variable x] [operator +] ([variable re][string-2 `foo`]) [operator +] [number 1][string-2 }fdsa`] [operator +] [number 2]"); + MT("quasi_no_function", + "[variable x] [operator =] [string-2 `fofdlakj${][variable x] [operator +] [string-2 `foo`] [operator +] [number 1][string-2 }fdsa`] [operator +] [number 2]"); + MT("indent_statement", "[keyword var] [variable x] [operator =] [number 10]", "[variable x] [operator +=] [variable y] [operator +]", From 5c6366faaeca35662fff50af3e943b0b91a419e0 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 17 Apr 2014 15:39:58 +0200 Subject: [PATCH 0613/4131] [xml mode] Fix giant indentation when continuing an attribute on a long line Closes #2473 --- mode/xml/xml.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/mode/xml/xml.js b/mode/xml/xml.js index b8c4297976..3248c454d1 100644 --- a/mode/xml/xml.js +++ b/mode/xml/xml.js @@ -321,7 +321,10 @@ CodeMirror.defineMode("xml", function(config, parserConfig) { var context = state.context; // Indent multi-line strings (e.g. css). if (state.tokenize.isInAttribute) { - return state.stringStartCol + 1; + if (state.tagStart == state.indented) + return state.stringStartCol + 1; + else + return state.indented + indentUnit; } if (context && context.noIndent) return CodeMirror.Pass; if (state.tokenize != inTag && state.tokenize != inText) From beb975f7e76c734044fa35a2c9a64b97f9eb5c94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Radek=20Pi=C3=B3rkowski?= Date: Tue, 15 Apr 2014 21:13:31 +0200 Subject: [PATCH 0614/4131] [php mode] Add support for interpolated variables in double-quoted strings. --- mode/php/index.html | 6 +- mode/php/php.js | 97 ++++++++++++++++++++++++++++- mode/php/test.js | 145 ++++++++++++++++++++++++++++++++++++++++++++ test/index.html | 3 + 4 files changed, 249 insertions(+), 2 deletions(-) create mode 100644 mode/php/test.js diff --git a/mode/php/index.html b/mode/php/index.html index 1fb7435bb1..dd25a5e788 100644 --- a/mode/php/index.html +++ b/mode/php/index.html @@ -32,8 +32,12 @@

    PHP mode

    DOWNLOAD LATEST RELEASE -
    version 4.0 (Release notes)
    +
    version 4.1 (Release notes)
    DONATE WITH PAYPAL diff --git a/lib/codemirror.js b/lib/codemirror.js index 0a07ed91ae..0ab217711e 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -7520,7 +7520,7 @@ // THE END - CodeMirror.version = "4.0.4"; + CodeMirror.version = "4.1.0"; return CodeMirror; }); diff --git a/package.json b/package.json index 39946f35f8..26d7053629 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "codemirror", - "version":"4.0.4", + "version":"4.1.0", "main": "lib/codemirror.js", "description": "In-browser code editing made bearable", "licenses": [{"type": "MIT", From 295c1aff82ad31e465c7ba391dde51d818b45a7c Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Tue, 22 Apr 2014 14:24:13 +0200 Subject: [PATCH 0630/4131] Bump version number post-4.1 --- doc/manual.html | 2 +- lib/codemirror.js | 2 +- package.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/manual.html b/doc/manual.html index f47e437ede..910d521ce6 100644 --- a/doc/manual.html +++ b/doc/manual.html @@ -63,7 +63,7 @@

    User manual and reference guide - version 4.1.0 + version 4.1.1

    CodeMirror is a code-editor component that can be embedded in diff --git a/lib/codemirror.js b/lib/codemirror.js index 0ab217711e..e4e92a06f6 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -7520,7 +7520,7 @@ // THE END - CodeMirror.version = "4.1.0"; + CodeMirror.version = "4.1.1"; return CodeMirror; }); diff --git a/package.json b/package.json index 26d7053629..8377f5a93e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "codemirror", - "version":"4.1.0", + "version":"4.1.1", "main": "lib/codemirror.js", "description": "In-browser code editing made bearable", "licenses": [{"type": "MIT", From ce4a4d8032105ab25f3065b88f274c56e2ba20c9 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Tue, 22 Apr 2014 15:18:39 +0200 Subject: [PATCH 0631/4131] [livescript mode] Fix empty tokens, clean up style Remove .ls source file --- mode/livescript/livescript.js | 31 ++-- mode/livescript/livescript.ls | 266 ---------------------------------- 2 files changed, 14 insertions(+), 283 deletions(-) delete mode 100644 mode/livescript/livescript.ls diff --git a/mode/livescript/livescript.js b/mode/livescript/livescript.js index 756181fafb..1efc3ecf66 100644 --- a/mode/livescript/livescript.js +++ b/mode/livescript/livescript.js @@ -11,18 +11,17 @@ else // Plain browser env mod(CodeMirror); })(function(CodeMirror) { -"use strict"; + "use strict"; -(function() { CodeMirror.defineMode('livescript', function(){ - var tokenBase, external; - tokenBase = function(stream, state){ - var next_rule, nr, i$, len$, r, m; - if (next_rule = state.next || 'start') { + var tokenBase = function(stream, state) { + var next_rule = state.next || "start"; + if (next_rule) { state.next = state.next; - if (Array.isArray(nr = Rules[next_rule])) { - for (i$ = 0, len$ = nr.length; i$ < len$; ++i$) { - r = nr[i$]; + var nr = Rules[next_rule]; + if (nr.splice) { + for (var i$ = 0; i$ < nr.length; ++i$) { + var r = nr[i$], m; if (r.regex && (m = stream.match(r.regex))) { state.next = r.next || state.next; return r.token; @@ -44,7 +43,7 @@ stream.next(); return 'error'; }; - external = { + var external = { startState: function(){ return { next: 'start', @@ -52,8 +51,8 @@ }; }, token: function(stream, state){ - var style; - style = tokenBase(stream, state); + while (stream.pos == stream.start) + var style = tokenBase(stream, state); state.lastToken = { style: style, indent: stream.indentation(), @@ -62,8 +61,7 @@ return style.replace(/\./g, ' '); }, indent: function(state){ - var indentation; - indentation = state.lastToken.indent; + var indentation = state.lastToken.indent; if (state.lastToken.content.match(indenter)) { indentation += 2; } @@ -262,7 +260,7 @@ }; for (var idx in Rules) { var r = Rules[idx]; - if (Array.isArray(r)) { + if (r.splice) { for (var i = 0, len = r.length; i < len; ++i) { var rr = r[i]; if (typeof rr.regex === 'string') { @@ -273,8 +271,7 @@ Rules[idx].regex = new RegExp('^' + r.regex); } } -})(); -CodeMirror.defineMIME('text/x-livescript', 'livescript'); + CodeMirror.defineMIME('text/x-livescript', 'livescript'); }); diff --git a/mode/livescript/livescript.ls b/mode/livescript/livescript.ls deleted file mode 100644 index 065242312a..0000000000 --- a/mode/livescript/livescript.ls +++ /dev/null @@ -1,266 +0,0 @@ -/** - * Link to the project's GitHub page: - * https://github.com/duralog/CodeMirror - */ -CodeMirror.defineMode 'livescript', (conf) -> - tokenBase = (stream, state) -> - #indent = - if next_rule = state.next or \start - state.next = state.next - if Array.isArray nr = Rules[next_rule] - for r in nr - if r.regex and m = stream.match r.regex - state.next = r.next - return r.token - stream.next! - return \error - if stream.match r = Rules[next_rule] - if r.regex and stream.match r.regex - state.next = r.next - return r.token - else - stream.next! - return \error - stream.next! - return 'error' - external = { - startState: (basecolumn) -> - { - next: \start - lastToken: null - } - token: (stream, state) -> - style = tokenBase stream, state #tokenLexer stream, state - state.lastToken = { - style: style - indent: stream.indentation! - content: stream.current! - } - style.replace /\./g, ' ' - indent: (state, textAfter) -> - # XXX this won't work with backcalls - indentation = state.lastToken.indent - if state.lastToken.content.match indenter then indentation += 2 - return indentation - } - external - -### Highlight Rules -# taken from mode-ls.ls - -indenter = // (? - : [({[=:] - | [-~]> - | \b (?: e(?:lse|xport) | d(?:o|efault) | t(?:ry|hen) | finally | - import (?:\s* all)? | const | var | - let | new | catch (?:\s* #identifier)? ) - ) \s* $ // - -identifier = /(?![\d\s])[$\w\xAA-\uFFDC](?:(?!\s)[$\w\xAA-\uFFDC]|-[A-Za-z])*/$ -keywordend = /(?![$\w]|-[A-Za-z]|\s*:(?![:=]))/$ -stringfill = token: \string, regex: '.+' - -Rules = - start: - * token: \comment.doc - regex: '/\\*' - next : \comment - - * token: \comment - regex: '#.*' - - * token: \keyword - regex: //(? - :t(?:h(?:is|row|en)|ry|ypeof!?) - |c(?:on(?:tinue|st)|a(?:se|tch)|lass) - |i(?:n(?:stanceof)?|mp(?:ort(?:\s+all)?|lements)|[fs]) - |d(?:e(?:fault|lete|bugger)|o) - |f(?:or(?:\s+own)?|inally|unction) - |s(?:uper|witch) - |e(?:lse|x(?:tends|port)|val) - |a(?:nd|rguments) - |n(?:ew|ot) - |un(?:less|til) - |w(?:hile|ith) - |o[fr]|return|break|let|var|loop - )//$ + keywordend - - * token: \constant.language - regex: '(?:true|false|yes|no|on|off|null|void|undefined)' + keywordend - - * token: \invalid.illegal - regex: '(? - :p(?:ackage|r(?:ivate|otected)|ublic) - |i(?:mplements|nterface) - |enum|static|yield - )' + keywordend - - * token: \language.support.class - regex: '(? - :R(?:e(?:gExp|ferenceError)|angeError) - |S(?:tring|yntaxError) - |E(?:rror|valError) - |Array|Boolean|Date|Function|Number|Object|TypeError|URIError - )' + keywordend - - * token: \language.support.function - regex: '(? - :is(?:NaN|Finite) - |parse(?:Int|Float) - |Math|JSON - |(?:en|de)codeURI(?:Component)? - )' + keywordend - - * token: \variable.language - regex: '(?:t(?:hat|il|o)|f(?:rom|allthrough)|it|by|e)' + keywordend - - * token: \identifier - regex: identifier + /\s*:(?![:=])/$ - - * token: \variable - regex: identifier - - * token: \keyword.operator - regex: /(?:\.{3}|\s+\?)/$ - - * token: \keyword.variable - regex: /(?:@+|::|\.\.)/$ - next : \key - - * token: \keyword.operator - regex: /\.\s*/$ - next : \key - - * token: \string - regex: /\\\S[^\s,;)}\]]*/$ - - * token: \string.doc - regex: \''' - next : \qdoc - - * token: \string.doc - regex: \""" - next : \qqdoc - - * token: \string - regex: \' - next : \qstring - - * token: \string - regex: \" - next : \qqstring - - * token: \string - regex: \` - next : \js - - * token: \string - regex: '<\\[' - next : \words - - * token: \string.regex - regex: \// - next : \heregex - - * token: \string.regex - regex: // - /(?: [^ [ / \n \\ ]* - (?: (?: \\. - | \[ [^\]\n\\]* (?:\\.[^\]\n\\]*)* \] - ) [^ [ / \n \\ ]* - )* - )/ [gimy$]{0,4} - //$ - next : \key - - * token: \constant.numeric - regex: '(?:0x[\\da-fA-F][\\da-fA-F_]* - |(?:[2-9]|[12]\\d|3[0-6])r[\\da-zA-Z][\\da-zA-Z_]* - |(?:\\d[\\d_]*(?:\\.\\d[\\d_]*)?|\\.\\d[\\d_]*) - (?:e[+-]?\\d[\\d_]*)?[\\w$]*)' - - * token: \lparen - regex: '[({[]' - - * token: \rparen - regex: '[)}\\]]' - next : \key - - * token: \keyword.operator - regex: \\\S+ - - * token: \text - regex: \\\s+ - - heregex: - * token: \string.regex - regex: '.*?//[gimy$?]{0,4}' - next : \start - * token: \string.regex - regex: '\\s*#{' - * token: \comment.regex - regex: '\\s+(?:#.*)?' - * token: \string.regex - regex: '\\S+' - - key: - * token: \keyword.operator - regex: '[.?@!]+' - * token: \identifier - regex: identifier - next : \start - * token: \text - regex: '.' - next : \start - - comment: - * token: \comment.doc - regex: '.*?\\*/' - next : \start - * token: \comment.doc - regex: '.+' - - qdoc: - token: \string - regex: ".*?'''" - next : \key - stringfill - - qqdoc: - token: \string - regex: '.*?"""' - next : \key - stringfill - - qstring: - token: \string - regex: /[^\\']*(?:\\.[^\\']*)*'/$ - next : \key - stringfill - - qqstring: - token: \string - regex: /[^\\"]*(?:\\.[^\\"]*)*"/$ - next : \key - stringfill - - js: - token: \string - regex: /[^\\`]*(?:\\.[^\\`]*)*`/$ - next : \key - stringfill - - words: - token: \string - regex: '.*?\\]>' - next : \key - stringfill - -# for optimization, precompile the regexps -for idx, r of Rules - if Array.isArray r - for rr, i in r - if rr.regex then Rules[idx][i].regex = new RegExp '^'+rr.regex - else if r.regex then Rules[idx].regex = new RegExp '^'+r.regex - -CodeMirror.defineMIME 'text/x-livescript', 'livescript' From 513fba04e227bf8cdcf2f9877c7626778243873e Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Tue, 22 Apr 2014 16:50:30 +0200 Subject: [PATCH 0632/4131] Register select-all detection timeout per editor So that a subsequent context menu handler can cancel it Issue #2491 --- lib/codemirror.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/lib/codemirror.js b/lib/codemirror.js index e4e92a06f6..8ca3b12ad7 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -3130,7 +3130,6 @@ // CONTEXT MENU HANDLING - var detectingSelectAll; // To make the context menu work, we need to briefly unhide the // textarea (making it as unobtrusive as possible) to let the // right-click take effect on it. @@ -3180,14 +3179,14 @@ // Try to detect the user choosing select-all if (display.input.selectionStart != null) { if (!ie || ie_upto8) prepareSelectAllHack(); - clearTimeout(detectingSelectAll); + clearTimeout(display.detectingSelectAll); var i = 0, poll = function() { if (display.selForContextMenu == cm.doc.sel && display.input.selectionStart == 0) operation(cm, commands.selectAll)(cm); - else if (i++ < 10) detectingSelectAll = setTimeout(poll, 500); + else if (i++ < 10) display.detectingSelectAll = setTimeout(poll, 500); else resetInput(cm); }; - detectingSelectAll = setTimeout(poll, 200); + display.detectingSelectAll = setTimeout(poll, 200); } } From 6ab1283f659a305b89167bce08b3ccde4d065074 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Tue, 22 Apr 2014 17:37:56 +0200 Subject: [PATCH 0633/4131] More proper prevention of select-all race condition Issue #2491 --- lib/codemirror.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/codemirror.js b/lib/codemirror.js index 8ca3b12ad7..2e615bd74a 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -3158,6 +3158,7 @@ // Adds "Select all" to context menu in FF if (!cm.somethingSelected()) display.input.value = display.prevInput = " "; display.selForContextMenu = cm.doc.sel; + clearTimeout(display.detectingSelectAll); // Select-all will be greyed out if there's nothing to select, so // this adds a zero-width space so that we can later check whether @@ -3179,7 +3180,6 @@ // Try to detect the user choosing select-all if (display.input.selectionStart != null) { if (!ie || ie_upto8) prepareSelectAllHack(); - clearTimeout(display.detectingSelectAll); var i = 0, poll = function() { if (display.selForContextMenu == cm.doc.sel && display.input.selectionStart == 0) operation(cm, commands.selectAll)(cm); From 708f68cb338bcf577bef1091a7a101b5953edf50 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Wed, 23 Apr 2014 13:16:53 +0200 Subject: [PATCH 0634/4131] Fix logic error in onFocus Issue #2494 --- demo/complete.html | 8 ++++++++ lib/codemirror.js | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/demo/complete.html b/demo/complete.html index 047a7ecca4..41c244b9a8 100644 --- a/demo/complete.html +++ b/demo/complete.html @@ -75,5 +75,13 @@

    Autocomplete Demo

    extraKeys: {"Ctrl-Space": "autocomplete"}, mode: {name: "javascript", globalVars: true} }); +document.querySelector("img#logo").addEventListener("click", function(e) { + editor.setSelection(CodeMirror.Pos(0, 0), CodeMirror.Pos(0, 10)); + console.log("before focus", editor.display.input.selectionEnd); + editor.focus(); + console.log("after focus", editor.display.input.selectionEnd); + e.stopPropagation(); + e.preventDefault(); +}, false); diff --git a/lib/codemirror.js b/lib/codemirror.js index 2e615bd74a..fa31adc161 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -3110,7 +3110,7 @@ // The prevInput test prevents this from firing when a context // menu is closed (since the resetInput would kill the // select-all detection hack) - if (!cm.curOp && cm.display.selForContextMenu == cm.doc.sel) { + if (!cm.curOp && cm.display.selForContextMenu != cm.doc.sel) { resetInput(cm); if (webkit) setTimeout(bind(resetInput, cm, true), 0); // Issue #1730 } From 1e3321f4c335569425900ab566a088c896a51ea0 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Wed, 23 Apr 2014 13:17:12 +0200 Subject: [PATCH 0635/4131] Remove debugging code --- demo/complete.html | 8 -------- 1 file changed, 8 deletions(-) diff --git a/demo/complete.html b/demo/complete.html index 41c244b9a8..047a7ecca4 100644 --- a/demo/complete.html +++ b/demo/complete.html @@ -75,13 +75,5 @@

    Autocomplete Demo

    extraKeys: {"Ctrl-Space": "autocomplete"}, mode: {name: "javascript", globalVars: true} }); -document.querySelector("img#logo").addEventListener("click", function(e) { - editor.setSelection(CodeMirror.Pos(0, 0), CodeMirror.Pos(0, 10)); - console.log("before focus", editor.display.input.selectionEnd); - editor.focus(); - console.log("after focus", editor.display.input.selectionEnd); - e.stopPropagation(); - e.preventDefault(); -}, false); From fb1fc604aad3ebd8848b7630947c9b8952add500 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Wed, 23 Apr 2014 17:08:28 +0200 Subject: [PATCH 0636/4131] Prevent select-all hack from confusing readInput when there is a selection Issue #2496 --- lib/codemirror.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/codemirror.js b/lib/codemirror.js index fa31adc161..02c25d40be 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -2246,6 +2246,8 @@ if (withOp) startOperation(cm); cm.display.shift = false; + if (text.charCodeAt(0) == 0x200b && doc.sel == cm.display.selForContextMenu && !prevInput) + prevInput = "\u200b"; // Find the part of the input that is actually new var same = 0, l = Math.min(prevInput.length, text.length); while (same < l && prevInput.charCodeAt(same) == text.charCodeAt(same)) ++same; From 0558dfe76ceae8764011c982d13a766087c9dd20 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Wed, 23 Apr 2014 17:12:32 +0200 Subject: [PATCH 0637/4131] Another fix around the select-all hack Issue #2495 --- lib/codemirror.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/codemirror.js b/lib/codemirror.js index 02c25d40be..ca9be7acab 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -230,6 +230,10 @@ // True when shift is held down. d.shift = false; + + // Used to track whether anything happened since the context menu + // was opened. + d.selForContextMenu = null; } // STATE UPDATES @@ -3498,6 +3502,7 @@ if (changeHandler) signalLater(cm, "change", cm, obj); if (changesHandler) (cm.curOp.changeObjs || (cm.curOp.changeObjs = [])).push(obj); } + cm.display.selForContextMenu = null; } function replaceRange(doc, code, from, to, origin) { From 4ea847025f65bc49ea1157100917f5da67433960 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 24 Apr 2014 10:09:27 +0200 Subject: [PATCH 0638/4131] Scroll change, rather than cursor, into view on undo/redo --- lib/codemirror.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/codemirror.js b/lib/codemirror.js index ca9be7acab..f636832fff 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -3388,7 +3388,7 @@ var after = i ? computeSelAfterChange(doc, change, null) : lst(source); makeChangeSingleDoc(doc, change, after, mergeOldSpans(doc, change)); - if (doc.cm) ensureCursorVisible(doc.cm); + if (!i && doc.cm) doc.cm.scrollIntoView(change); var rebased = []; // Propagate to the linked documents From 068227e4e9dd04c29da343ac2440c6b9a6e945ba Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 24 Apr 2014 10:22:06 +0200 Subject: [PATCH 0639/4131] Fall back to nullRect in measureCharInner to work around Safari issue Issue #2492 --- lib/codemirror.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/codemirror.js b/lib/codemirror.js index f636832fff..0aec28d822 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -1625,7 +1625,7 @@ else rect = nullRect; } else { - rect = range(node, start, end).getBoundingClientRect(); + rect = range(node, start, end).getBoundingClientRect() || nullRect; } } else { // If it is a widget, simply get the box for the whole widget. if (start > 0) collapse = bias = "right"; From 9fa870fef10b8389e0592cd0b6b831bc265b1839 Mon Sep 17 00:00:00 2001 From: Forbes Lindesay Date: Tue, 22 Apr 2014 14:56:25 +0100 Subject: [PATCH 0640/4131] [jade mode] Re-write to match the jade lexer --- mode/jade/index.html | 8 +- mode/jade/jade.js | 650 +++++++++++++++++++++++++++++++++++++------ 2 files changed, 574 insertions(+), 84 deletions(-) diff --git a/mode/jade/index.html b/mode/jade/index.html index e22b15e65b..8bfd5620c0 100644 --- a/mode/jade/index.html +++ b/mode/jade/index.html @@ -6,6 +6,10 @@ + + + +
    ' + - '' + - val.replace(/ /g,'\xb7').replace('&', '&').replace('<', '<') + + '' + + '' + + esc(val.replace(/ /g,'\xb7')) + '' + '
    '; s += ''; - for (var i = 0; i < output.length; i += 2) { - var style = output[i], val = output[i+1]; + for (var i = 0; i < output.length; ++i) { + var style = output[i].style, val = output[i].text; s += ''; } s += ''; - for (var i = 0; i < output.length; i += 2) { - s += ''; + for (var i = 0; i < output.length; ++i) { + s += ''; } s += '
    ' + '' + @@ -163,8 +163,8 @@ '
    ' + (output[i] || null) + '' + (output[i].style || null) + '
    '; return s; From eab52760ffe9baa44eb4175059f24f720da7cdd8 Mon Sep 17 00:00:00 2001 From: Beni Cherniavsky-Paskin Date: Thu, 1 May 2014 14:27:21 -0700 Subject: [PATCH 0684/4131] mode tests: optionally show mode state after every token. Doesn't show states (but shouldn't crash) on old browsers. --- test/mode_test.css | 12 ++++++++++++ test/mode_test.js | 30 +++++++++++++++++++++++++----- 2 files changed, 37 insertions(+), 5 deletions(-) diff --git a/test/mode_test.css b/test/mode_test.css index 1ac66737fb..7ae3b0ada8 100644 --- a/test/mode_test.css +++ b/test/mode_test.css @@ -8,3 +8,15 @@ .mt-output .mt-style { font-size: x-small; } + +.mt-output .mt-state { + font-size: x-small; +} + +.mt-output .mt-state-row { + display: none; +} + +.mt-state-unhide .mt-output .mt-state-row { + display: table-row; +} diff --git a/test/mode_test.js b/test/mode_test.js index 82364eaec7..2e16eba0ee 100644 --- a/test/mode_test.js +++ b/test/mode_test.js @@ -67,7 +67,8 @@ }; function esc(str) { - return str.replace('&', '&').replace('<', '<'); + return str.replace('&', '&').replace('<', '<').replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'"); +; } function compare(text, expected, mode) { @@ -89,7 +90,7 @@ s += '
    '; s += 'expected:'; s += prettyPrintOutputTable(expectedOutput, diff); - s += 'observed:'; + s += 'observed: [display states]'; s += prettyPrintOutputTable(observedOutput, diff); s += '
    '; s += '
    '; @@ -101,6 +102,19 @@ if (s) throw new Failure(s); } + function stringify(obj) { + function replacer(key, obj) { + if (typeof obj == "function") { + var m = obj.toString().match(/function\s*[^\s(]*/); + return m ? m[0] : "function"; + } + return obj; + } + if (window.JSON && JSON.stringify) + return JSON.stringify(obj, replacer, 2); + return "[unsupported]"; // Fail safely if no native JSON. + } + function highlight(string, mode) { var state = mode.startState(); @@ -129,7 +143,7 @@ if (pos && st[pos-1].style == compare && !newLine) { st[pos-1].text += substr; } else if (substr) { - st[pos++] = {style: compare, text: substr}; + st[pos++] = {style: compare, text: substr, state: stringify(state)}; } // Give up when line is ridiculously long if (stream.pos > 5000) { @@ -158,7 +172,7 @@ s += '' + '' + - esc(val.replace(/ /g,'\xb7')) + + esc(val.replace(/ /g,'\xb7')) + // · MIDDLE DOT '' + ''; } @@ -166,7 +180,13 @@ for (var i = 0; i < output.length; ++i) { s += '' + (output[i].style || null) + ''; } - s += ''; + if(output[0].state) { + s += ''; + for (var i = 0; i < output.length; ++i) { + s += '
    ' + esc(output[i].state) + '
    '; + } + } + s += ''; return s; } })(); From 579a6e015aea4c3858f2e04230d172660deecf15 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 5 May 2014 12:15:34 +0200 Subject: [PATCH 0685/4131] [test runner] Top-align mode test states --- mode/javascript/test.js | 2 +- test/mode_test.css | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/mode/javascript/test.js b/mode/javascript/test.js index 782f0457f9..f5ddcc43de 100644 --- a/mode/javascript/test.js +++ b/mode/javascript/test.js @@ -9,7 +9,7 @@ "[keyword function](){ [keyword var] [def x] [operator =] [number 1] [operator +] [number 2], [def y]; }"); MT("destructuring", - "([keyword function]([def a], [[[def b], [def c] ]]) {", + "([keywordo function]([def a], [[[def b], [def c] ]]) {", " [keyword let] {[def d], [property foo]: [def c][operator =][number 10], [def x]} [operator =] [variable foo]([variable-2 a]);", " [[[variable-2 c], [variable y] ]] [operator =] [variable-2 c];", "})();"); diff --git a/test/mode_test.css b/test/mode_test.css index 7ae3b0ada8..f83271b4e2 100644 --- a/test/mode_test.css +++ b/test/mode_test.css @@ -11,6 +11,7 @@ .mt-output .mt-state { font-size: x-small; + vertical-align: top; } .mt-output .mt-state-row { From 39788f1d77762668e435fef908dc152a0c98a52f Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 5 May 2014 12:18:57 +0200 Subject: [PATCH 0686/4131] Revert intentionally broken but unintentionally committed test --- mode/javascript/test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mode/javascript/test.js b/mode/javascript/test.js index f5ddcc43de..782f0457f9 100644 --- a/mode/javascript/test.js +++ b/mode/javascript/test.js @@ -9,7 +9,7 @@ "[keyword function](){ [keyword var] [def x] [operator =] [number 1] [operator +] [number 2], [def y]; }"); MT("destructuring", - "([keywordo function]([def a], [[[def b], [def c] ]]) {", + "([keyword function]([def a], [[[def b], [def c] ]]) {", " [keyword let] {[def d], [property foo]: [def c][operator =][number 10], [def x]} [operator =] [variable foo]([variable-2 a]);", " [[[variable-2 c], [variable y] ]] [operator =] [variable-2 c];", "})();"); From a0bd44226e24694d96fd100452b67da1f5d1c4ec Mon Sep 17 00:00:00 2001 From: Anders Nawroth Date: Mon, 5 May 2014 10:24:01 +0200 Subject: [PATCH 0687/4131] [cypher mode] Add UNWIND keyword --- mode/cypher/cypher.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mode/cypher/cypher.js b/mode/cypher/cypher.js index da6f3acaae..f102c9ec1a 100644 --- a/mode/cypher/cypher.js +++ b/mode/cypher/cypher.js @@ -59,7 +59,7 @@ var curPunc; var funcs = wordRegexp(["abs", "acos", "allShortestPaths", "asin", "atan", "atan2", "avg", "ceil", "coalesce", "collect", "cos", "cot", "count", "degrees", "e", "endnode", "exp", "extract", "filter", "floor", "haversin", "head", "id", "labels", "last", "left", "length", "log", "log10", "lower", "ltrim", "max", "min", "node", "nodes", "percentileCont", "percentileDisc", "pi", "radians", "rand", "range", "reduce", "rel", "relationship", "relationships", "replace", "right", "round", "rtrim", "shortestPath", "sign", "sin", "split", "sqrt", "startnode", "stdev", "stdevp", "str", "substring", "sum", "tail", "tan", "timestamp", "toFloat", "toInt", "trim", "type", "upper"]); var preds = wordRegexp(["all", "and", "any", "has", "in", "none", "not", "or", "single", "xor"]); - var keywords = wordRegexp(["as", "asc", "ascending", "assert", "by", "case", "commit", "constraint", "create", "csv", "cypher", "delete", "desc", "descending", "distinct", "drop", "else", "end", "false", "foreach", "from", "headers", "in", "index", "is", "limit", "load", "match", "merge", "null", "on", "optional", "order", "periodic", "remove", "return", "scan", "set", "skip", "start", "then", "true", "union", "unique", "using", "when", "where", "with"]); + var keywords = wordRegexp(["as", "asc", "ascending", "assert", "by", "case", "commit", "constraint", "create", "csv", "cypher", "delete", "desc", "descending", "distinct", "drop", "else", "end", "false", "foreach", "from", "headers", "in", "index", "is", "limit", "load", "match", "merge", "null", "on", "optional", "order", "periodic", "remove", "return", "scan", "set", "skip", "start", "then", "true", "union", "unique", "unwind", "using", "when", "where", "with"]); var operatorChars = /[*+\-<>=&|~%^]/; return { From 0c3da1a0c937fee28fc9169ee02e8301c9984903 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Tue, 6 May 2014 10:54:20 +0200 Subject: [PATCH 0688/4131] [match-highlighter addon] Use primary selection, not first one Closes #2539 --- addon/search/match-highlighter.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/addon/search/match-highlighter.js b/addon/search/match-highlighter.js index d9c818b838..83ab8c33c7 100644 --- a/addon/search/match-highlighter.js +++ b/addon/search/match-highlighter.js @@ -76,8 +76,9 @@ cm.addOverlay(state.overlay = makeOverlay(line.slice(start, end), re, state.style)); return; } - if (cm.getCursor("head").line != cm.getCursor("anchor").line) return; - var selection = cm.getSelections()[0].replace(/^\s+|\s+$/g, ""); + var from = cm.getCursor("from"), to = cm.getCursor("to"); + if (from.line != to.line) return; + var selection = cm.getRange(from, to).replace(/^\s+|\s+$/g, ""); if (selection.length >= state.minChars) cm.addOverlay(state.overlay = makeOverlay(selection, false, state.style)); }); From 1adf6180d0f0297ac314f87ff89d2de84cdc938a Mon Sep 17 00:00:00 2001 From: Panupong Pasupat Date: Mon, 5 May 2014 21:29:32 -0700 Subject: [PATCH 0689/4131] [markdown mode] Fix code block styling after indented line --- mode/markdown/markdown.js | 3 +-- mode/markdown/test.js | 8 ++++++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/mode/markdown/markdown.js b/mode/markdown/markdown.js index ff466be86f..92f71275f4 100644 --- a/mode/markdown/markdown.js +++ b/mode/markdown/markdown.js @@ -709,8 +709,7 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) { if (forceBlankLine) { state.prevLineHasContent = false; - blankLine(state); - return this.token(stream, state); + return blankLine(state); } else { state.prevLineHasContent = state.thisLineHasContent; state.thisLineHasContent = true; diff --git a/mode/markdown/test.js b/mode/markdown/test.js index c3016d3a6a..984d876e38 100644 --- a/mode/markdown/test.js +++ b/mode/markdown/test.js @@ -89,6 +89,14 @@ " [comment hello]", " [comment world]"); + // Code blocks should end even after extra indented lines + MT("codeBlocksWithTrailingIndentedLine", + " [comment foo]", + " [comment bar]", + " [comment baz]", + " ", + "hello"); + // Code blocks using 1 tab (regardless of CodeMirror.indentWithTabs value) MT("codeBlocksUsing1Tab", "\t[comment foo]"); From 90650c649327da228ed4f384da512089ac38f8ce Mon Sep 17 00:00:00 2001 From: Panupong Pasupat Date: Mon, 5 May 2014 21:49:49 -0700 Subject: [PATCH 0690/4131] [markdown mode] Fix XML styling in Markdown mode Fix the condition when XML styling should be invoked. Also add test cases. --- mode/markdown/markdown.js | 2 +- mode/markdown/test.js | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/mode/markdown/markdown.js b/mode/markdown/markdown.js index 92f71275f4..84ea4d46b9 100644 --- a/mode/markdown/markdown.js +++ b/mode/markdown/markdown.js @@ -209,7 +209,7 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) { function htmlBlock(stream, state) { var style = htmlMode.token(stream, state.htmlState); - if ((htmlFound && !state.htmlState.tagName && !state.htmlState.context) || + if ((htmlFound && state.htmlState.tagStart === null && !state.htmlState.context) || (state.md_inside && stream.current().indexOf(">") > -1)) { state.f = inlineNormal; state.block = blockNormal; diff --git a/mode/markdown/test.js b/mode/markdown/test.js index 984d876e38..4d1d70ad14 100644 --- a/mode/markdown/test.js +++ b/mode/markdown/test.js @@ -729,4 +729,23 @@ "[comment ```]", "foo", "[comment ```]"); + + // Tests that require XML mode + + MT("xmlMode", + "[tag&bracket <][tag div][tag&bracket >]", + "*foo*", + "[tag&bracket <][tag http://github.com][tag&bracket />]", + "[tag&bracket ]", + "[link ]"); + + MT("xmlModeWithMarkdownInside", + "[tag&bracket <][tag div] [attribute markdown]=[string 1][tag&bracket >]", + "[em *foo*]", + "[link ]", + "[tag ]", + "[link ]", + "[tag&bracket <][tag div][tag&bracket >]", + "[tag&bracket ]"); + })(); From 60ab165bfa2bfc81b97d3b2b2d16c9665002adf5 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Tue, 6 May 2014 11:04:27 +0200 Subject: [PATCH 0691/4131] [dylan mode] Add module loading shim Closes #2533 --- mode/dylan/dylan.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/mode/dylan/dylan.js b/mode/dylan/dylan.js index d81ef0cbcb..ccf9679181 100644 --- a/mode/dylan/dylan.js +++ b/mode/dylan/dylan.js @@ -1,3 +1,13 @@ +(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.defineMode("dylan", function(_config) { // Words var words = { @@ -282,3 +292,5 @@ CodeMirror.defineMode("dylan", function(_config) { }); CodeMirror.defineMIME("text/x-dylan", "dylan"); + +}); From 6abb339705fd234de93b14c28f37a5a212b65629 Mon Sep 17 00:00:00 2001 From: binny Date: Mon, 5 May 2014 21:55:30 +0530 Subject: [PATCH 0692/4131] [vim] Visual paste operation with unit tests --- keymap/vim.js | 61 +++++++++++++++++++++++++++++------------------- test/vim_test.js | 25 ++++++++++++++++++++ 2 files changed, 62 insertions(+), 24 deletions(-) diff --git a/keymap/vim.js b/keymap/vim.js index c78d76af94..1ea39c1ef0 100644 --- a/keymap/vim.js +++ b/keymap/vim.js @@ -2051,7 +2051,7 @@ } this.enterInsertMode(cm, { repeat: actionArgs.repeat }, vim); }, - paste: function(cm, actionArgs) { + paste: function(cm, actionArgs, vim) { var cur = copyCursor(cm.getCursor()); var register = vimGlobalState.registerController.getRegister( actionArgs.registerName); @@ -2092,7 +2092,9 @@ } var linewise = register.linewise; if (linewise) { - if (actionArgs.after) { + if(vim.visualMode) { + text = vim.visualLine ? text.slice(0, -1) : '\n' + text.slice(0, text.length - 1) + '\n'; + } else if (actionArgs.after) { // Move the newline at the end to the start instead, and paste just // before the newline character of the line we are on right now. text = '\n' + text.slice(0, text.length - 1); @@ -2103,24 +2105,35 @@ } else { cur.ch += actionArgs.after ? 1 : 0; } - cm.replaceRange(text, cur); - // Now fine tune the cursor to where we want it. var curPosFinal; var idx; - if (linewise && actionArgs.after) { - curPosFinal = Pos( - cur.line + 1, - findFirstNonWhiteSpaceCharacter(cm.getLine(cur.line + 1))); - } else if (linewise && !actionArgs.after) { - curPosFinal = Pos( - cur.line, - findFirstNonWhiteSpaceCharacter(cm.getLine(cur.line))); - } else if (!linewise && actionArgs.after) { - idx = cm.indexFromPos(cur); - curPosFinal = cm.posFromIndex(idx + text.length - 1); + if (vim.visualMode) { + var selectedArea = getSelectedAreaRange(cm, vim); + var selectionStart = selectedArea[0]; + var selectionEnd = selectedArea[1]; + // push the previously selected text to unnamed register + vimGlobalState.registerController.unnamedRegister.setText(cm.getRange(selectionStart, selectionEnd)); + cm.replaceRange(text, selectionStart, selectionEnd); + curPosFinal = cm.posFromIndex(cm.indexFromPos(selectionStart) + text.length - 1); + if(linewise)curPosFinal.ch=0; } else { - idx = cm.indexFromPos(cur); - curPosFinal = cm.posFromIndex(idx + text.length); + cm.replaceRange(text, cur); + // Now fine tune the cursor to where we want it. + if (linewise && actionArgs.after) { + curPosFinal = Pos( + cur.line + 1, + findFirstNonWhiteSpaceCharacter(cm.getLine(cur.line + 1))); + } else if (linewise && !actionArgs.after) { + curPosFinal = Pos( + cur.line, + findFirstNonWhiteSpaceCharacter(cm.getLine(cur.line))); + } else if (!linewise && actionArgs.after) { + idx = cm.indexFromPos(cur); + curPosFinal = cm.posFromIndex(idx + text.length - 1); + } else { + idx = cm.indexFromPos(cur); + curPosFinal = cm.posFromIndex(idx + text.length); + } } cm.setCursor(curPosFinal); }, @@ -2220,13 +2233,6 @@ var selectionStart = selectedAreaRange[0]; var selectionEnd = selectedAreaRange[1]; var toLower = actionArgs.toLower; - if (cursorIsBefore(selectionEnd, selectionStart)) { - var tmp = selectionStart; - selectionStart = selectionEnd; - selectionEnd = tmp; - } else { - selectionEnd = cm.clipPos(Pos(selectionEnd.line, selectionEnd.ch+1)); - } var text = cm.getRange(selectionStart, selectionEnd); cm.replaceRange(toLower ? text.toLowerCase() : text.toUpperCase(), selectionStart, selectionEnd); cm.setCursor(selectionStart); @@ -2324,6 +2330,13 @@ return [{line: selectionStart.line, ch: 0}, {line: selectionEnd.line, ch: lineLength(cm, selectionEnd.line)}]; } } else { + if (cursorIsBefore(selectionEnd, selectionStart)) { + var tmp = selectionStart; + selectionStart = selectionEnd; + selectionEnd = tmp; + } else { + selectionEnd = cm.clipPos(Pos(selectionEnd.line, selectionEnd.ch+1)); + } exitVisualMode(cm); } return [selectionStart, selectionEnd]; diff --git a/test/vim_test.js b/test/vim_test.js index 71cd5ed941..a3f3fed3ad 100644 --- a/test/vim_test.js +++ b/test/vim_test.js @@ -1639,6 +1639,31 @@ testVim('uppercase/lowercase_visual', function(cm, vim, helpers) { helpers.doKeys('V', 'U', 'j', '.'); eq('ABCDEF\nGHIJKL\nMnopq\nSHORT LINE\nLONG LINE OF TEXT', cm.getValue()); }, { value: 'abcdef\nghijkl\nmnopq\nshort line\nlong line of text'}); +testVim('visual_paste', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('v', 'l', 'l', 'y', 'j', 'v', 'l', 'p'); + helpers.assertCursorAt(1, 4); + eq('this is a\nunthi test for visual paste', cm.getValue()); + cm.setCursor(0, 0); + // in case of pasting whole line + helpers.doKeys('y', 'y'); + cm.setCursor(1, 6); + helpers.doKeys('v', 'l', 'l', 'l', 'p'); + helpers.assertCursorAt(2, 0); + eq('this is a\nunthi \nthis is a\n for visual paste', cm.getValue()); +}, { value: 'this is a\nunit test for visual paste'}); + +// This checks the contents of the register used to paste the text +testVim('v_paste_from_register', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('"', 'a', 'y', 'w'); + cm.setCursor(1, 0); + helpers.doKeys('v', 'p'); + cm.openDialog = helpers.fakeOpenDialog('registers'); + cm.openNotification = helpers.fakeOpenNotification(function(text) { + is(/a\s+register/.test(text)); + }); +}, { value: 'register contents\nare not erased'}); testVim('S_normal', function(cm, vim, helpers) { cm.setCursor(0, 1); helpers.doKeys('j', 'S'); From 6db5ec2870fc78977c817e35440185e26bff9175 Mon Sep 17 00:00:00 2001 From: binny Date: Wed, 30 Apr 2014 06:01:39 +0530 Subject: [PATCH 0693/4131] [vim] support for append action command in visual mode added --- keymap/vim.js | 8 ++++++++ test/vim_test.js | 7 +++++++ 2 files changed, 15 insertions(+) diff --git a/keymap/vim.js b/keymap/vim.js index 1ea39c1ef0..c48506adaa 100644 --- a/keymap/vim.js +++ b/keymap/vim.js @@ -271,6 +271,7 @@ 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, @@ -1914,6 +1915,13 @@ cm.setCursor(offsetCursor(cm.getCursor(), 0, 1)); } else if (insertAt == 'firstNonBlank') { cm.setCursor(motions.moveToFirstNonWhiteSpaceCharacter(cm)); + } else if (insertAt == 'endOfSelectedArea') { + var selectionEnd = cm.getCursor('head'); + var selectionStart = cm.getCursor('anchor'); + var cursor = cm.getCursor(); + cursor = cursorIsBefore(selectionStart, selectionEnd) ? Pos(cursor.line, selectionEnd.ch+1) : Pos(cursor.line, selectionEnd.ch); + cm.setCursor(cursor); + exitVisualMode(cm); } cm.setOption('keyMap', 'vim-insert'); cm.setOption('disableInput', false); diff --git a/test/vim_test.js b/test/vim_test.js index a3f3fed3ad..fecc52ba35 100644 --- a/test/vim_test.js +++ b/test/vim_test.js @@ -1141,6 +1141,13 @@ testVim('a_eol', function(cm, vim, helpers) { helpers.assertCursorAt(0, lines[0].length); eq('vim-insert', cm.getOption('keyMap')); }); +testVim('a_endOfSelectedArea', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('v', 'j', 'l'); + helpers.doKeys('A'); + helpers.assertCursorAt(1, 2); + eq('vim-insert', cm.getOption('keyMap')); +}, {value: 'foo\nbar'}); testVim('i', function(cm, vim, helpers) { cm.setCursor(0, 1); helpers.doKeys('i'); From 546eb6ce365d860d1649f0b6e22cd6b1f7879a21 Mon Sep 17 00:00:00 2001 From: binny Date: Fri, 2 May 2014 03:32:33 +0530 Subject: [PATCH 0694/4131] [vim] Resolve upward selection bug --- keymap/vim.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/keymap/vim.js b/keymap/vim.js index c48506adaa..e33d269089 100644 --- a/keymap/vim.js +++ b/keymap/vim.js @@ -1918,9 +1918,8 @@ } else if (insertAt == 'endOfSelectedArea') { var selectionEnd = cm.getCursor('head'); var selectionStart = cm.getCursor('anchor'); - var cursor = cm.getCursor(); - cursor = cursorIsBefore(selectionStart, selectionEnd) ? Pos(cursor.line, selectionEnd.ch+1) : Pos(cursor.line, selectionEnd.ch); - cm.setCursor(cursor); + selectionEnd = cursorIsBefore(selectionStart, selectionEnd) ? Pos(selectionEnd.line, selectionEnd.ch+1) : (selectionEnd.line < selectionStart.line ? Pos(selectionStart.line, 0) : selectionEnd); + cm.setCursor(selectionEnd); exitVisualMode(cm); } cm.setOption('keyMap', 'vim-insert'); From 41a29b0132445f8f10a5fc4b83f7c1e456171d03 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 8 May 2014 12:22:20 +0200 Subject: [PATCH 0695/4131] Abort wheel delta measurement when scrolling explicitly Issue #2537 --- lib/codemirror.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/codemirror.js b/lib/codemirror.js index 4a843d3f63..0bf6f2d8e8 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -1927,6 +1927,10 @@ if (!updated && op.selectionChanged) updateSelection(cm); if (!updated && op.startHeight != cm.doc.height) updateScrollbars(cm); + // Abort mouse wheel delta measurement, when scrolling explicitly + if (display.wheelStartX != null && (op.scrollTop != null || op.scrollLeft != null || op.scrollToPos)) + display.wheelStartX = display.wheelStartY = null; + // Propagate the scroll position to the actual DOM scroller if (op.scrollTop != null && display.scroller.scrollTop != op.scrollTop) { var top = Math.max(0, Math.min(display.scroller.scrollHeight - display.scroller.clientHeight, op.scrollTop)); From 0efe7a57115a252abf033e16ea1d1a375cd5a229 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Fri, 9 May 2014 14:48:38 +0200 Subject: [PATCH 0696/4131] [sublime keybindings] Don't include zero-char selection bottoms in swapLine* Issue #2542 --- keymap/sublime.js | 16 ++++++++-------- test/sublime_test.js | 6 ++++++ 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/keymap/sublime.js b/keymap/sublime.js index eea46347fd..9158e27944 100644 --- a/keymap/sublime.js +++ b/keymap/sublime.js @@ -184,9 +184,12 @@ }; cmds[map["Shift-" + ctrl + "Up"] = "swapLineUp"] = function(cm) { - var ranges = cm.listSelections(), linesToMove = [], at = cm.firstLine() - 1; + var ranges = cm.listSelections(), linesToMove = [], at = cm.firstLine() - 1, newSels = []; for (var i = 0; i < ranges.length; i++) { var range = ranges[i], from = range.from().line - 1, to = range.to().line; + newSels.push({anchor: Pos(range.anchor.line - 1, range.anchor.ch), + head: Pos(range.head.line - 1, range.head.ch)}); + if (range.to().ch == 0 && !range.empty()) --to; if (from > at) linesToMove.push(from, to); else if (linesToMove.length) linesToMove[linesToMove.length - 1] = to; at = to; @@ -196,16 +199,12 @@ var from = linesToMove[i], to = linesToMove[i + 1]; var line = cm.getLine(from); cm.replaceRange("", Pos(from, 0), Pos(from + 1, 0), "+swapLine"); - if (to > cm.lastLine()) { + if (to > cm.lastLine()) cm.replaceRange("\n" + line, Pos(cm.lastLine()), null, "+swapLine"); - var sels = cm.listSelections(), last = sels[sels.length - 1]; - var head = last.head.line == to ? Pos(to - 1) : last.head; - var anchor = last.anchor.line == to ? Pos(to - 1) : last.anchor; - cm.setSelections(sels.slice(0, sels.length - 1).concat([{head: head, anchor: anchor}])); - } else { + else cm.replaceRange(line + "\n", Pos(to, 0), null, "+swapLine"); - } } + cm.setSelections(newSels); cm.scrollIntoView(); }); }; @@ -214,6 +213,7 @@ var ranges = cm.listSelections(), linesToMove = [], at = cm.lastLine() + 1; for (var i = ranges.length - 1; i >= 0; i--) { var range = ranges[i], from = range.to().line + 1, to = range.from().line; + if (range.to().ch == 0 && !range.empty()) from--; if (from < at) linesToMove.push(from, to); else if (linesToMove.length) linesToMove[linesToMove.length - 1] = to; at = to; diff --git a/test/sublime_test.js b/test/sublime_test.js index f09504c51a..c93e041b87 100644 --- a/test/sublime_test.js +++ b/test/sublime_test.js @@ -178,6 +178,12 @@ 1, 0, 2, 0, 2, 2, 2, 2)); + stTest("swapLineEmptyBottomSel", "1\n2\n3", + setSel(0, 1, 1, 0), + "swapLineDown", val("2\n1\n3"), hasSel(1, 1, 2, 0), + "swapLineUp", val("1\n2\n3"), hasSel(0, 1, 1, 0), + "swapLineUp", val("1\n2\n3"), hasSel(0, 0, 0, 0)); + stTest("swapLineUpFromEnd", "a\nb\nc", Pos(2, 1), "swapLineUp", hasSel(1, 1, 1, 1), val("a\nc\nb")); From fea31914767042d0d42800ab82dc29b3e76a6a2b Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Fri, 9 May 2014 15:18:36 +0200 Subject: [PATCH 0697/4131] [javascript-hint addon] Support an option that disables use of the current global scope --- addon/hint/javascript-hint.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/addon/hint/javascript-hint.js b/addon/hint/javascript-hint.js index 305bb85a29..baf20b45dc 100644 --- a/addon/hint/javascript-hint.js +++ b/addon/hint/javascript-hint.js @@ -108,7 +108,8 @@ if (obj.type && obj.type.indexOf("variable") === 0) { if (options && options.additionalContext) base = options.additionalContext[obj.string]; - base = base || window[obj.string]; + if (!options || options.useGlobalScope !== false) + base = base || window[obj.string]; } else if (obj.type == "string") { base = ""; } else if (obj.type == "atom") { @@ -128,7 +129,8 @@ // (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); - gatherCompletions(window); + if (!options || options.useGlobalScope !== false) + gatherCompletions(window); forEach(keywords, maybeAdd); } return found; From a6faf989152a86a22f6155a775f3c16d724d1a88 Mon Sep 17 00:00:00 2001 From: Bem Jones-Bey Date: Tue, 6 May 2014 15:00:32 -0700 Subject: [PATCH 0698/4131] [css mode] Add more CSS Shapes properties Add shape-image-threshold and shape-margin. --- mode/css/css.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mode/css/css.js b/mode/css/css.js index 3fae9687fd..8828329fc4 100644 --- a/mode/css/css.js +++ b/mode/css/css.js @@ -433,8 +433,8 @@ CodeMirror.defineMode("css", function(config, parserConfig) { "region-break-before", "region-break-inside", "region-fragment", "rendering-intent", "resize", "rest", "rest-after", "rest-before", "richness", "right", "rotation", "rotation-point", "ruby-align", "ruby-overhang", - "ruby-position", "ruby-span", "shape-inside", "shape-outside", "size", - "speak", "speak-as", "speak-header", + "ruby-position", "ruby-span", "shape-image-threshold", "shape-inside", "shape-margin", + "shape-outside", "size", "speak", "speak-as", "speak-header", "speak-numeral", "speak-punctuation", "speech-rate", "stress", "string-set", "tab-size", "table-layout", "target", "target-name", "target-new", "target-position", "text-align", "text-align-last", "text-decoration", From 81aeea3757b2c9826af68fb21fd5a170684f0aac Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Fri, 9 May 2014 15:24:47 +0200 Subject: [PATCH 0699/4131] [real-world uses] Add Better Text Viewer and CrossUI --- doc/realworld.html | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/realworld.html b/doc/realworld.html index ccfbf4be41..e6649b1f02 100644 --- a/doc/realworld.html +++ b/doc/realworld.html @@ -28,6 +28,7 @@

    CodeMirror real-world uses

  • Adobe Brackets (code editor)
  • Amber (JavaScript-based Smalltalk system)
  • APEye (tool for testing & documenting APIs)
  • +
  • Better Text Viewer (plain text reader app for Chrome)
  • Bitbucket (code hosting)
  • Blogger's template editor
  • BlueGriffon (HTML editor)
  • @@ -35,6 +36,7 @@

    CodeMirror real-world uses

  • Chrome DevTools
  • ClickHelp (technical writing tool)
  • Complete.ly playground
  • +
  • CrossUI (cross-platform UI builder)
  • Cruncher (notepad with calculation features)
  • Code per Node (Drupal module)
  • Codebug (PHP Xdebug front-end)
  • From 01e844f09eb74ad55a987779ead1c1fb17d5aea9 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Fri, 9 May 2014 15:52:39 +0200 Subject: [PATCH 0700/4131] Add license and version comment to all scripts --- addon/comment/comment.js | 3 +++ addon/comment/continuecomment.js | 3 +++ addon/dialog/dialog.js | 3 +++ addon/display/fullscreen.js | 3 +++ addon/display/placeholder.js | 3 +++ addon/display/rulers.js | 3 +++ addon/edit/closebrackets.js | 3 +++ addon/edit/closetag.js | 3 +++ addon/edit/continuelist.js | 3 +++ addon/edit/matchbrackets.js | 3 +++ addon/edit/matchtags.js | 3 +++ addon/edit/trailingspace.js | 3 +++ addon/fold/brace-fold.js | 3 +++ addon/fold/comment-fold.js | 3 +++ addon/fold/foldcode.js | 3 +++ addon/fold/foldgutter.js | 3 +++ addon/fold/indent-fold.js | 3 +++ addon/fold/markdown-fold.js | 3 +++ addon/fold/xml-fold.js | 3 +++ addon/hint/anyword-hint.js | 3 +++ addon/hint/css-hint.js | 3 +++ addon/hint/html-hint.js | 3 +++ addon/hint/javascript-hint.js | 3 +++ addon/hint/python-hint.js | 3 +++ addon/hint/show-hint.js | 3 +++ addon/hint/sql-hint.js | 3 +++ addon/hint/xml-hint.js | 3 +++ addon/lint/coffeescript-lint.js | 3 +++ addon/lint/css-lint.js | 3 +++ addon/lint/javascript-lint.js | 3 +++ addon/lint/json-lint.js | 3 +++ addon/lint/lint.js | 3 +++ addon/lint/yaml-lint.js | 3 +++ addon/merge/merge.js | 3 +++ addon/mode/loadmode.js | 3 +++ addon/mode/multiplex.js | 3 +++ addon/mode/multiplex_test.js | 3 +++ addon/mode/overlay.js | 3 +++ addon/runmode/colorize.js | 3 +++ addon/runmode/runmode-standalone.js | 3 +++ addon/runmode/runmode.js | 3 +++ addon/runmode/runmode.node.js | 3 +++ addon/scroll/scrollpastend.js | 3 +++ addon/search/match-highlighter.js | 3 +++ addon/search/search.js | 3 +++ addon/search/searchcursor.js | 3 +++ addon/selection/active-line.js | 3 +++ addon/selection/mark-selection.js | 3 +++ addon/tern/tern.js | 3 +++ addon/tern/worker.js | 3 +++ addon/wrap/hardwrap.js | 3 +++ bin/release | 15 +++++++++++++++ keymap/emacs.js | 3 +++ keymap/sublime.js | 3 +++ keymap/vim.js | 3 +++ lib/codemirror.js | 3 +++ mode/apl/apl.js | 3 +++ mode/asterisk/asterisk.js | 3 +++ mode/clike/clike.js | 3 +++ mode/clojure/clojure.js | 3 +++ mode/cobol/cobol.js | 3 +++ mode/coffeescript/coffeescript.js | 3 +++ mode/commonlisp/commonlisp.js | 3 +++ mode/css/css.js | 3 +++ mode/css/less_test.js | 3 +++ mode/css/scss_test.js | 3 +++ mode/css/test.js | 3 +++ mode/cypher/cypher.js | 3 +++ mode/d/d.js | 3 +++ mode/diff/diff.js | 3 +++ mode/django/django.js | 3 +++ mode/dtd/dtd.js | 3 +++ mode/dylan/dylan.js | 3 +++ mode/ecl/ecl.js | 3 +++ mode/eiffel/eiffel.js | 3 +++ mode/erlang/erlang.js | 3 +++ mode/fortran/fortran.js | 3 +++ mode/gas/gas.js | 3 +++ mode/gfm/gfm.js | 3 +++ mode/gfm/test.js | 3 +++ mode/gherkin/gherkin.js | 3 +++ mode/go/go.js | 3 +++ mode/groovy/groovy.js | 3 +++ mode/haml/haml.js | 3 +++ mode/haml/test.js | 3 +++ mode/haskell/haskell.js | 3 +++ mode/haxe/haxe.js | 3 +++ mode/htmlembedded/htmlembedded.js | 3 +++ mode/htmlmixed/htmlmixed.js | 3 +++ mode/http/http.js | 3 +++ mode/jade/jade.js | 3 +++ mode/javascript/javascript.js | 3 +++ mode/javascript/test.js | 3 +++ mode/jinja2/jinja2.js | 3 +++ mode/julia/julia.js | 3 +++ mode/livescript/livescript.js | 3 +++ mode/lua/lua.js | 3 +++ mode/markdown/markdown.js | 3 +++ mode/markdown/test.js | 3 +++ mode/meta.js | 3 +++ mode/mirc/mirc.js | 3 +++ mode/mllike/mllike.js | 3 +++ mode/nginx/nginx.js | 3 +++ mode/ntriples/ntriples.js | 3 +++ mode/octave/octave.js | 3 +++ mode/pascal/pascal.js | 3 +++ mode/pegjs/pegjs.js | 3 +++ mode/perl/perl.js | 3 +++ mode/php/php.js | 3 +++ mode/php/test.js | 3 +++ mode/pig/pig.js | 3 +++ mode/properties/properties.js | 3 +++ mode/puppet/puppet.js | 3 +++ mode/python/python.js | 3 +++ mode/q/q.js | 3 +++ mode/r/r.js | 3 +++ mode/rpm/rpm.js | 3 +++ mode/rst/rst.js | 3 +++ mode/ruby/ruby.js | 3 +++ mode/ruby/test.js | 3 +++ mode/rust/rust.js | 3 +++ mode/sass/sass.js | 3 +++ mode/scheme/scheme.js | 3 +++ mode/shell/shell.js | 3 +++ mode/shell/test.js | 3 +++ mode/sieve/sieve.js | 3 +++ mode/smalltalk/smalltalk.js | 3 +++ mode/smarty/smarty.js | 3 +++ mode/smartymixed/smartymixed.js | 3 +++ mode/solr/solr.js | 3 +++ mode/sparql/sparql.js | 3 +++ mode/sql/sql.js | 3 +++ mode/stex/stex.js | 3 +++ mode/stex/test.js | 3 +++ mode/tcl/tcl.js | 3 +++ mode/tiddlywiki/tiddlywiki.js | 3 +++ mode/tiki/tiki.js | 3 +++ mode/toml/toml.js | 3 +++ mode/turtle/turtle.js | 3 +++ mode/vb/vb.js | 3 +++ mode/vbscript/vbscript.js | 3 +++ mode/velocity/velocity.js | 3 +++ mode/verilog/test.js | 3 +++ mode/verilog/verilog.js | 3 +++ mode/xml/test.js | 3 +++ mode/xml/xml.js | 3 +++ mode/xquery/test.js | 3 +++ mode/xquery/xquery.js | 3 +++ mode/yaml/yaml.js | 3 +++ mode/z80/z80.js | 3 +++ test/lint/lint.js | 7 ++++++- 151 files changed, 468 insertions(+), 1 deletion(-) diff --git a/addon/comment/comment.js b/addon/comment/comment.js index 1eb9a05c5d..f56721206e 100644 --- a/addon/comment/comment.js +++ b/addon/comment/comment.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, 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")); diff --git a/addon/comment/continuecomment.js b/addon/comment/continuecomment.js index 42277267f5..5247a845c4 100644 --- a/addon/comment/continuecomment.js +++ b/addon/comment/continuecomment.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, 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")); diff --git a/addon/dialog/dialog.js b/addon/dialog/dialog.js index 586b7370dc..8fbdea168d 100644 --- a/addon/dialog/dialog.js +++ b/addon/dialog/dialog.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, copyright (c) by Marijn Haverbeke and others +// Distributed under an MIT license: http://codemirror.net/LICENSE + // Open simple dialogs on top of an editor. Relies on dialog.css. (function(mod) { diff --git a/addon/display/fullscreen.js b/addon/display/fullscreen.js index e39c6e162f..e7f22a7936 100644 --- a/addon/display/fullscreen.js +++ b/addon/display/fullscreen.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, 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")); diff --git a/addon/display/placeholder.js b/addon/display/placeholder.js index 0fdc9b0d5b..fbc0a8bdf0 100644 --- a/addon/display/placeholder.js +++ b/addon/display/placeholder.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, 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")); diff --git a/addon/display/rulers.js b/addon/display/rulers.js index 42cc2b9a90..e025415b51 100644 --- a/addon/display/rulers.js +++ b/addon/display/rulers.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, 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")); diff --git a/addon/edit/closebrackets.js b/addon/edit/closebrackets.js index 3cea887d1d..4caac60b98 100644 --- a/addon/edit/closebrackets.js +++ b/addon/edit/closebrackets.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, 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")); diff --git a/addon/edit/closetag.js b/addon/edit/closetag.js index c7c0701ba5..d64045ab1b 100644 --- a/addon/edit/closetag.js +++ b/addon/edit/closetag.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, copyright (c) by Marijn Haverbeke and others +// Distributed under an MIT license: http://codemirror.net/LICENSE + /** * Tag-closer extension for CodeMirror. * diff --git a/addon/edit/continuelist.js b/addon/edit/continuelist.js index 2946aa6a24..3dcf757397 100644 --- a/addon/edit/continuelist.js +++ b/addon/edit/continuelist.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, 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")); diff --git a/addon/edit/matchbrackets.js b/addon/edit/matchbrackets.js index dcdde81dfe..c1221ca4c0 100644 --- a/addon/edit/matchbrackets.js +++ b/addon/edit/matchbrackets.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, 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")); diff --git a/addon/edit/matchtags.js b/addon/edit/matchtags.js index 76a7b87c9a..a91d578365 100644 --- a/addon/edit/matchtags.js +++ b/addon/edit/matchtags.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, 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"), require("../fold/xml-fold")); diff --git a/addon/edit/trailingspace.js b/addon/edit/trailingspace.js index ec07221e30..e12162d33c 100644 --- a/addon/edit/trailingspace.js +++ b/addon/edit/trailingspace.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, 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")); diff --git a/addon/fold/brace-fold.js b/addon/fold/brace-fold.js index f0ee62029a..a0161e2c19 100644 --- a/addon/fold/brace-fold.js +++ b/addon/fold/brace-fold.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, 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")); diff --git a/addon/fold/comment-fold.js b/addon/fold/comment-fold.js index d72c5479a7..593539affd 100644 --- a/addon/fold/comment-fold.js +++ b/addon/fold/comment-fold.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, 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")); diff --git a/addon/fold/foldcode.js b/addon/fold/foldcode.js index 81094e2543..51cc3939b3 100644 --- a/addon/fold/foldcode.js +++ b/addon/fold/foldcode.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, 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")); diff --git a/addon/fold/foldgutter.js b/addon/fold/foldgutter.js index 9caba59aad..04ce8493e8 100644 --- a/addon/fold/foldgutter.js +++ b/addon/fold/foldgutter.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, 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"), require("./foldcode")); diff --git a/addon/fold/indent-fold.js b/addon/fold/indent-fold.js index d0130836a2..126ed4953c 100644 --- a/addon/fold/indent-fold.js +++ b/addon/fold/indent-fold.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, 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")); diff --git a/addon/fold/markdown-fold.js b/addon/fold/markdown-fold.js index 3bbf5b6077..ecee9e7e27 100644 --- a/addon/fold/markdown-fold.js +++ b/addon/fold/markdown-fold.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, 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")); diff --git a/addon/fold/xml-fold.js b/addon/fold/xml-fold.js index d554e2fc42..e1fd5756d8 100644 --- a/addon/fold/xml-fold.js +++ b/addon/fold/xml-fold.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, 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")); diff --git a/addon/hint/anyword-hint.js b/addon/hint/anyword-hint.js index 3ef979b524..0b6d872f3d 100644 --- a/addon/hint/anyword-hint.js +++ b/addon/hint/anyword-hint.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, 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")); diff --git a/addon/hint/css-hint.js b/addon/hint/css-hint.js index 96d9d52e1b..a93458819c 100644 --- a/addon/hint/css-hint.js +++ b/addon/hint/css-hint.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, 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"), require("../../mode/css/css")); diff --git a/addon/hint/html-hint.js b/addon/hint/html-hint.js index cbe7c61ad4..cfdcff9de2 100755 --- a/addon/hint/html-hint.js +++ b/addon/hint/html-hint.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, 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")); diff --git a/addon/hint/javascript-hint.js b/addon/hint/javascript-hint.js index baf20b45dc..29f3960902 100644 --- a/addon/hint/javascript-hint.js +++ b/addon/hint/javascript-hint.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, 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")); diff --git a/addon/hint/python-hint.js b/addon/hint/python-hint.js index eebfcc76dc..49dfb08f3a 100644 --- a/addon/hint/python-hint.js +++ b/addon/hint/python-hint.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, 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")); diff --git a/addon/hint/show-hint.js b/addon/hint/show-hint.js index 46b55648cb..4bede1fb03 100644 --- a/addon/hint/show-hint.js +++ b/addon/hint/show-hint.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, 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")); diff --git a/addon/hint/sql-hint.js b/addon/hint/sql-hint.js index a48d2b3cea..e527a878b9 100644 --- a/addon/hint/sql-hint.js +++ b/addon/hint/sql-hint.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, 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"), require("../../mode/sql/sql")); diff --git a/addon/hint/xml-hint.js b/addon/hint/xml-hint.js index 9cfd1e884f..de9f79eb3b 100644 --- a/addon/hint/xml-hint.js +++ b/addon/hint/xml-hint.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, 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")); diff --git a/addon/lint/coffeescript-lint.js b/addon/lint/coffeescript-lint.js index 6df17f8f84..2cc6314f06 100644 --- a/addon/lint/coffeescript-lint.js +++ b/addon/lint/coffeescript-lint.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, copyright (c) by Marijn Haverbeke and others +// Distributed under an MIT license: http://codemirror.net/LICENSE + // Depends on coffeelint.js from http://www.coffeelint.org/js/coffeelint.js // declare global: coffeelint diff --git a/addon/lint/css-lint.js b/addon/lint/css-lint.js index de9cd20d7a..93f2e5f5d8 100644 --- a/addon/lint/css-lint.js +++ b/addon/lint/css-lint.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, copyright (c) by Marijn Haverbeke and others +// Distributed under an MIT license: http://codemirror.net/LICENSE + // Depends on csslint.js from https://github.com/stubbornella/csslint // declare global: CSSLint diff --git a/addon/lint/javascript-lint.js b/addon/lint/javascript-lint.js index 86c863a4a2..ed62dd989c 100644 --- a/addon/lint/javascript-lint.js +++ b/addon/lint/javascript-lint.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, 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")); diff --git a/addon/lint/json-lint.js b/addon/lint/json-lint.js index 1f5f82d0ca..b548a8e439 100644 --- a/addon/lint/json-lint.js +++ b/addon/lint/json-lint.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, copyright (c) by Marijn Haverbeke and others +// Distributed under an MIT license: http://codemirror.net/LICENSE + // Depends on jsonlint.js from https://github.com/zaach/jsonlint // declare global: jsonlint diff --git a/addon/lint/lint.js b/addon/lint/lint.js index 393a689036..1682acf6ea 100644 --- a/addon/lint/lint.js +++ b/addon/lint/lint.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, 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")); diff --git a/addon/lint/yaml-lint.js b/addon/lint/yaml-lint.js index b53673af4b..3ada0eaf9f 100644 --- a/addon/lint/yaml-lint.js +++ b/addon/lint/yaml-lint.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, 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")); diff --git a/addon/merge/merge.js b/addon/merge/merge.js index fe3fcf4282..61e25e5d36 100644 --- a/addon/merge/merge.js +++ b/addon/merge/merge.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, 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")); diff --git a/addon/mode/loadmode.js b/addon/mode/loadmode.js index e08c281321..e49421b8fc 100644 --- a/addon/mode/loadmode.js +++ b/addon/mode/loadmode.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, 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")); diff --git a/addon/mode/multiplex.js b/addon/mode/multiplex.js index 07385c35f2..40601f4dfa 100644 --- a/addon/mode/multiplex.js +++ b/addon/mode/multiplex.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, 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")); diff --git a/addon/mode/multiplex_test.js b/addon/mode/multiplex_test.js index c0656357c7..a10012ce8c 100644 --- a/addon/mode/multiplex_test.js +++ b/addon/mode/multiplex_test.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, copyright (c) by Marijn Haverbeke and others +// Distributed under an MIT license: http://codemirror.net/LICENSE + (function() { CodeMirror.defineMode("markdown_with_stex", function(){ var inner = CodeMirror.getMode({}, "stex"); diff --git a/addon/mode/overlay.js b/addon/mode/overlay.js index e32fa830b3..82f754c461 100644 --- a/addon/mode/overlay.js +++ b/addon/mode/overlay.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, copyright (c) by Marijn Haverbeke and others +// Distributed under an MIT license: http://codemirror.net/LICENSE + // Utility function that allows modes to be combined. The mode given // as the base argument takes care of most of the normal mode // functionality, but a second (typically simple) mode is used, which diff --git a/addon/runmode/colorize.js b/addon/runmode/colorize.js index 0f9530b17b..eb99f29945 100644 --- a/addon/runmode/colorize.js +++ b/addon/runmode/colorize.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, 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"), require("./runmode")); diff --git a/addon/runmode/runmode-standalone.js b/addon/runmode/runmode-standalone.js index e36e00fbc6..3e1e746e95 100644 --- a/addon/runmode/runmode-standalone.js +++ b/addon/runmode/runmode-standalone.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, copyright (c) by Marijn Haverbeke and others +// Distributed under an MIT license: http://codemirror.net/LICENSE + window.CodeMirror = {}; (function() { diff --git a/addon/runmode/runmode.js b/addon/runmode/runmode.js index 5592a99a60..5406ff72fd 100644 --- a/addon/runmode/runmode.js +++ b/addon/runmode/runmode.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, 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")); diff --git a/addon/runmode/runmode.node.js b/addon/runmode/runmode.node.js index 15bf392313..f8c467f381 100644 --- a/addon/runmode/runmode.node.js +++ b/addon/runmode/runmode.node.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, copyright (c) by Marijn Haverbeke and others +// Distributed under an MIT license: http://codemirror.net/LICENSE + /* Just enough of CodeMirror to run runMode under node.js */ // declare global: StringStream diff --git a/addon/scroll/scrollpastend.js b/addon/scroll/scrollpastend.js index 467b7aa1cf..e9f4ecb68a 100644 --- a/addon/scroll/scrollpastend.js +++ b/addon/scroll/scrollpastend.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, 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")); diff --git a/addon/search/match-highlighter.js b/addon/search/match-highlighter.js index 83ab8c33c7..0dc28c10ba 100644 --- a/addon/search/match-highlighter.js +++ b/addon/search/match-highlighter.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, copyright (c) by Marijn Haverbeke and others +// Distributed under an MIT license: http://codemirror.net/LICENSE + // Highlighting text that matches the selection // // Defines an option highlightSelectionMatches, which, when enabled, diff --git a/addon/search/search.js b/addon/search/search.js index 7a1db6ee09..7bc3414c7b 100644 --- a/addon/search/search.js +++ b/addon/search/search.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, copyright (c) by Marijn Haverbeke and others +// Distributed under an MIT license: http://codemirror.net/LICENSE + // Define search commands. Depends on dialog.js or another // implementation of the openDialog method. diff --git a/addon/search/searchcursor.js b/addon/search/searchcursor.js index 899f44c4ab..f6df00a94e 100644 --- a/addon/search/searchcursor.js +++ b/addon/search/searchcursor.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, 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")); diff --git a/addon/selection/active-line.js b/addon/selection/active-line.js index a818f109b6..bafcb6b8c3 100644 --- a/addon/selection/active-line.js +++ b/addon/selection/active-line.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, copyright (c) by Marijn Haverbeke and others +// Distributed under an MIT license: http://codemirror.net/LICENSE + // Because sometimes you need to style the cursor's line. // // Adds an option 'styleActiveLine' which, when enabled, gives the diff --git a/addon/selection/mark-selection.js b/addon/selection/mark-selection.js index ae0d393143..f621c0704a 100644 --- a/addon/selection/mark-selection.js +++ b/addon/selection/mark-selection.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, copyright (c) by Marijn Haverbeke and others +// Distributed under an MIT license: http://codemirror.net/LICENSE + // Because sometimes you need to mark the selected *text*. // // Adds an option 'styleSelectedText' which, when enabled, gives diff --git a/addon/tern/tern.js b/addon/tern/tern.js index 2f450ed024..318f1484d9 100644 --- a/addon/tern/tern.js +++ b/addon/tern/tern.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, copyright (c) by Marijn Haverbeke and others +// Distributed under an MIT license: http://codemirror.net/LICENSE + // Glue code between CodeMirror and Tern. // // Create a CodeMirror.TernServer to wrap an actual Tern server, diff --git a/addon/tern/worker.js b/addon/tern/worker.js index 1ff63de411..615ce61e6a 100644 --- a/addon/tern/worker.js +++ b/addon/tern/worker.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, copyright (c) by Marijn Haverbeke and others +// Distributed under an MIT license: http://codemirror.net/LICENSE + // declare global: tern, server var server; diff --git a/addon/wrap/hardwrap.js b/addon/wrap/hardwrap.js index 87aab1b8f6..fb0b5f2fcf 100644 --- a/addon/wrap/hardwrap.js +++ b/addon/wrap/hardwrap.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, 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")); diff --git a/bin/release b/bin/release index 3c33290f3f..91451faae5 100755 --- a/bin/release +++ b/bin/release @@ -27,6 +27,21 @@ rewrite("doc/manual.html", function(manual) { return manual.replace(/>version \d+\.\d+\.\d+<\/span>/, ">version " + number + ""); }); +function walkDir(dir) { + fs.readdirSync(dir).forEach(function(file) { + var fname = dir + "/" + file; + if (/\.js$/.test(file)) rewrite(file, function(script) { + return script.replace(/^\/\/ CodeMirror \d+\.\d+\.\d+, copyright/, + "// CodeMirror " + number + ", copyright"); + }); + else if (fs.lstatSync(fname).isDirectory()) walkDir(fname); + }); +} +walkDir("mode"); +walkDir("lib"); +walkDir("addon"); +walkDir("keymap"); + if (bumpOnly) process.exit(0); child.exec("bash bin/authors.sh", function(){}); diff --git a/keymap/emacs.js b/keymap/emacs.js index 7cecf1f627..b1b70254d8 100644 --- a/keymap/emacs.js +++ b/keymap/emacs.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, 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")); diff --git a/keymap/sublime.js b/keymap/sublime.js index 9158e27944..0681fa3e2b 100644 --- a/keymap/sublime.js +++ b/keymap/sublime.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, copyright (c) by Marijn Haverbeke and others +// Distributed under an MIT license: http://codemirror.net/LICENSE + // A rough approximation of Sublime Text's keybindings // Depends on addon/search/searchcursor.js and optionally addon/dialog/dialogs.js diff --git a/keymap/vim.js b/keymap/vim.js index e33d269089..9dce29e253 100644 --- a/keymap/vim.js +++ b/keymap/vim.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, copyright (c) by Marijn Haverbeke and others +// Distributed under an MIT license: http://codemirror.net/LICENSE + /** * Supported keybindings: * diff --git a/lib/codemirror.js b/lib/codemirror.js index 0bf6f2d8e8..50bccb38a9 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, copyright (c) by Marijn Haverbeke and others +// Distributed under an MIT license: http://codemirror.net/LICENSE + // This is CodeMirror (http://codemirror.net), a code editor // implemented in JavaScript on top of the browser's DOM. // diff --git a/mode/apl/apl.js b/mode/apl/apl.js index 2ba74c18c2..0a318dad61 100644 --- a/mode/apl/apl.js +++ b/mode/apl/apl.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, 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")); diff --git a/mode/asterisk/asterisk.js b/mode/asterisk/asterisk.js index c56fc0b38a..f34471d4eb 100644 --- a/mode/asterisk/asterisk.js +++ b/mode/asterisk/asterisk.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, copyright (c) by Marijn Haverbeke and others +// Distributed under an MIT license: http://codemirror.net/LICENSE + /* * ===================================================================================== * diff --git a/mode/clike/clike.js b/mode/clike/clike.js index 60b88bf1aa..a114344f87 100644 --- a/mode/clike/clike.js +++ b/mode/clike/clike.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, 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")); diff --git a/mode/clojure/clojure.js b/mode/clojure/clojure.js index 3b596ad607..f8e8879d42 100644 --- a/mode/clojure/clojure.js +++ b/mode/clojure/clojure.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, copyright (c) by Marijn Haverbeke and others +// Distributed under an MIT license: http://codemirror.net/LICENSE + /** * Author: Hans Engel * Branched from CodeMirror's Scheme mode (by Koh Zi Han, based on implementation by Koh Zi Chun) diff --git a/mode/cobol/cobol.js b/mode/cobol/cobol.js index e66e42a191..231218509a 100644 --- a/mode/cobol/cobol.js +++ b/mode/cobol/cobol.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, copyright (c) by Marijn Haverbeke and others +// Distributed under an MIT license: http://codemirror.net/LICENSE + /** * Author: Gautam Mehta * Branched from CodeMirror's Scheme mode diff --git a/mode/coffeescript/coffeescript.js b/mode/coffeescript/coffeescript.js index c6da8f2a29..5350f6099c 100644 --- a/mode/coffeescript/coffeescript.js +++ b/mode/coffeescript/coffeescript.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, copyright (c) by Marijn Haverbeke and others +// Distributed under an MIT license: http://codemirror.net/LICENSE + /** * Link to the project's GitHub page: * https://github.com/pickhardt/coffeescript-codemirror-mode diff --git a/mode/commonlisp/commonlisp.js b/mode/commonlisp/commonlisp.js index a0f0732bf6..ffb3c96493 100644 --- a/mode/commonlisp/commonlisp.js +++ b/mode/commonlisp/commonlisp.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, 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")); diff --git a/mode/css/css.js b/mode/css/css.js index 8828329fc4..6b49e473f0 100644 --- a/mode/css/css.js +++ b/mode/css/css.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, 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")); diff --git a/mode/css/less_test.js b/mode/css/less_test.js index ea64f91d12..a569e107dd 100644 --- a/mode/css/less_test.js +++ b/mode/css/less_test.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, copyright (c) by Marijn Haverbeke and others +// Distributed under an MIT license: http://codemirror.net/LICENSE + (function() { "use strict"; diff --git a/mode/css/scss_test.js b/mode/css/scss_test.js index c51cb42bba..85077532dc 100644 --- a/mode/css/scss_test.js +++ b/mode/css/scss_test.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, copyright (c) by Marijn Haverbeke and others +// Distributed under an MIT license: http://codemirror.net/LICENSE + (function() { var mode = CodeMirror.getMode({indentUnit: 2}, "text/x-scss"); function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1), "scss"); } diff --git a/mode/css/test.js b/mode/css/test.js index f9f667295c..85f597b570 100644 --- a/mode/css/test.js +++ b/mode/css/test.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, copyright (c) by Marijn Haverbeke and others +// Distributed under an MIT license: http://codemirror.net/LICENSE + (function() { var mode = CodeMirror.getMode({indentUnit: 2}, "css"); function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); } diff --git a/mode/cypher/cypher.js b/mode/cypher/cypher.js index f102c9ec1a..902430c2b0 100644 --- a/mode/cypher/cypher.js +++ b/mode/cypher/cypher.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, copyright (c) by Marijn Haverbeke and others +// Distributed under an MIT license: http://codemirror.net/LICENSE + // By the Neo4j Team and contributors. // https://github.com/neo4j-contrib/CodeMirror diff --git a/mode/d/d.js b/mode/d/d.js index 3ab8b42838..cb9a674cec 100644 --- a/mode/d/d.js +++ b/mode/d/d.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, 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")); diff --git a/mode/diff/diff.js b/mode/diff/diff.js index d43f15d51a..ad62f2fcef 100644 --- a/mode/diff/diff.js +++ b/mode/diff/diff.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, 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")); diff --git a/mode/django/django.js b/mode/django/django.js index 38de7d5ee3..3fe57cdea3 100644 --- a/mode/django/django.js +++ b/mode/django/django.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, 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"), require("../htmlmixed/htmlmixed"), diff --git a/mode/dtd/dtd.js b/mode/dtd/dtd.js index b4a6cb3155..7c3b6a1cab 100644 --- a/mode/dtd/dtd.js +++ b/mode/dtd/dtd.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, copyright (c) by Marijn Haverbeke and others +// Distributed under an MIT license: http://codemirror.net/LICENSE + /* DTD mode Ported to CodeMirror by Peter Kroon diff --git a/mode/dylan/dylan.js b/mode/dylan/dylan.js index ccf9679181..b4526f6fad 100644 --- a/mode/dylan/dylan.js +++ b/mode/dylan/dylan.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, 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")); diff --git a/mode/ecl/ecl.js b/mode/ecl/ecl.js index 2b841ff5f1..18d60899e0 100644 --- a/mode/ecl/ecl.js +++ b/mode/ecl/ecl.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, 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")); diff --git a/mode/eiffel/eiffel.js b/mode/eiffel/eiffel.js index c6c3c84600..52c54e7863 100644 --- a/mode/eiffel/eiffel.js +++ b/mode/eiffel/eiffel.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, 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")); diff --git a/mode/erlang/erlang.js b/mode/erlang/erlang.js index 3d4b1ba92e..7e2a1d4ad3 100644 --- a/mode/erlang/erlang.js +++ b/mode/erlang/erlang.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, copyright (c) by Marijn Haverbeke and others +// Distributed under an MIT license: http://codemirror.net/LICENSE + /*jshint unused:true, eqnull:true, curly:true, bitwise:true */ /*jshint undef:true, latedef:true, trailing:true */ /*global CodeMirror:true */ diff --git a/mode/fortran/fortran.js b/mode/fortran/fortran.js index 58dac127c1..66b9c9ad70 100644 --- a/mode/fortran/fortran.js +++ b/mode/fortran/fortran.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, 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")); diff --git a/mode/gas/gas.js b/mode/gas/gas.js index ba5f195a11..6bf66b6f49 100644 --- a/mode/gas/gas.js +++ b/mode/gas/gas.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, 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")); diff --git a/mode/gfm/gfm.js b/mode/gfm/gfm.js index 5a028c48b4..5de044807d 100644 --- a/mode/gfm/gfm.js +++ b/mode/gfm/gfm.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, 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"), require("../markdown/markdown"), require("../../addon/mode/overlay")); diff --git a/mode/gfm/test.js b/mode/gfm/test.js index d06a219240..f3d72bfadf 100644 --- a/mode/gfm/test.js +++ b/mode/gfm/test.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, copyright (c) by Marijn Haverbeke and others +// Distributed under an MIT license: http://codemirror.net/LICENSE + (function() { var mode = CodeMirror.getMode({tabSize: 4}, "gfm"); function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); } diff --git a/mode/gherkin/gherkin.js b/mode/gherkin/gherkin.js index 41003641ec..c94efcb6aa 100644 --- a/mode/gherkin/gherkin.js +++ b/mode/gherkin/gherkin.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, copyright (c) by Marijn Haverbeke and others +// Distributed under an MIT license: http://codemirror.net/LICENSE + /* Gherkin mode - http://www.cukes.info/ Report bugs/issues here: https://github.com/marijnh/CodeMirror/issues diff --git a/mode/go/go.js b/mode/go/go.js index 82463052f6..46e13b6c54 100644 --- a/mode/go/go.js +++ b/mode/go/go.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, 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")); diff --git a/mode/groovy/groovy.js b/mode/groovy/groovy.js index 399452d536..4a867d8337 100644 --- a/mode/groovy/groovy.js +++ b/mode/groovy/groovy.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, 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")); diff --git a/mode/haml/haml.js b/mode/haml/haml.js index 59a86e7cec..1ab5001fc2 100644 --- a/mode/haml/haml.js +++ b/mode/haml/haml.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, 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"), require("../htmlmixed/htmlmixed"), require("../ruby/ruby")); diff --git a/mode/haml/test.js b/mode/haml/test.js index 75d0e7710f..0a8fc55696 100644 --- a/mode/haml/test.js +++ b/mode/haml/test.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, copyright (c) by Marijn Haverbeke and others +// Distributed under an MIT license: http://codemirror.net/LICENSE + (function() { var mode = CodeMirror.getMode({tabSize: 4, indentUnit: 2}, "haml"); function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); } diff --git a/mode/haskell/haskell.js b/mode/haskell/haskell.js index 2876172a95..4d923568d0 100644 --- a/mode/haskell/haskell.js +++ b/mode/haskell/haskell.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, 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")); diff --git a/mode/haxe/haxe.js b/mode/haxe/haxe.js index ffde5991ad..487a88ddf3 100644 --- a/mode/haxe/haxe.js +++ b/mode/haxe/haxe.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, 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")); diff --git a/mode/htmlembedded/htmlembedded.js b/mode/htmlembedded/htmlembedded.js index 3a07c3432e..7b3b9be725 100644 --- a/mode/htmlembedded/htmlembedded.js +++ b/mode/htmlembedded/htmlembedded.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, 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"), require("../htmlmixed/htmlmixed")); diff --git a/mode/htmlmixed/htmlmixed.js b/mode/htmlmixed/htmlmixed.js index d80ef9c64c..1dacbe8098 100644 --- a/mode/htmlmixed/htmlmixed.js +++ b/mode/htmlmixed/htmlmixed.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, 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"), require("../xml/xml"), require("../javascript/javascript"), require("../css/css")); diff --git a/mode/http/http.js b/mode/http/http.js index d2ad5994b6..bd0cb574d3 100644 --- a/mode/http/http.js +++ b/mode/http/http.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, 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")); diff --git a/mode/jade/jade.js b/mode/jade/jade.js index 64d4d2f4be..b7c99b083d 100644 --- a/mode/jade/jade.js +++ b/mode/jade/jade.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, 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"), require("../javascript/javascript"), require("../css/css"), require("../htmlmixed/htmlmixed")); diff --git a/mode/javascript/javascript.js b/mode/javascript/javascript.js index e719089349..71e8a09c6f 100644 --- a/mode/javascript/javascript.js +++ b/mode/javascript/javascript.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, copyright (c) by Marijn Haverbeke and others +// Distributed under an MIT license: http://codemirror.net/LICENSE + // TODO actually recognize syntax of TypeScript constructs (function(mod) { diff --git a/mode/javascript/test.js b/mode/javascript/test.js index 782f0457f9..4411a98452 100644 --- a/mode/javascript/test.js +++ b/mode/javascript/test.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, copyright (c) by Marijn Haverbeke and others +// Distributed under an MIT license: http://codemirror.net/LICENSE + (function() { var mode = CodeMirror.getMode({indentUnit: 2}, "javascript"); function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); } diff --git a/mode/jinja2/jinja2.js b/mode/jinja2/jinja2.js index 4b535e5322..e80c772929 100644 --- a/mode/jinja2/jinja2.js +++ b/mode/jinja2/jinja2.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, 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")); diff --git a/mode/julia/julia.js b/mode/julia/julia.js index d37ab503ed..79b47fb3ef 100644 --- a/mode/julia/julia.js +++ b/mode/julia/julia.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, 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")); diff --git a/mode/livescript/livescript.js b/mode/livescript/livescript.js index 1efc3ecf66..8e822bd6d3 100644 --- a/mode/livescript/livescript.js +++ b/mode/livescript/livescript.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, copyright (c) by Marijn Haverbeke and others +// Distributed under an MIT license: http://codemirror.net/LICENSE + /** * Link to the project's GitHub page: * https://github.com/duralog/CodeMirror diff --git a/mode/lua/lua.js b/mode/lua/lua.js index 3673557c27..6121b86b38 100644 --- a/mode/lua/lua.js +++ b/mode/lua/lua.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, copyright (c) by Marijn Haverbeke and others +// Distributed under an MIT license: http://codemirror.net/LICENSE + // LUA mode. Ported to CodeMirror 2 from Franciszek Wawrzak's // CodeMirror 1 mode. // highlights keywords, strings, comments (no leveling supported! ("[==[")), tokens, basic indenting diff --git a/mode/markdown/markdown.js b/mode/markdown/markdown.js index 84ea4d46b9..81472f02f7 100644 --- a/mode/markdown/markdown.js +++ b/mode/markdown/markdown.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, 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", require("../xml/xml"))); diff --git a/mode/markdown/test.js b/mode/markdown/test.js index 4d1d70ad14..ba1b15fc82 100644 --- a/mode/markdown/test.js +++ b/mode/markdown/test.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, copyright (c) by Marijn Haverbeke and others +// Distributed under an MIT license: http://codemirror.net/LICENSE + (function() { var mode = CodeMirror.getMode({tabSize: 4}, "markdown"); function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); } diff --git a/mode/meta.js b/mode/meta.js index 5fc51ebeec..5cccf7e9ab 100644 --- a/mode/meta.js +++ b/mode/meta.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, 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")); diff --git a/mode/mirc/mirc.js b/mode/mirc/mirc.js index 6b2a23a16c..321830baf7 100644 --- a/mode/mirc/mirc.js +++ b/mode/mirc/mirc.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, copyright (c) by Marijn Haverbeke and others +// Distributed under an MIT license: http://codemirror.net/LICENSE + //mIRC mode by Ford_Lawnmower :: Based on Velocity mode by Steve O'Hara (function(mod) { diff --git a/mode/mllike/mllike.js b/mode/mllike/mllike.js index d4d59fceb7..18771467a8 100644 --- a/mode/mllike/mllike.js +++ b/mode/mllike/mllike.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, 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")); diff --git a/mode/nginx/nginx.js b/mode/nginx/nginx.js index 4e17cdb3c4..22c266384d 100644 --- a/mode/nginx/nginx.js +++ b/mode/nginx/nginx.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, 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")); diff --git a/mode/ntriples/ntriples.js b/mode/ntriples/ntriples.js index cd5eb24f07..1f9ba451cb 100644 --- a/mode/ntriples/ntriples.js +++ b/mode/ntriples/ntriples.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, copyright (c) by Marijn Haverbeke and others +// Distributed under an MIT license: http://codemirror.net/LICENSE + /********************************************************** * This script provides syntax highlighting support for * the Ntriples format. diff --git a/mode/octave/octave.js b/mode/octave/octave.js index 16fe4dfd78..e5a50bce3b 100644 --- a/mode/octave/octave.js +++ b/mode/octave/octave.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, 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")); diff --git a/mode/pascal/pascal.js b/mode/pascal/pascal.js index 642dd9bf79..652addd2c2 100644 --- a/mode/pascal/pascal.js +++ b/mode/pascal/pascal.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, 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")); diff --git a/mode/pegjs/pegjs.js b/mode/pegjs/pegjs.js index f74f2a4f22..725579d5a0 100644 --- a/mode/pegjs/pegjs.js +++ b/mode/pegjs/pegjs.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, 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"), require("../javascript/javascript")); diff --git a/mode/perl/perl.js b/mode/perl/perl.js index 0126d3ea36..9b02783a1d 100644 --- a/mode/perl/perl.js +++ b/mode/perl/perl.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, copyright (c) by Marijn Haverbeke and others +// Distributed under an MIT license: http://codemirror.net/LICENSE + // CodeMirror2 mode/perl/perl.js (text/x-perl) beta 0.10 (2011-11-08) // This is a part of CodeMirror from https://github.com/sabaca/CodeMirror_mode_perl (mail@sabaca.com) diff --git a/mode/php/php.js b/mode/php/php.js index 81591e4d65..4185804791 100644 --- a/mode/php/php.js +++ b/mode/php/php.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, 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"), require("../htmlmixed/htmlmixed"), require("../clike/clike")); diff --git a/mode/php/test.js b/mode/php/test.js index db68d75de3..2d901cf08d 100644 --- a/mode/php/test.js +++ b/mode/php/test.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, copyright (c) by Marijn Haverbeke and others +// Distributed under an MIT license: http://codemirror.net/LICENSE + (function() { var mode = CodeMirror.getMode({indentUnit: 2}, "php"); function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); } diff --git a/mode/pig/pig.js b/mode/pig/pig.js index 64ac506a79..52ad349c41 100644 --- a/mode/pig/pig.js +++ b/mode/pig/pig.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, copyright (c) by Marijn Haverbeke and others +// Distributed under an MIT license: http://codemirror.net/LICENSE + /* * Pig Latin Mode for CodeMirror 2 * @author Prasanth Jayachandran diff --git a/mode/properties/properties.js b/mode/properties/properties.js index 6dfe06f128..b91191a7b5 100644 --- a/mode/properties/properties.js +++ b/mode/properties/properties.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, 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")); diff --git a/mode/puppet/puppet.js b/mode/puppet/puppet.js index da8823e5ed..bba431eb3d 100644 --- a/mode/puppet/puppet.js +++ b/mode/puppet/puppet.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, 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")); diff --git a/mode/python/python.js b/mode/python/python.js index 4fc4354ff7..1fb32a7c16 100644 --- a/mode/python/python.js +++ b/mode/python/python.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, 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")); diff --git a/mode/q/q.js b/mode/q/q.js index d6e3b66610..ff788d9d52 100644 --- a/mode/q/q.js +++ b/mode/q/q.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, 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")); diff --git a/mode/r/r.js b/mode/r/r.js index 281d7fa40f..d04eca3899 100644 --- a/mode/r/r.js +++ b/mode/r/r.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, 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")); diff --git a/mode/rpm/rpm.js b/mode/rpm/rpm.js index 497997c4ff..bad1b3e024 100644 --- a/mode/rpm/rpm.js +++ b/mode/rpm/rpm.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, 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")); diff --git a/mode/rst/rst.js b/mode/rst/rst.js index 0763d4b999..11c3678428 100644 --- a/mode/rst/rst.js +++ b/mode/rst/rst.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, 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"), require("../python/python"), require("../stex/stex"), require("../../addon/mode/overlay")); diff --git a/mode/ruby/ruby.js b/mode/ruby/ruby.js index 4ef08b1552..8ffd2d7e8a 100644 --- a/mode/ruby/ruby.js +++ b/mode/ruby/ruby.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, 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")); diff --git a/mode/ruby/test.js b/mode/ruby/test.js index c97d106686..1a6067d027 100644 --- a/mode/ruby/test.js +++ b/mode/ruby/test.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, copyright (c) by Marijn Haverbeke and others +// Distributed under an MIT license: http://codemirror.net/LICENSE + (function() { var mode = CodeMirror.getMode({indentUnit: 2}, "ruby"); function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); } diff --git a/mode/rust/rust.js b/mode/rust/rust.js index 2e6e20b231..e7abed3520 100644 --- a/mode/rust/rust.js +++ b/mode/rust/rust.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, 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")); diff --git a/mode/sass/sass.js b/mode/sass/sass.js index 74ae91db12..8cdb1365f9 100644 --- a/mode/sass/sass.js +++ b/mode/sass/sass.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, 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")); diff --git a/mode/scheme/scheme.js b/mode/scheme/scheme.js index 7124f7283b..97979057ef 100644 --- a/mode/scheme/scheme.js +++ b/mode/scheme/scheme.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, copyright (c) by Marijn Haverbeke and others +// Distributed under an MIT license: http://codemirror.net/LICENSE + /** * Author: Koh Zi Han, based on implementation by Koh Zi Chun */ diff --git a/mode/shell/shell.js b/mode/shell/shell.js index 5abb44711f..c1893a4dd1 100644 --- a/mode/shell/shell.js +++ b/mode/shell/shell.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, 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")); diff --git a/mode/shell/test.js b/mode/shell/test.js index 3ab045c087..8bdb82103d 100644 --- a/mode/shell/test.js +++ b/mode/shell/test.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, copyright (c) by Marijn Haverbeke and others +// Distributed under an MIT license: http://codemirror.net/LICENSE + (function() { var mode = CodeMirror.getMode({}, "shell"); function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); } diff --git a/mode/sieve/sieve.js b/mode/sieve/sieve.js index 8256dda0a4..d74c839e01 100644 --- a/mode/sieve/sieve.js +++ b/mode/sieve/sieve.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, 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")); diff --git a/mode/smalltalk/smalltalk.js b/mode/smalltalk/smalltalk.js index deb78a4f7a..42fdc67830 100644 --- a/mode/smalltalk/smalltalk.js +++ b/mode/smalltalk/smalltalk.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, 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")); diff --git a/mode/smarty/smarty.js b/mode/smarty/smarty.js index 2a78c6d394..8c4bd13b61 100644 --- a/mode/smarty/smarty.js +++ b/mode/smarty/smarty.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, copyright (c) by Marijn Haverbeke and others +// Distributed under an MIT license: http://codemirror.net/LICENSE + /** * Smarty 2 and 3 mode. */ diff --git a/mode/smartymixed/smartymixed.js b/mode/smartymixed/smartymixed.js index 7e5e12c0ec..3be014b872 100644 --- a/mode/smartymixed/smartymixed.js +++ b/mode/smartymixed/smartymixed.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, copyright (c) by Marijn Haverbeke and others +// Distributed under an MIT license: http://codemirror.net/LICENSE + /** * @file smartymixed.js * @brief Smarty Mixed Codemirror mode (Smarty + Mixed HTML) diff --git a/mode/solr/solr.js b/mode/solr/solr.js index 25d928ec1b..ed7eff6eb6 100644 --- a/mode/solr/solr.js +++ b/mode/solr/solr.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, 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")); diff --git a/mode/sparql/sparql.js b/mode/sparql/sparql.js index f228b1dffe..f4453e6864 100644 --- a/mode/sparql/sparql.js +++ b/mode/sparql/sparql.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, 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")); diff --git a/mode/sql/sql.js b/mode/sql/sql.js index 417db06282..59510ffa08 100644 --- a/mode/sql/sql.js +++ b/mode/sql/sql.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, 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")); diff --git a/mode/stex/stex.js b/mode/stex/stex.js index 59a395a0fe..b5ef7898f3 100644 --- a/mode/stex/stex.js +++ b/mode/stex/stex.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, copyright (c) by Marijn Haverbeke and others +// Distributed under an MIT license: http://codemirror.net/LICENSE + /* * Author: Constantin Jucovschi (c.jucovschi@jacobs-university.de) * Licence: MIT diff --git a/mode/stex/test.js b/mode/stex/test.js index ab629e81ea..6eaf0f6881 100644 --- a/mode/stex/test.js +++ b/mode/stex/test.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, copyright (c) by Marijn Haverbeke and others +// Distributed under an MIT license: http://codemirror.net/LICENSE + (function() { var mode = CodeMirror.getMode({tabSize: 4}, "stex"); function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); } diff --git a/mode/tcl/tcl.js b/mode/tcl/tcl.js index 4c29ee7d98..49c555b108 100644 --- a/mode/tcl/tcl.js +++ b/mode/tcl/tcl.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, copyright (c) by Marijn Haverbeke and others +// Distributed under an MIT license: http://codemirror.net/LICENSE + //tcl mode by Ford_Lawnmower :: Based on Velocity mode by Steve O'Hara (function(mod) { diff --git a/mode/tiddlywiki/tiddlywiki.js b/mode/tiddlywiki/tiddlywiki.js index ecd1d173c0..31dff8cb93 100644 --- a/mode/tiddlywiki/tiddlywiki.js +++ b/mode/tiddlywiki/tiddlywiki.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, copyright (c) by Marijn Haverbeke and others +// Distributed under an MIT license: http://codemirror.net/LICENSE + /*** |''Name''|tiddlywiki.js| |''Description''|Enables TiddlyWikiy syntax highlighting using CodeMirror| diff --git a/mode/tiki/tiki.js b/mode/tiki/tiki.js index eb9a893fde..02c2f1b74b 100644 --- a/mode/tiki/tiki.js +++ b/mode/tiki/tiki.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, 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")); diff --git a/mode/toml/toml.js b/mode/toml/toml.js index 2c722b3752..593807a900 100644 --- a/mode/toml/toml.js +++ b/mode/toml/toml.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, 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")); diff --git a/mode/turtle/turtle.js b/mode/turtle/turtle.js index de9fc2b6c7..b2c7023c16 100644 --- a/mode/turtle/turtle.js +++ b/mode/turtle/turtle.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, 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")); diff --git a/mode/vb/vb.js b/mode/vb/vb.js index 4fd80210fb..6fa42d97eb 100644 --- a/mode/vb/vb.js +++ b/mode/vb/vb.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, 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")); diff --git a/mode/vbscript/vbscript.js b/mode/vbscript/vbscript.js index 4be7c7f2bb..9293c0af34 100644 --- a/mode/vbscript/vbscript.js +++ b/mode/vbscript/vbscript.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, copyright (c) by Marijn Haverbeke and others +// Distributed under an MIT license: http://codemirror.net/LICENSE + /* For extra ASP classic objects, initialize CodeMirror instance with this option: isASP: true diff --git a/mode/velocity/velocity.js b/mode/velocity/velocity.js index b64636bb43..fd0292920b 100644 --- a/mode/velocity/velocity.js +++ b/mode/velocity/velocity.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, 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")); diff --git a/mode/verilog/test.js b/mode/verilog/test.js index 6f5770b848..42d4f618cf 100644 --- a/mode/verilog/test.js +++ b/mode/verilog/test.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, copyright (c) by Marijn Haverbeke and others +// Distributed under an MIT license: http://codemirror.net/LICENSE + (function() { var mode = CodeMirror.getMode({indentUnit: 4}, "verilog"); function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); } diff --git a/mode/verilog/verilog.js b/mode/verilog/verilog.js index d52ecea2a3..c575ac5f51 100644 --- a/mode/verilog/verilog.js +++ b/mode/verilog/verilog.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, 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")); diff --git a/mode/xml/test.js b/mode/xml/test.js index 1b9d9d1760..122e1675ce 100644 --- a/mode/xml/test.js +++ b/mode/xml/test.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, copyright (c) by Marijn Haverbeke and others +// Distributed under an MIT license: http://codemirror.net/LICENSE + (function() { var mode = CodeMirror.getMode({indentUnit: 2}, "xml"), mname = "xml"; function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1), mname); } diff --git a/mode/xml/xml.js b/mode/xml/xml.js index 3248c454d1..946757fc57 100644 --- a/mode/xml/xml.js +++ b/mode/xml/xml.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, 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")); diff --git a/mode/xquery/test.js b/mode/xquery/test.js index 41719dd169..511a879d90 100644 --- a/mode/xquery/test.js +++ b/mode/xquery/test.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, copyright (c) by Marijn Haverbeke and others +// Distributed under an MIT license: http://codemirror.net/LICENSE + // Don't take these too seriously -- the expected results appear to be // based on the results of actual runs without any serious manual // verification. If a change you made causes them to fail, the test is diff --git a/mode/xquery/xquery.js b/mode/xquery/xquery.js index 2c7faf425a..0426bf66a5 100644 --- a/mode/xquery/xquery.js +++ b/mode/xquery/xquery.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, 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")); diff --git a/mode/yaml/yaml.js b/mode/yaml/yaml.js index f7b3a90c03..41679f1eea 100644 --- a/mode/yaml/yaml.js +++ b/mode/yaml/yaml.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, 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")); diff --git a/mode/z80/z80.js b/mode/z80/z80.js index c778803072..d441e383ac 100644 --- a/mode/z80/z80.js +++ b/mode/z80/z80.js @@ -1,3 +1,6 @@ +// CodeMirror 4.1.1, 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")); diff --git a/test/lint/lint.js b/test/lint/lint.js index a65deb60be..ba8900f7d7 100644 --- a/test/lint/lint.js +++ b/test/lint/lint.js @@ -31,6 +31,8 @@ var scopePasser = walk.make({ ScopeBody: function(node, prev, c) { c(node, node.scope); } }); +var cBlob = /^\/\/ CodeMirror \d+\.\d+\.\d+, copyright \(c\) by Marijn Haverbeke and others\n\/\/ Distributed under an MIT license: http:\/\/codemirror.net\/LICENSE\n\n/; + function checkFile(fileName) { var file = fs.readFileSync(fileName, "utf8"), notAllowed; if (notAllowed = file.match(/[\x00-\x08\x0b\x0c\x0e-\x19\uFEFF\t]|[ \t]\n/)) { @@ -41,6 +43,9 @@ function checkFile(fileName) { var info = acorn.getLineInfo(file, notAllowed.index); fail(msg + " at line " + info.line + ", column " + info.column, {source: fileName}); } + + if (!cBlob.test(file)) + fail("Missing license blob", {source: fileName}); var globalsSeen = Object.create(null); @@ -152,7 +157,7 @@ function checkDir(dir) { fs.readdirSync(dir).forEach(function(file) { var fname = dir + "/" + file; if (/\.js$/.test(file)) checkFile(fname); - else if (file != "dep" && fs.lstatSync(fname).isDirectory()) checkDir(fname); + else if (fs.lstatSync(fname).isDirectory()) checkDir(fname); }); } From 01fb28518dd76a7848606669020bc1b85a81c899 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Fri, 9 May 2014 15:56:59 +0200 Subject: [PATCH 0701/4131] Fix bug in release script --- bin/release | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/release b/bin/release index 91451faae5..c26d290f94 100755 --- a/bin/release +++ b/bin/release @@ -30,7 +30,7 @@ rewrite("doc/manual.html", function(manual) { function walkDir(dir) { fs.readdirSync(dir).forEach(function(file) { var fname = dir + "/" + file; - if (/\.js$/.test(file)) rewrite(file, function(script) { + if (/\.js$/.test(file)) rewrite(fname, function(script) { return script.replace(/^\/\/ CodeMirror \d+\.\d+\.\d+, copyright/, "// CodeMirror " + number + ", copyright"); }); From a5b79b5c30fd8694fcb1fdaafeb70ab0bd335ca9 Mon Sep 17 00:00:00 2001 From: as3boyan Date: Sat, 10 May 2014 22:00:23 +0300 Subject: [PATCH 0702/4131] [show-hint addon] Fix a typo --- addon/hint/show-hint.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addon/hint/show-hint.js b/addon/hint/show-hint.js index 4bede1fb03..59322749ce 100644 --- a/addon/hint/show-hint.js +++ b/addon/hint/show-hint.js @@ -379,7 +379,7 @@ alignWithWord: true, closeCharacters: /[\s()\[\]{};:>,]/, closeOnUnfocus: true, - completeOnSignleClick: false, + completeOnSingleClick: false, container: null, customKeys: null, extraKeys: null From a0edb5ba6f5d6ccb289ab6ab2ef2b6b4ad98762b Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 12 May 2014 09:20:28 +0200 Subject: [PATCH 0703/4131] Don't mess up the display when updateDisplay is given a negative top offset Issue #2554 --- lib/codemirror.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/codemirror.js b/lib/codemirror.js index 50bccb38a9..ddb2514618 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -463,7 +463,7 @@ // the the current scroll position). viewPort may contain top, // height, and ensure (see op.scrollToPos) properties. function visibleLines(display, doc, viewPort) { - var top = viewPort && viewPort.top != null ? viewPort.top : display.scroller.scrollTop; + var top = viewPort && viewPort.top != null ? Math.max(0, viewPort.top) : display.scroller.scrollTop; top = Math.floor(top - paddingTop(display)); var bottom = viewPort && viewPort.bottom != null ? viewPort.bottom : top + display.wrapper.clientHeight; @@ -667,7 +667,6 @@ cm.display.gutters.style.height = Math.max(measure.docHeight, measure.clientHeight - scrollerCutOff) + "px"; } - function checkForWebkitWidthBug(cm, measure) { // Work around Webkit bug where it sometimes reserves space for a // non-existing phantom scrollbar in the scroller (Issue #2420) From bb0725b52fd9a1bcf19c623e0fb19f43ace40522 Mon Sep 17 00:00:00 2001 From: Bem Jones-Bey Date: Fri, 9 May 2014 10:28:00 -0700 Subject: [PATCH 0704/4131] [css mode] Add object-fit and object-position properties --- mode/css/css.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mode/css/css.js b/mode/css/css.js index 6b49e473f0..e5ed6ad5f5 100644 --- a/mode/css/css.js +++ b/mode/css/css.js @@ -425,7 +425,8 @@ CodeMirror.defineMode("css", function(config, parserConfig) { "marker-offset", "marks", "marquee-direction", "marquee-loop", "marquee-play-count", "marquee-speed", "marquee-style", "max-height", "max-width", "min-height", "min-width", "move-to", "nav-down", "nav-index", - "nav-left", "nav-right", "nav-up", "opacity", "order", "orphans", "outline", + "nav-left", "nav-right", "nav-up", "object-fit", "object-position", + "opacity", "order", "orphans", "outline", "outline-color", "outline-offset", "outline-style", "outline-width", "overflow", "overflow-style", "overflow-wrap", "overflow-x", "overflow-y", "padding", "padding-bottom", "padding-left", "padding-right", "padding-top", From 33eb40146574312f7de39c697af3b18c86d0d902 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 12 May 2014 10:07:27 +0200 Subject: [PATCH 0705/4131] [css mode] Better handling of parentheses in property values Issue #2551 --- mode/css/css.js | 15 +++++---------- mode/css/test.js | 10 ++++++++++ 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/mode/css/css.js b/mode/css/css.js index e5ed6ad5f5..00d3785bcf 100644 --- a/mode/css/css.js +++ b/mode/css/css.js @@ -167,7 +167,7 @@ CodeMirror.defineMode("css", function(config, parserConfig) { } else if (type == ":") { return "pseudo"; } else if (allowNested && type == "(") { - return pushContext(state, stream, "params"); + return pushContext(state, stream, "parens"); } return state.context.type; }; @@ -228,6 +228,8 @@ CodeMirror.defineMode("css", function(config, parserConfig) { states.parens = function(type, stream, state) { if (type == "{" || type == "}") return popAndPass(type, stream, state); if (type == ")") return popContext(state); + if (type == "(") return pushContext(state, stream, "parens"); + if (type == "word") wordAsValue(stream); return "parens"; }; @@ -303,13 +305,6 @@ CodeMirror.defineMode("css", function(config, parserConfig) { return "interpolation"; }; - states.params = function(type, stream, state) { - if (type == ")") return popContext(state); - if (type == "{" || type == "}") return popAndPass(type, stream, state); - if (type == "word") wordAsValue(stream); - return "params"; - }; - return { startState: function(base) { return {tokenize: null, @@ -332,10 +327,10 @@ CodeMirror.defineMode("css", function(config, parserConfig) { indent: function(state, textAfter) { var cx = state.context, ch = textAfter && textAfter.charAt(0); var indent = cx.indent; - if (cx.type == "prop" && ch == "}") cx = cx.prev; + if (cx.type == "prop" && (ch == "}" || ch == ")")) cx = cx.prev; if (cx.prev && (ch == "}" && (cx.type == "block" || cx.type == "top" || cx.type == "interpolation" || cx.type == "font_face") || - ch == ")" && (cx.type == "parens" || cx.type == "params" || cx.type == "media_parens") || + ch == ")" && (cx.type == "parens" || cx.type == "media_parens") || ch == "{" && (cx.type == "at" || cx.type == "media"))) { indent = cx.indent - indentUnit; cx = cx.prev; diff --git a/mode/css/test.js b/mode/css/test.js index 85f597b570..1a75e08ea4 100644 --- a/mode/css/test.js +++ b/mode/css/test.js @@ -122,4 +122,14 @@ MT("empty_url", "[def @import] [tag url]() [tag screen];"); + + MT("parens", + "[qualifier .foo] {", + " [property background-image]: [variable fade]([atom #000], [number 20%]);", + " [property border-image]: [variable linear-gradient](", + " [atom to] [atom bottom],", + " [variable fade]([atom #000], [number 20%]) [number 0%],", + " [variable fade]([atom #000], [number 20%]) [number 100%]", + " );", + "}"); })(); From 687fb51f4a6547942b08efee81e8b84393d99a5b Mon Sep 17 00:00:00 2001 From: daines Date: Mon, 12 May 2014 09:24:07 -0400 Subject: [PATCH 0706/4131] Fix typo in manual --- doc/manual.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/manual.html b/doc/manual.html index 59c81f3456..d78797dadd 100644 --- a/doc/manual.html +++ b/doc/manual.html @@ -2328,7 +2328,7 @@

    Addons

    of the token that is being completed as {line, ch} objects.
    If no hinting function is given, the addon will - use CodeMirror.hint.auto, with + use CodeMirror.hint.auto, which calls getHelpers with the "hint" type to find applicable hinting functions, and tries them one by one. If that fails, it looks From 87df1c6e7f2a07c42689c6afba4b7192445196c8 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Tue, 13 May 2014 11:20:30 +0200 Subject: [PATCH 0707/4131] [closetag addon] Improve heuristic for seeing if closing tag already exists Issue #2557 --- addon/edit/closetag.js | 28 +++++++++++++++++++++++++--- addon/fold/xml-fold.js | 2 +- mode/xml/xml.js | 2 +- 3 files changed, 27 insertions(+), 5 deletions(-) diff --git a/addon/edit/closetag.js b/addon/edit/closetag.js index d64045ab1b..db31b0eb02 100644 --- a/addon/edit/closetag.js +++ b/addon/edit/closetag.js @@ -58,6 +58,7 @@ var pos = ranges[i].head, tok = cm.getTokenAt(pos); var inner = CodeMirror.innerMode(cm.getMode(), tok.state), state = inner.state; if (inner.mode.name != "xml" || !state.tagName) return CodeMirror.Pass; + var opt = cm.getOption("autoCloseTags"), html = inner.mode.configuration == "html"; var dontCloseTags = (typeof opt == "object" && opt.dontCloseTags) || (html && htmlDontClose); var indentTags = (typeof opt == "object" && opt.indentTags) || (html && htmlIndent); @@ -71,8 +72,7 @@ tok.type == "tag" && state.type == "closeTag" || tok.string.indexOf("/") == (tok.string.length - 1) || // match something like dontCloseTags && indexOf(dontCloseTags, lowerTagName) > -1 || - CodeMirror.scanForClosingTag && CodeMirror.scanForClosingTag(cm, pos, tagName, - Math.min(cm.lastLine() + 1, pos.line + 50))) + closingTagExists(cm, tagName, pos, state, true)) return CodeMirror.Pass; var indent = indentTags && indexOf(indentTags, lowerTagName) > -1; @@ -103,7 +103,8 @@ var inner = CodeMirror.innerMode(cm.getMode(), tok.state), state = inner.state; if (tok.type == "string" || tok.string.charAt(0) != "<" || tok.start != pos.ch - 1 || inner.mode.name != "xml" || - !state.context || !state.context.tagName) + !state.context || !state.context.tagName || + closingTagExists(cm, state.context.tagName, pos, state)) return CodeMirror.Pass; replacements[i] = "/" + state.context.tagName + ">"; } @@ -116,4 +117,25 @@ if (collection[i] == elt) return i; return -1; } + + // If xml-fold is loaded, we use its functionality to try and verify + // whether a given tag is actually unclosed. + function closingTagExists(cm, tagName, pos, state, newTag) { + if (!CodeMirror.scanForClosingTag) return false; + var end = Math.min(cm.lastLine() + 1, pos.line + 500); + var nextClose = CodeMirror.scanForClosingTag(cm, pos, null, end); + if (!nextClose || nextClose.tag != tagName) return false; + var cx = state.context; + // If the immediate wrapping context contains onCx instances of + // the same tag, a closing tag only exists if there are at least + // that many closing tags of that type following. + for (var onCx = newTag ? 1 : 0; cx && cx.tagName == tagName; cx = cx.prev) ++onCx; + pos = nextClose.to; + for (var i = 1; i < onCx; i++) { + var next = CodeMirror.scanForClosingTag(cm, pos, null, end); + if (!next || next.tag != tagName) return false; + pos = next.to; + } + return true; + } }); diff --git a/addon/fold/xml-fold.js b/addon/fold/xml-fold.js index e1fd5756d8..33d6e07b53 100644 --- a/addon/fold/xml-fold.js +++ b/addon/fold/xml-fold.js @@ -176,6 +176,6 @@ // Used by addon/edit/closetag.js CodeMirror.scanForClosingTag = function(cm, pos, name, end) { var iter = new Iter(cm, pos.line, pos.ch, end ? {from: 0, to: end} : null); - return !!findMatchingClose(iter, name); + return findMatchingClose(iter, name); }; }); diff --git a/mode/xml/xml.js b/mode/xml/xml.js index 946757fc57..9a84b632aa 100644 --- a/mode/xml/xml.js +++ b/mode/xml/xml.js @@ -124,7 +124,7 @@ CodeMirror.defineMode("xml", function(config, parserConfig) { state.state = baseState; state.tagName = state.tagStart = null; var next = state.tokenize(stream, state); - return next ? next + " error" : "error"; + return next ? next + " tag error" : "tag error"; } else if (/[\'\"]/.test(ch)) { state.tokenize = inAttribute(ch); state.stringStartCol = stream.column(); From 5b5c813680f3f69affc472942e3000c1b714e0db Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Tue, 13 May 2014 11:32:21 +0200 Subject: [PATCH 0708/4131] Make ctrl-drag copy text Issue #2556 --- lib/codemirror.js | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/lib/codemirror.js b/lib/codemirror.js index ddb2514618..ba39b4e9a3 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -2574,17 +2574,17 @@ lastClick = {time: now, pos: start}; } - var sel = cm.doc.sel, addNew = mac ? e.metaKey : e.ctrlKey; - if (cm.options.dragDrop && dragAndDrop && !addNew && !isReadOnly(cm) && + var sel = cm.doc.sel, modifier = mac ? e.metaKey : e.ctrlKey; + if (cm.options.dragDrop && dragAndDrop && !isReadOnly(cm) && type == "single" && sel.contains(start) > -1 && sel.somethingSelected()) - leftButtonStartDrag(cm, e, start); + leftButtonStartDrag(cm, e, start, modifier); else - leftButtonSelect(cm, e, start, type, addNew); + leftButtonSelect(cm, e, start, type, modifier); } // Start a text drag. When it ends, see if any dragging actually // happen, and treat as a click if it didn't. - function leftButtonStartDrag(cm, e, start) { + function leftButtonStartDrag(cm, e, start, modifier) { var display = cm.display; var dragEnd = operation(cm, function(e2) { if (webkit) display.scroller.draggable = false; @@ -2593,7 +2593,8 @@ off(display.scroller, "drop", dragEnd); if (Math.abs(e.clientX - e2.clientX) + Math.abs(e.clientY - e2.clientY) < 10) { e_preventDefault(e2); - extendSelection(cm.doc, start); + if (!modifier) + extendSelection(cm.doc, start); focusInput(cm); // Work around unexplainable focus problem in IE9 (#2127) if (ie_upto10 && !ie_upto8) @@ -2817,7 +2818,8 @@ try { var text = e.dataTransfer.getData("Text"); if (text) { - var selected = cm.state.draggingText && cm.listSelections(); + if (cm.state.draggingText && !(mac ? e.metaKey : e.ctrlKey)) + var selected = cm.listSelections(); setSelectionNoUndo(cm.doc, simpleSelection(pos, pos)); if (selected) for (var i = 0; i < selected.length; ++i) replaceRange(cm.doc, "", selected[i].anchor, selected[i].head, "drag"); From e6eed2510342b43bdc869f860385a49f8e4061a0 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Tue, 13 May 2014 11:53:02 +0200 Subject: [PATCH 0709/4131] Ensure a viewport always contains a single line --- lib/codemirror.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/codemirror.js b/lib/codemirror.js index ba39b4e9a3..371c37651f 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -479,7 +479,7 @@ return {from: lineAtHeight(doc, heightAtLine(getLine(doc, ensureTo)) - display.wrapper.clientHeight), to: ensureTo}; } - return {from: from, to: to}; + return {from: from, to: Math.max(to, from + 1)}; } // LINE NUMBERS From 02725ae5464565178884059639e791ca42aee266 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Tue, 13 May 2014 13:18:48 +0200 Subject: [PATCH 0710/4131] [tern addon] Improve alignment of completion docs --- addon/tern/tern.css | 1 + 1 file changed, 1 insertion(+) diff --git a/addon/tern/tern.css b/addon/tern/tern.css index eacc2f053a..76fba33d4a 100644 --- a/addon/tern/tern.css +++ b/addon/tern/tern.css @@ -76,6 +76,7 @@ .CodeMirror-Tern-hint-doc { max-width: 25em; + margin-top: -3px; } .CodeMirror-Tern-fname { color: black; } From 9556bdd640d17ffccaa40d80939cfbce0e36b160 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Tue, 13 May 2014 13:34:43 +0200 Subject: [PATCH 0711/4131] [tern addon] Remove unnecessary error check --- addon/tern/tern.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/addon/tern/tern.js b/addon/tern/tern.js index 318f1484d9..3508f18130 100644 --- a/addon/tern/tern.js +++ b/addon/tern/tern.js @@ -432,7 +432,7 @@ function rename(ts, cm) { var token = cm.getTokenAt(cm.getCursor()); - if (!/\w/.test(token.string)) showError(ts, cm, "Not at a variable"); + if (!/\w/.test(token.string)) return showError(ts, cm, "Not at a variable"); dialog(cm, "New name for " + token.string, function(newName) { ts.request(cm, {type: "rename", newName: newName, fullDocs: true}, function(error, data) { if (error) return showError(ts, cm, error); @@ -443,7 +443,6 @@ function selectName(ts, cm) { var cur = cm.getCursor(), token = cm.getTokenAt(cur); - if (!/\w/.test(token.string)) showError(ts, cm, "Not at a variable"); var name = findDoc(ts, cm.doc).name; ts.request(cm, {type: "refs"}, function(error, data) { if (error) return showError(ts, cm, error); From 09c8a0b09afe6eab99ea297a2d2bc1c737546b80 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Tue, 13 May 2014 13:41:49 +0200 Subject: [PATCH 0712/4131] [tern addon] Lint fix --- addon/tern/tern.js | 1 - 1 file changed, 1 deletion(-) diff --git a/addon/tern/tern.js b/addon/tern/tern.js index 3508f18130..9bae94b27e 100644 --- a/addon/tern/tern.js +++ b/addon/tern/tern.js @@ -442,7 +442,6 @@ } function selectName(ts, cm) { - var cur = cm.getCursor(), token = cm.getTokenAt(cur); var name = findDoc(ts, cm.doc).name; ts.request(cm, {type: "refs"}, function(error, data) { if (error) return showError(ts, cm, error); From 714954d744e74626b38a87834c7e46a589133f01 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 15 May 2014 12:34:58 +0200 Subject: [PATCH 0713/4131] [tern addon] Allow hiding and deleting docs by identity, not just name --- addon/tern/tern.js | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/addon/tern/tern.js b/addon/tern/tern.js index 9bae94b27e..27d6421512 100644 --- a/addon/tern/tern.js +++ b/addon/tern/tern.js @@ -17,7 +17,7 @@ // indicate that a file is not available. // * fileFilter: A function(value, docName, doc) that will be applied // to documents before passing them on to Tern. -// * switchToDoc: A function(name) that should, when providing a +// * switchToDoc: A function(name, doc) that should, when providing a // multi-file view, switch the view or focus to the named file. // * showError: A function(editor, message) that can be used to // override the way errors are displayed. @@ -88,17 +88,17 @@ return this.docs[name] = data; }, - delDoc: function(name) { - var found = this.docs[name]; + delDoc: function(id) { + var found = resolveDoc(this, id); if (!found) return; CodeMirror.off(found.doc, "change", this.trackChange); - delete this.docs[name]; - this.server.delFile(name); + delete this.docs[found.name]; + this.server.delFile(found.name); }, - hideDoc: function(name) { + hideDoc: function(id) { closeArgHints(this); - var found = this.docs[name]; + var found = resolveDoc(this, id); if (found && found.changed) sendDoc(this, found); }, @@ -157,6 +157,12 @@ return ts.addDoc(name, doc); } + function resolveDoc(ts, id) { + if (typeof id == "string") return ts.docs[id]; + if (id instanceof CodeMirror) id = id.getDoc(); + if (id instanceof CodeMirror.Doc) return findDoc(ts, id); + } + function trackChange(ts, doc, change) { var data = findDoc(ts, doc); @@ -387,7 +393,7 @@ doc.doc.setSelection(end, start); if (curDoc != doc && ts.options.switchToDoc) { closeArgHints(ts); - ts.options.switchToDoc(doc.name); + ts.options.switchToDoc(doc.name, doc.doc); } } From c6e7cd1bd76cb42fe67199cd643d2b17cc3d0372 Mon Sep 17 00:00:00 2001 From: Yunchi Luo Date: Fri, 9 May 2014 20:42:08 +0200 Subject: [PATCH 0714/4131] [vim] Add vim keypress and command done events --- demo/vim.html | 11 +++++++++++ keymap/vim.js | 16 +++++++++++----- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/demo/vim.html b/demo/vim.html index ad34660892..f92ff9e6d8 100644 --- a/demo/vim.html +++ b/demo/vim.html @@ -45,6 +45,7 @@

    Vim bindings demo

    return (--n >= 0) ? (unsigned char) *bufp++ : EOF; } +
    + + +

    Mode for Kotlin (http://kotlin.jetbrains.org/)

    +

    Developed by Hadi Hariri (https://github.com/hhariri).

    +

    MIME type defined: text/x-kotlin.

    + diff --git a/mode/kotlin/kotlin.js b/mode/kotlin/kotlin.js new file mode 100644 index 0000000000..73c84f6c4f --- /dev/null +++ b/mode/kotlin/kotlin.js @@ -0,0 +1,280 @@ +// 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.defineMode("kotlin", function (config, parserConfig) { + function words(str) { + var obj = {}, words = str.split(" "); + for (var i = 0; i < words.length; ++i) obj[words[i]] = true; + return obj; + } + + var multiLineStrings = parserConfig.multiLineStrings; + + var keywords = words( + "package continue return object while break class data trait throw super" + + " when type this else This try val var fun for is in if do as true false null get set"); + var softKeywords = words("import" + + " where by get set abstract enum open annotation override private public internal" + + " protected catch out vararg inline finally final ref"); + var blockKeywords = words("catch class do else finally for if where try while enum"); + var atoms = words("null true false this"); + + var curPunc; + + function tokenBase(stream, state) { + var ch = stream.next(); + if (ch == '"' || ch == "'") { + return startString(ch, stream, state); + } + // Wildcard import w/o trailing semicolon (import smth.*) + if (ch == "." && stream.eat("*")) { + return "word"; + } + if (/[\[\]{}\(\),;\:\.]/.test(ch)) { + curPunc = ch; + return null; + } + if (/\d/.test(ch)) { + if (stream.eat(/eE/)) { + stream.eat(/\+\-/); + stream.eatWhile(/\d/); + } + return "number"; + } + if (ch == "/") { + if (stream.eat("*")) { + state.tokenize.push(tokenComment); + return tokenComment(stream, state); + } + if (stream.eat("/")) { + stream.skipToEnd(); + return "comment"; + } + if (expectExpression(state.lastToken)) { + return startString(ch, stream, state); + } + } + // Commented + if (ch == "-" && stream.eat(">")) { + curPunc = "->"; + return null; + } + if (/[\-+*&%=<>!?|\/~]/.test(ch)) { + stream.eatWhile(/[\-+*&%=<>|~]/); + return "operator"; + } + stream.eatWhile(/[\w\$_]/); + + var cur = stream.current(); + if (atoms.propertyIsEnumerable(cur)) { + return "atom"; + } + if (softKeywords.propertyIsEnumerable(cur)) { + if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement"; + return "softKeyword"; + } + + if (keywords.propertyIsEnumerable(cur)) { + if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement"; + return "keyword"; + } + return "word"; + } + + tokenBase.isBase = true; + + function startString(quote, stream, state) { + var tripleQuoted = false; + if (quote != "/" && stream.eat(quote)) { + if (stream.eat(quote)) tripleQuoted = true; + else return "string"; + } + function t(stream, state) { + var escaped = false, next, end = !tripleQuoted; + + while ((next = stream.next()) != null) { + if (next == quote && !escaped) { + if (!tripleQuoted) { + break; + } + if (stream.match(quote + quote)) { + end = true; + break; + } + } + + if (quote == '"' && next == "$" && !escaped && stream.eat("{")) { + state.tokenize.push(tokenBaseUntilBrace()); + return "string"; + } + + if (next == "$" && !escaped && !stream.eat(" ")) { + state.tokenize.push(tokenBaseUntilSpace()); + return "string"; + } + escaped = !escaped && next == "\\"; + } + if (multiLineStrings) + state.tokenize.push(t); + if (end) state.tokenize.pop(); + return "string"; + } + + state.tokenize.push(t); + return t(stream, state); + } + + function tokenBaseUntilBrace() { + var depth = 1; + + function t(stream, state) { + if (stream.peek() == "}") { + depth--; + if (depth == 0) { + state.tokenize.pop(); + return state.tokenize[state.tokenize.length - 1](stream, state); + } + } else if (stream.peek() == "{") { + depth++; + } + return tokenBase(stream, state); + } + + t.isBase = true; + return t; + } + + function tokenBaseUntilSpace() { + function t(stream, state) { + if (stream.eat(/[\w]/)) { + var isWord = stream.eatWhile(/[\w]/); + if (isWord) { + state.tokenize.pop(); + return "word"; + } + } + state.tokenize.pop(); + return "string"; + } + + t.isBase = true; + return t; + } + + function tokenComment(stream, state) { + var maybeEnd = false, ch; + while (ch = stream.next()) { + if (ch == "/" && maybeEnd) { + state.tokenize.pop(); + break; + } + maybeEnd = (ch == "*"); + } + return "comment"; + } + + function expectExpression(last) { + return !last || last == "operator" || last == "->" || /[\.\[\{\(,;:]/.test(last) || + last == "newstatement" || last == "keyword" || last == "proplabel"; + } + + function Context(indented, column, type, align, prev) { + this.indented = indented; + this.column = column; + this.type = type; + this.align = align; + this.prev = prev; + } + + function pushContext(state, col, type) { + return state.context = new Context(state.indented, col, type, null, state.context); + } + + function popContext(state) { + var t = state.context.type; + if (t == ")" || t == "]" || t == "}") + state.indented = state.context.indented; + return state.context = state.context.prev; + } + + // Interface + + return { + startState: function (basecolumn) { + return { + tokenize: [tokenBase], + context: new Context((basecolumn || 0) - config.indentUnit, 0, "top", false), + indented: 0, + startOfLine: true, + lastToken: null + }; + }, + + token: function (stream, state) { + var ctx = state.context; + if (stream.sol()) { + if (ctx.align == null) ctx.align = false; + state.indented = stream.indentation(); + state.startOfLine = true; + // Automatic semicolon insertion + if (ctx.type == "statement" && !expectExpression(state.lastToken)) { + popContext(state); + ctx = state.context; + } + } + if (stream.eatSpace()) return null; + curPunc = null; + var style = state.tokenize[state.tokenize.length - 1](stream, state); + if (style == "comment") return style; + if (ctx.align == null) ctx.align = true; + if ((curPunc == ";" || curPunc == ":") && ctx.type == "statement") popContext(state); + // Handle indentation for {x -> \n ... } + else if (curPunc == "->" && ctx.type == "statement" && ctx.prev.type == "}") { + popContext(state); + state.context.align = false; + } + else if (curPunc == "{") pushContext(state, stream.column(), "}"); + else if (curPunc == "[") pushContext(state, stream.column(), "]"); + else if (curPunc == "(") pushContext(state, stream.column(), ")"); + else if (curPunc == "}") { + while (ctx.type == "statement") ctx = popContext(state); + if (ctx.type == "}") ctx = popContext(state); + while (ctx.type == "statement") ctx = popContext(state); + } + else if (curPunc == ctx.type) popContext(state); + else if (ctx.type == "}" || ctx.type == "top" || (ctx.type == "statement" && curPunc == "newstatement")) + pushContext(state, stream.column(), "statement"); + state.startOfLine = false; + state.lastToken = curPunc || style; + return style; + }, + + indent: function (state, textAfter) { + if (!state.tokenize[state.tokenize.length - 1].isBase) return 0; + var firstChar = textAfter && textAfter.charAt(0), ctx = state.context; + if (ctx.type == "statement" && !expectExpression(state.lastToken)) ctx = ctx.prev; + var closing = firstChar == ctx.type; + if (ctx.type == "statement") { + return ctx.indented + (firstChar == "{" ? 0 : config.indentUnit); + } + else if (ctx.align) return ctx.column + (closing ? 0 : 1); + else return ctx.indented + (closing ? 0 : config.indentUnit); + }, + + electricChars: "{}" + }; +}); + +CodeMirror.defineMIME("text/x-kotlin", "kotlin"); + +}); From 4928d37fb9650ce76e1dcba8ad593f1a579b1f70 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Fri, 4 Jul 2014 11:54:03 +0200 Subject: [PATCH 0816/4131] [kotlin mode] Integrate Issue #2678 --- doc/compress.html | 1 + mode/index.html | 1 + mode/kotlin/index.html | 3 +- mode/meta.js | 193 +++++++++++++++++++++-------------------- 4 files changed, 101 insertions(+), 97 deletions(-) diff --git a/doc/compress.html b/doc/compress.html index 5762aa442b..ede45e1c6e 100644 --- a/doc/compress.html +++ b/doc/compress.html @@ -123,6 +123,7 @@

    Script compression helper

    + diff --git a/mode/index.html b/mode/index.html index 91fb92bff8..1aa0b8d821 100644 --- a/mode/index.html +++ b/mode/index.html @@ -65,6 +65,7 @@

    Language modes

  • JavaScript
  • Jinja2
  • Julia
  • +
  • Kotlin
  • LESS
  • LiveScript
  • Lua
  • diff --git a/mode/kotlin/index.html b/mode/kotlin/index.html index 24fb46706f..38700f3226 100644 --- a/mode/kotlin/index.html +++ b/mode/kotlin/index.html @@ -79,7 +79,8 @@

    Kotlin mode

    Mode for Kotlin (http://kotlin.jetbrains.org/)

    diff --git a/mode/meta.js b/mode/meta.js index 4e42cb32df..3627cd7470 100644 --- a/mode/meta.js +++ b/mode/meta.js @@ -12,102 +12,103 @@ "use strict"; CodeMirror.modeInfo = [ - {name: 'APL', mime: 'text/apl', mode: 'apl'}, - {name: 'Asterisk', mime: 'text/x-asterisk', mode: 'asterisk'}, - {name: 'C', mime: 'text/x-csrc', mode: 'clike'}, - {name: 'C++', mime: 'text/x-c++src', mode: 'clike'}, - {name: 'Cobol', mime: 'text/x-cobol', mode: 'cobol'}, - {name: 'Java', mime: 'text/x-java', mode: 'clike'}, - {name: 'C#', mime: 'text/x-csharp', mode: 'clike'}, - {name: 'Scala', mime: 'text/x-scala', mode: 'clike'}, - {name: 'Clojure', mime: 'text/x-clojure', mode: 'clojure'}, - {name: 'CoffeeScript', mime: 'text/x-coffeescript', mode: 'coffeescript'}, - {name: 'Common Lisp', mime: 'text/x-common-lisp', mode: 'commonlisp'}, - {name: 'Cypher', mime: 'application/x-cypher-query', mode: 'cypher'}, - {name: 'CSS', mime: 'text/css', mode: 'css'}, - {name: 'D', mime: 'text/x-d', mode: 'd'}, - {name: 'diff', mime: 'text/x-diff', mode: 'diff'}, - {name: 'DTD', mime: 'application/xml-dtd', mode: 'dtd'}, - {name: 'Dylan', mime: 'text/x-dylan', mode: 'dylan'}, - {name: 'ECL', mime: 'text/x-ecl', mode: 'ecl'}, - {name: 'Eiffel', mime: 'text/x-eiffel', mode: 'eiffel'}, - {name: 'Erlang', mime: 'text/x-erlang', mode: 'erlang'}, - {name: 'Fortran', mime: 'text/x-fortran', mode: 'fortran'}, - {name: 'F#', mime: 'text/x-fsharp', mode: 'mllike'}, - {name: 'Gas', mime: 'text/x-gas', mode: 'gas'}, - {name: 'Gherkin', mime: 'text/x-feature', mode: 'gherkin'}, - {name: 'GitHub Flavored Markdown', mime: 'text/x-gfm', mode: 'gfm'}, - {name: 'Go', mime: 'text/x-go', mode: 'go'}, - {name: 'Groovy', mime: 'text/x-groovy', mode: 'groovy'}, - {name: 'HAML', mime: 'text/x-haml', mode: 'haml'}, - {name: 'Haskell', mime: 'text/x-haskell', mode: 'haskell'}, - {name: 'Haxe', mime: 'text/x-haxe', mode: 'haxe'}, - {name: 'ASP.NET', mime: 'application/x-aspx', mode: 'htmlembedded'}, - {name: 'Embedded Javascript', mime: 'application/x-ejs', mode: 'htmlembedded'}, - {name: 'JavaServer Pages', mime: 'application/x-jsp', mode: 'htmlembedded'}, - {name: 'HTML', mime: 'text/html', mode: 'htmlmixed'}, - {name: 'HTTP', mime: 'message/http', mode: 'http'}, - {name: 'Jade', mime: 'text/x-jade', mode: 'jade'}, - {name: 'JavaScript', mime: 'text/javascript', mode: 'javascript'}, - {name: 'JavaScript', mime: 'application/javascript', mode: 'javascript'}, - {name: 'JSON', mime: 'application/x-json', mode: 'javascript'}, - {name: 'JSON', mime: 'application/json', mode: 'javascript'}, - {name: 'JSON-LD', mime: 'application/ld+json', mode: 'javascript'}, - {name: 'TypeScript', mime: 'application/typescript', mode: 'javascript'}, - {name: 'Jinja2', mime: null, mode: 'jinja2'}, - {name: 'Julia', mime: 'text/x-julia', mode: 'julia'}, - {name: 'LESS', mime: 'text/x-less', mode: 'css'}, - {name: 'LiveScript', mime: 'text/x-livescript', mode: 'livescript'}, - {name: 'Lua', mime: 'text/x-lua', mode: 'lua'}, - {name: 'Markdown (GitHub-flavour)', mime: 'text/x-markdown', mode: 'markdown'}, - {name: 'mIRC', mime: 'text/mirc', mode: 'mirc'}, - {name: 'Nginx', mime: 'text/x-nginx-conf', mode: 'nginx'}, - {name: 'NTriples', mime: 'text/n-triples', mode: 'ntriples'}, - {name: 'OCaml', mime: 'text/x-ocaml', mode: 'mllike'}, - {name: 'Octave', mime: 'text/x-octave', mode: 'octave'}, - {name: 'Pascal', mime: 'text/x-pascal', mode: 'pascal'}, - {name: 'PEG.js', mime: null, mode: 'pegjs'}, - {name: 'Perl', mime: 'text/x-perl', mode: 'perl'}, - {name: 'PHP', mime: 'text/x-php', mode: 'php'}, - {name: 'PHP(HTML)', mime: 'application/x-httpd-php', mode: 'php'}, - {name: 'Pig', mime: 'text/x-pig', mode: 'pig'}, - {name: 'Plain Text', mime: 'text/plain', mode: 'null'}, - {name: 'Properties files', mime: 'text/x-properties', mode: 'properties'}, - {name: 'Python', mime: 'text/x-python', mode: 'python'}, - {name: 'Puppet', mime: 'text/x-puppet', mode: 'puppet'}, - {name: 'Cython', mime: 'text/x-cython', mode: 'python'}, - {name: 'R', mime: 'text/x-rsrc', mode: 'r'}, - {name: 'reStructuredText', mime: 'text/x-rst', mode: 'rst'}, - {name: 'Ruby', mime: 'text/x-ruby', mode: 'ruby'}, - {name: 'Rust', mime: 'text/x-rustsrc', mode: 'rust'}, - {name: 'Sass', mime: 'text/x-sass', mode: 'sass'}, - {name: 'Scheme', mime: 'text/x-scheme', mode: 'scheme'}, - {name: 'SCSS', mime: 'text/x-scss', mode: 'css'}, - {name: 'Shell', mime: 'text/x-sh', mode: 'shell'}, - {name: 'Sieve', mime: 'application/sieve', mode: 'sieve'}, - {name: 'Smalltalk', mime: 'text/x-stsrc', mode: 'smalltalk'}, - {name: 'Smarty', mime: 'text/x-smarty', mode: 'smarty'}, - {name: 'SmartyMixed', mime: 'text/x-smarty', mode: 'smartymixed'}, - {name: 'Solr', mime: 'text/x-solr', mode: 'solr'}, - {name: 'SPARQL', mime: 'application/x-sparql-query', mode: 'sparql'}, - {name: 'SQL', mime: 'text/x-sql', mode: 'sql'}, - {name: 'MariaDB', mime: 'text/x-mariadb', mode: 'sql'}, - {name: 'sTeX', mime: 'text/x-stex', mode: 'stex'}, - {name: 'LaTeX', mime: 'text/x-latex', mode: 'stex'}, - {name: 'SystemVerilog', mime: 'text/x-systemverilog', mode: 'verilog'}, - {name: 'Tcl', mime: 'text/x-tcl', mode: 'tcl'}, - {name: 'TiddlyWiki ', mime: 'text/x-tiddlywiki', mode: 'tiddlywiki'}, - {name: 'Tiki wiki', mime: 'text/tiki', mode: 'tiki'}, - {name: 'TOML', mime: 'text/x-toml', mode: 'toml'}, - {name: 'Turtle', mime: 'text/turtle', mode: 'turtle'}, - {name: 'VB.NET', mime: 'text/x-vb', mode: 'vb'}, - {name: 'VBScript', mime: 'text/vbscript', mode: 'vbscript'}, - {name: 'Velocity', mime: 'text/velocity', mode: 'velocity'}, - {name: 'Verilog', mime: 'text/x-verilog', mode: 'verilog'}, - {name: 'XML', mime: 'application/xml', mode: 'xml'}, - {name: 'XQuery', mime: 'application/xquery', mode: 'xquery'}, - {name: 'YAML', mime: 'text/x-yaml', mode: 'yaml'}, - {name: 'Z80', mime: 'text/x-z80', mode: 'z80'} + {name: "APL", mime: "text/apl", mode: "apl"}, + {name: "Asterisk", mime: "text/x-asterisk", mode: "asterisk"}, + {name: "C", mime: "text/x-csrc", mode: "clike"}, + {name: "C++", mime: "text/x-c++src", mode: "clike"}, + {name: "Cobol", mime: "text/x-cobol", mode: "cobol"}, + {name: "Java", mime: "text/x-java", mode: "clike"}, + {name: "C#", mime: "text/x-csharp", mode: "clike"}, + {name: "Scala", mime: "text/x-scala", mode: "clike"}, + {name: "Clojure", mime: "text/x-clojure", mode: "clojure"}, + {name: "CoffeeScript", mime: "text/x-coffeescript", mode: "coffeescript"}, + {name: "Common Lisp", mime: "text/x-common-lisp", mode: "commonlisp"}, + {name: "Cypher", mime: "application/x-cypher-query", mode: "cypher"}, + {name: "CSS", mime: "text/css", mode: "css"}, + {name: "D", mime: "text/x-d", mode: "d"}, + {name: "diff", mime: "text/x-diff", mode: "diff"}, + {name: "DTD", mime: "application/xml-dtd", mode: "dtd"}, + {name: "Dylan", mime: "text/x-dylan", mode: "dylan"}, + {name: "ECL", mime: "text/x-ecl", mode: "ecl"}, + {name: "Eiffel", mime: "text/x-eiffel", mode: "eiffel"}, + {name: "Erlang", mime: "text/x-erlang", mode: "erlang"}, + {name: "Fortran", mime: "text/x-fortran", mode: "fortran"}, + {name: "F#", mime: "text/x-fsharp", mode: "mllike"}, + {name: "Gas", mime: "text/x-gas", mode: "gas"}, + {name: "Gherkin", mime: "text/x-feature", mode: "gherkin"}, + {name: "GitHub Flavored Markdown", mime: "text/x-gfm", mode: "gfm"}, + {name: "Go", mime: "text/x-go", mode: "go"}, + {name: "Groovy", mime: "text/x-groovy", mode: "groovy"}, + {name: "HAML", mime: "text/x-haml", mode: "haml"}, + {name: "Haskell", mime: "text/x-haskell", mode: "haskell"}, + {name: "Haxe", mime: "text/x-haxe", mode: "haxe"}, + {name: "ASP.NET", mime: "application/x-aspx", mode: "htmlembedded"}, + {name: "Embedded Javascript", mime: "application/x-ejs", mode: "htmlembedded"}, + {name: "JavaServer Pages", mime: "application/x-jsp", mode: "htmlembedded"}, + {name: "HTML", mime: "text/html", mode: "htmlmixed"}, + {name: "HTTP", mime: "message/http", mode: "http"}, + {name: "Jade", mime: "text/x-jade", mode: "jade"}, + {name: "JavaScript", mime: "text/javascript", mode: "javascript"}, + {name: "JavaScript", mime: "application/javascript", mode: "javascript"}, + {name: "JSON", mime: "application/x-json", mode: "javascript"}, + {name: "JSON", mime: "application/json", mode: "javascript"}, + {name: "JSON-LD", mime: "application/ld+json", mode: "javascript"}, + {name: "TypeScript", mime: "application/typescript", mode: "javascript"}, + {name: "Jinja2", mime: null, mode: "jinja2"}, + {name: "Julia", mime: "text/x-julia", mode: "julia"}, + {name: "Kotlin", mime: "text/x-kotlin", mode: "kotlin"}, + {name: "LESS", mime: "text/x-less", mode: "css"}, + {name: "LiveScript", mime: "text/x-livescript", mode: "livescript"}, + {name: "Lua", mime: "text/x-lua", mode: "lua"}, + {name: "Markdown (GitHub-flavour)", mime: "text/x-markdown", mode: "markdown"}, + {name: "mIRC", mime: "text/mirc", mode: "mirc"}, + {name: "Nginx", mime: "text/x-nginx-conf", mode: "nginx"}, + {name: "NTriples", mime: "text/n-triples", mode: "ntriples"}, + {name: "OCaml", mime: "text/x-ocaml", mode: "mllike"}, + {name: "Octave", mime: "text/x-octave", mode: "octave"}, + {name: "Pascal", mime: "text/x-pascal", mode: "pascal"}, + {name: "PEG.js", mime: null, mode: "pegjs"}, + {name: "Perl", mime: "text/x-perl", mode: "perl"}, + {name: "PHP", mime: "text/x-php", mode: "php"}, + {name: "PHP(HTML)", mime: "application/x-httpd-php", mode: "php"}, + {name: "Pig", mime: "text/x-pig", mode: "pig"}, + {name: "Plain Text", mime: "text/plain", mode: "null"}, + {name: "Properties files", mime: "text/x-properties", mode: "properties"}, + {name: "Python", mime: "text/x-python", mode: "python"}, + {name: "Puppet", mime: "text/x-puppet", mode: "puppet"}, + {name: "Cython", mime: "text/x-cython", mode: "python"}, + {name: "R", mime: "text/x-rsrc", mode: "r"}, + {name: "reStructuredText", mime: "text/x-rst", mode: "rst"}, + {name: "Ruby", mime: "text/x-ruby", mode: "ruby"}, + {name: "Rust", mime: "text/x-rustsrc", mode: "rust"}, + {name: "Sass", mime: "text/x-sass", mode: "sass"}, + {name: "Scheme", mime: "text/x-scheme", mode: "scheme"}, + {name: "SCSS", mime: "text/x-scss", mode: "css"}, + {name: "Shell", mime: "text/x-sh", mode: "shell"}, + {name: "Sieve", mime: "application/sieve", mode: "sieve"}, + {name: "Smalltalk", mime: "text/x-stsrc", mode: "smalltalk"}, + {name: "Smarty", mime: "text/x-smarty", mode: "smarty"}, + {name: "SmartyMixed", mime: "text/x-smarty", mode: "smartymixed"}, + {name: "Solr", mime: "text/x-solr", mode: "solr"}, + {name: "SPARQL", mime: "application/x-sparql-query", mode: "sparql"}, + {name: "SQL", mime: "text/x-sql", mode: "sql"}, + {name: "MariaDB", mime: "text/x-mariadb", mode: "sql"}, + {name: "sTeX", mime: "text/x-stex", mode: "stex"}, + {name: "LaTeX", mime: "text/x-latex", mode: "stex"}, + {name: "SystemVerilog", mime: "text/x-systemverilog", mode: "verilog"}, + {name: "Tcl", mime: "text/x-tcl", mode: "tcl"}, + {name: "TiddlyWiki ", mime: "text/x-tiddlywiki", mode: "tiddlywiki"}, + {name: "Tiki wiki", mime: "text/tiki", mode: "tiki"}, + {name: "TOML", mime: "text/x-toml", mode: "toml"}, + {name: "Turtle", mime: "text/turtle", mode: "turtle"}, + {name: "VB.NET", mime: "text/x-vb", mode: "vb"}, + {name: "VBScript", mime: "text/vbscript", mode: "vbscript"}, + {name: "Velocity", mime: "text/velocity", mode: "velocity"}, + {name: "Verilog", mime: "text/x-verilog", mode: "verilog"}, + {name: "XML", mime: "application/xml", mode: "xml"}, + {name: "XQuery", mime: "application/xquery", mode: "xquery"}, + {name: "YAML", mime: "text/x-yaml", mode: "yaml"}, + {name: "Z80", mime: "text/x-z80", mode: "z80"} ]; }); From b55cc7f5cd0b1128508dda51f525538dd1897f29 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 3 Jul 2014 15:05:42 +0200 Subject: [PATCH 0817/4131] [multi-editor operations] Set up operation grouping Now nested operations from different editors end at the same time --- lib/codemirror.js | 66 ++++++++++++++++++++++++++++++----------------- 1 file changed, 42 insertions(+), 24 deletions(-) diff --git a/lib/codemirror.js b/lib/codemirror.js index 1aee422b42..85cfea9d7b 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -1911,10 +1911,13 @@ // error-prone). Instead, display updates are batched and then all // combined and executed at once. + var operationGroup = null; + var nextOpId = 0; // Start a new operation. function startOperation(cm) { cm.curOp = { + cm: cm, viewChanged: false, // Flag that indicates that lines might need to be redrawn startHeight: cm.doc.height, // Used to detect need to update scrollbar forceUpdate: false, // Used to force a redraw @@ -1928,19 +1931,32 @@ scrollToPos: null, // Used to scroll to a specific position id: ++nextOpId // Unique ID }; - if (!delayedCallbackDepth++) delayedCallbacks = []; + if (operationGroup) { + operationGroup.ops.push(cm.curOp); + } else { + cm.curOp.ownsGroup = operationGroup = { + ops: [cm.curOp], + delayedCallbacks: [] + }; + } } // Finish an operation, updating the display and signalling delayed events function endOperation(cm) { - var op = cm.curOp, doc = cm.doc, display = cm.display; - cm.curOp = null; - var delayed; - if (!--delayedCallbackDepth) { - delayed = delayedCallbacks; - delayedCallbacks = null; - } + var op = cm.curOp, group = op.ownsGroup; + if (!group) return; + + cm.curOp = operationGroup = null; + for (var i = 0; i < group.ops.length; i++) + endOperationInner(group.ops[i]); + + for (var i = 0; i < group.delayedCallbacks.length; ++i) + group.delayedCallbacks[i](); + } + + function endOperationInner(op) { + var cm = op.cm, display = cm.display, doc = cm.doc; if (op.updateMaxLine) findMaxLine(cm); // If it looks like an update might be needed, call updateDisplay @@ -1949,11 +1965,11 @@ op.scrollToPos.to.line >= display.viewTo) || display.maxLineChanged && cm.options.lineWrapping) { var updated = updateDisplay(cm, {top: op.scrollTop, ensure: op.scrollToPos}, op.forceUpdate); - if (cm.display.scroller.offsetHeight) cm.doc.scrollTop = cm.display.scroller.scrollTop; + if (cm.display.scroller.offsetHeight) doc.scrollTop = cm.display.scroller.scrollTop; } // If no update was run, but the selection changed, redraw that. if (!updated && op.selectionChanged) updateSelection(cm); - if (!updated && op.startHeight != cm.doc.height) updateScrollbars(cm); + if (!updated && op.startHeight != doc.height) updateScrollbars(cm); // Abort mouse wheel delta measurement, when scrolling explicitly if (display.wheelStartX != null && (op.scrollTop != null || op.scrollLeft != null || op.scrollToPos)) @@ -1971,8 +1987,8 @@ } // If we need to scroll a specific position into view, do so. if (op.scrollToPos) { - var coords = scrollPosIntoView(cm, clipPos(cm.doc, op.scrollToPos.from), - clipPos(cm.doc, op.scrollToPos.to), op.scrollToPos.margin); + var coords = scrollPosIntoView(cm, clipPos(doc, op.scrollToPos.from), + clipPos(doc, op.scrollToPos.to), op.scrollToPos.margin); if (op.scrollToPos.isCursor && cm.state.focused) maybeScrollWindow(cm, coords); } @@ -1992,7 +2008,6 @@ // Fire change events, and delayed event handlers if (op.changeObjs) signal(cm, "changes", cm, op.changeObjs); - if (delayed) for (var i = 0; i < delayed.length; ++i) delayed[i](); if (op.cursorActivityHandlers) for (var i = 0; i < op.cursorActivityHandlers.length; i++) op.cursorActivityHandlers[i](cm); @@ -6960,6 +6975,8 @@ for (var i = 0; i < arr.length; ++i) arr[i].apply(null, args); }; + var orphanDelayedCallbacks = null; + // Often, we want to signal events at a point where we are in the // middle of some work, but don't want the handler to start calling // other methods on the editor, which might be in an inconsistent @@ -6967,25 +6984,26 @@ // signalLater looks whether there are any handlers, and schedules // them to be executed when the last operation ends, or, if no // operation is active, when a timeout fires. - var delayedCallbacks, delayedCallbackDepth = 0; function signalLater(emitter, type /*, values...*/) { var arr = emitter._handlers && emitter._handlers[type]; if (!arr) return; - var args = Array.prototype.slice.call(arguments, 2); - if (!delayedCallbacks) { - ++delayedCallbackDepth; - delayedCallbacks = []; - setTimeout(fireDelayed, 0); + var args = Array.prototype.slice.call(arguments, 2), list; + if (operationGroup) { + list = operationGroup.delayedCallbacks; + } else if (orphanDelayedCallbacks) { + list = orphanDelayedCallbacks; + } else { + list = orphanDelayedCallbacks = []; + setTimeout(fireOrphanDelayed, 0); } function bnd(f) {return function(){f.apply(null, args);};}; for (var i = 0; i < arr.length; ++i) - delayedCallbacks.push(bnd(arr[i])); + list.push(bnd(arr[i])); } - function fireDelayed() { - --delayedCallbackDepth; - var delayed = delayedCallbacks; - delayedCallbacks = null; + function fireOrphanDelayed() { + var delayed = orphanDelayedCallbacks; + orphanDelayedCallbacks = null; for (var i = 0; i < delayed.length; ++i) delayed[i](); } From 0bdd5ea0b31aade11c0f2a385cdd720aab90eea4 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 3 Jul 2014 15:32:10 +0200 Subject: [PATCH 0818/4131] [multi-editor operations] Fire delayed events before the operation ends --- lib/codemirror.js | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/lib/codemirror.js b/lib/codemirror.js index 85cfea9d7b..b9c63a226d 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -1925,6 +1925,7 @@ typing: false, // Whether this reset should be careful to leave existing text (for compositing) changeObjs: null, // Accumulated changes, for firing change events cursorActivityHandlers: null, // Set of handlers to fire cursorActivity on + cursorActivityCalled: 0, // Tracks which cursorActivity handlers have been called already selectionChanged: false, // Whether the selection needs to be redrawn updateMaxLine: false, // Set when the widest line needs to be determined anew scrollLeft: null, scrollTop: null, // Intermediate scroll position, not pushed to DOM yet @@ -1941,18 +1942,33 @@ } } + function fireCallbacksForOps(group) { + // Calls delayed callbacks and cursorActivity handlers until no + // new ones appear + var callbacks = group.delayedCallbacks, i = 0; + do { + for (; i < callbacks.length; i++) + callbacks[i](); + for (var j = 0; j < group.ops.length; j++) { + var op = group.ops[j]; + if (op.cursorActivityHandlers) + while (op.cursorActivityCalled < op.cursorActivityHandlers.length) + op.cursorActivityHandlers[op.cursorActivityCalled++](op.cm); + } + } while (i < callbacks.length); + } + // Finish an operation, updating the display and signalling delayed events function endOperation(cm) { var op = cm.curOp, group = op.ownsGroup; if (!group) return; - cm.curOp = operationGroup = null; - - for (var i = 0; i < group.ops.length; i++) - endOperationInner(group.ops[i]); - - for (var i = 0; i < group.delayedCallbacks.length; ++i) - group.delayedCallbacks[i](); + try { fireCallbacksForOps(group); } + finally { + cm.curOp = operationGroup = null; + for (var i = 0; i < group.ops.length; i++) + endOperationInner(group.ops[i]); + } } function endOperationInner(op) { @@ -2008,9 +2024,6 @@ // Fire change events, and delayed event handlers if (op.changeObjs) signal(cm, "changes", cm, op.changeObjs); - if (op.cursorActivityHandlers) - for (var i = 0; i < op.cursorActivityHandlers.length; i++) - op.cursorActivityHandlers[i](cm); } // Run the given function in an operation From 55e1ed94dc83539dcecc4abb56935c3b411da557 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 3 Jul 2014 15:54:08 +0200 Subject: [PATCH 0819/4131] Run operations cautiously again in highlightWorker --- lib/codemirror.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/codemirror.js b/lib/codemirror.js index b9c63a226d..089a3e9f3b 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -1408,8 +1408,8 @@ if (doc.frontier >= cm.display.viewTo) return; var end = +new Date + cm.options.workTime; var state = copyState(doc.mode, getStateBefore(cm, doc.frontier)); + var changedLines = []; - runInOp(cm, function() { doc.iter(doc.frontier, Math.min(doc.first + doc.size, cm.display.viewTo + 500), function(line) { if (doc.frontier >= cm.display.viewFrom) { // Visible var oldStyles = line.styles; @@ -1421,7 +1421,7 @@ var ischange = !oldStyles || oldStyles.length != line.styles.length || oldCls != newCls && (!oldCls || !newCls || oldCls.bgClass != newCls.bgClass || oldCls.textClass != newCls.textClass); for (var i = 0; !ischange && i < oldStyles.length; ++i) ischange = oldStyles[i] != line.styles[i]; - if (ischange) regLineChange(cm, doc.frontier, "text"); + if (ischange) changedLines.push(doc.frontier); line.stateAfter = copyState(doc.mode, state); } else { processLine(cm, line.text, state); @@ -1433,6 +1433,9 @@ return true; } }); + if (changedLines.length) runInOp(cm, function() { + for (var i = 0; i < changedLines.length; i++) + regLineChange(cm, changedLines[i], "text"); }); } From 24920fb8a247a6079bc41d92af08f64cfe82b4b9 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 3 Jul 2014 15:55:22 +0200 Subject: [PATCH 0820/4131] Don't wrap onKeyUp in an operation It doesn't need it --- lib/codemirror.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/codemirror.js b/lib/codemirror.js index 089a3e9f3b..b2e194273f 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -2452,7 +2452,7 @@ // Prevent wrapper from ever scrolling on(d.wrapper, "scroll", function() { d.wrapper.scrollTop = d.wrapper.scrollLeft = 0; }); - on(d.input, "keyup", operation(cm, onKeyUp)); + on(d.input, "keyup", function(e) { onKeyUp.call(cm, e); }); on(d.input, "input", function() { if (ie && ie_version >= 9 && cm.display.inputHasSelection) cm.display.inputHasSelection = null; fastPoll(cm); @@ -3145,8 +3145,8 @@ } function onKeyUp(e) { - if (signalDOMEvent(this, e)) return; if (e.keyCode == 16) this.doc.sel.shift = false; + signalDOMEvent(this, e); } function onKeyPress(e) { @@ -4164,7 +4164,7 @@ triggerOnKeyDown: methodOp(onKeyDown), triggerOnKeyPress: methodOp(onKeyPress), - triggerOnKeyUp: methodOp(onKeyUp), + triggerOnKeyUp: onKeyUp, execCommand: function(cmd) { if (commands.hasOwnProperty(cmd)) From e72560be12964597656fdf05d775893c46b81b14 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 3 Jul 2014 18:03:27 +0200 Subject: [PATCH 0821/4131] [multi-editor operations] Split actions at op end into steps, call in order --- lib/codemirror.js | 295 ++++++++++++++++++++++++++++------------------ 1 file changed, 181 insertions(+), 114 deletions(-) diff --git a/lib/codemirror.js b/lib/codemirror.js index b2e194273f..1bf02d2089 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -108,6 +108,7 @@ for (var opt in optionHandlers) if (optionHandlers.hasOwnProperty(opt)) optionHandlers[opt](cm, options[opt], Init); + maybeUpdateLineNumberWidth(cm); for (var i = 0; i < initHooks.length; ++i) initHooks[i](cm); }); } @@ -467,18 +468,18 @@ } // Compute the lines that are visible in a given viewport (defaults - // the the current scroll position). viewPort may contain top, + // the the current scroll position). viewport may contain top, // height, and ensure (see op.scrollToPos) properties. - function visibleLines(display, doc, viewPort) { - var top = viewPort && viewPort.top != null ? Math.max(0, viewPort.top) : display.scroller.scrollTop; + function visibleLines(display, doc, viewport) { + var top = viewport && viewport.top != null ? Math.max(0, viewport.top) : display.scroller.scrollTop; top = Math.floor(top - paddingTop(display)); - var bottom = viewPort && viewPort.bottom != null ? viewPort.bottom : top + display.wrapper.clientHeight; + var bottom = viewport && viewport.bottom != null ? viewport.bottom : top + display.wrapper.clientHeight; var from = lineAtHeight(doc, top), to = lineAtHeight(doc, bottom); // Ensure is a {from: {line, ch}, to: {line, ch}} object, and // forces those lines into the viewport (if possible). - if (viewPort && viewPort.ensure) { - var ensureFrom = viewPort.ensure.from.line, ensureTo = viewPort.ensure.to.line; + if (viewport && viewport.ensure) { + var ensureFrom = viewport.ensure.from.line, ensureTo = viewport.ensure.to.line; if (ensureFrom < from) return {from: ensureFrom, to: lineAtHeight(doc, heightAtLine(getLine(doc, ensureFrom)) + display.wrapper.clientHeight)}; @@ -543,83 +544,46 @@ // DISPLAY DRAWING - // Updates the display, selection, and scrollbars, using the - // information in display.view to find out which nodes are no longer - // up-to-date. Tries to bail out early when no changes are needed, - // unless forced is true. - // Returns true if an actual update happened, false otherwise. - function updateDisplay(cm, viewPort, forced) { - var oldFrom = cm.display.viewFrom, oldTo = cm.display.viewTo, updated; - var visible = visibleLines(cm.display, cm.doc, viewPort); - for (var first = true;; first = false) { - var oldWidth = cm.display.scroller.clientWidth; - if (!updateDisplayInner(cm, visible, forced)) break; - updated = true; - - // If the max line changed since it was last measured, measure it, - // and ensure the document's width matches it. - if (cm.display.maxLineChanged && !cm.options.lineWrapping) - adjustContentWidth(cm); - - var barMeasure = measureForScrollbars(cm); - updateSelection(cm); - setDocumentHeight(cm, barMeasure); - updateScrollbars(cm, barMeasure); - if (webkit && cm.options.lineWrapping) - checkForWebkitWidthBug(cm, barMeasure); // (Issue #2420) - if (webkit && barMeasure.scrollWidth > barMeasure.clientWidth && - barMeasure.scrollWidth < barMeasure.clientWidth + 1 && - !hScrollbarTakesSpace(cm)) - updateScrollbars(cm); // (Issue #2562) - if (first && cm.options.lineWrapping && oldWidth != cm.display.scroller.clientWidth) { - forced = true; - continue; - } - forced = false; - - // Clip forced viewport to actual scrollable area. - if (viewPort && viewPort.top != null) - viewPort = {top: Math.min(barMeasure.docHeight - scrollerCutOff - barMeasure.clientHeight, viewPort.top)}; - // Updated line heights might result in the drawn area not - // actually covering the viewport. Keep looping until it does. - visible = visibleLines(cm.display, cm.doc, viewPort); - if (visible.from >= cm.display.viewFrom && visible.to <= cm.display.viewTo) - break; - } + function DisplayUpdate(cm, viewport, force) { + var display = cm.display; - cm.display.updateLineNumbers = null; - if (updated) { - signalLater(cm, "update", cm); - if (cm.display.viewFrom != oldFrom || cm.display.viewTo != oldTo) - signalLater(cm, "viewportChange", cm, cm.display.viewFrom, cm.display.viewTo); - } - return updated; + this.viewport = viewport; + // Store some values that we'll need later (but don't want to force a relayout for) + this.visible = visibleLines(display, cm.doc, viewport); + this.editorIsHidden = !display.wrapper.offsetWidth; + this.wrapperHeight = display.wrapper.clientHeight; + this.oldViewFrom = display.viewFrom; this.oldViewTo = display.viewTo; + this.oldScrollerWidth = display.scroller.clientWidth; + this.force = force; + this.dims = getDimensions(cm); } // Does the actual updating of the line display. Bails out // (returning false) when there is nothing to be done and forced is // false. - function updateDisplayInner(cm, visible, forced) { + function updateDisplayIfNeeded(cm, update) { var display = cm.display, doc = cm.doc; - if (!display.wrapper.offsetWidth) { + if (update.editorIsHidden) { resetView(cm); - return; + return false; } // Bail out if the visible area is already rendered and nothing changed. - if (!forced && visible.from >= display.viewFrom && visible.to <= display.viewTo && + if (!update.force && + update.visible.from >= display.viewFrom && update.visible.to <= display.viewTo && (display.updateLineNumbers == null || display.updateLineNumbers >= display.viewTo) && countDirtyView(cm) == 0) - return; + return false; - if (maybeUpdateLineNumberWidth(cm)) + if (maybeUpdateLineNumberWidth(cm)) { resetView(cm); - var dims = getDimensions(cm); + update.dims = getDimensions(cm); + } // Compute a suitable new viewport (from & to) var end = doc.first + doc.size; - var from = Math.max(visible.from - cm.options.viewportMargin, doc.first); - var to = Math.min(end, visible.to + cm.options.viewportMargin); + var from = Math.max(update.visible.from - cm.options.viewportMargin, doc.first); + var to = Math.min(end, update.visible.to + cm.options.viewportMargin); if (display.viewFrom < from && from - display.viewFrom < 20) from = Math.max(doc.first, display.viewFrom); if (display.viewTo > to && display.viewTo - to < 20) to = Math.min(end, display.viewTo); if (sawCollapsedSpans) { @@ -628,7 +592,7 @@ } var different = from != display.viewFrom || to != display.viewTo || - display.lastSizeC != display.wrapper.clientHeight; + display.lastSizeC != update.wrapperHeight; adjustView(cm, from, to); display.viewOffset = heightAtLine(getLine(cm.doc, display.viewFrom)); @@ -636,13 +600,15 @@ cm.display.mover.style.top = display.viewOffset + "px"; var toUpdate = countDirtyView(cm); - if (!different && toUpdate == 0 && !forced) return; + if (!different && toUpdate == 0 && !update.force && + (display.updateLineNumbers == null || display.updateLineNumbers >= display.viewTo)) + return false; // For big changes, we hide the enclosing element during the // update, since that speeds up the operations on most browsers. var focused = activeElt(); if (toUpdate > 4) display.lineDiv.style.display = "none"; - patchDisplay(cm, display.updateLineNumbers, dims); + patchDisplay(cm, display.updateLineNumbers, update.dims); if (toUpdate > 4) display.lineDiv.style.display = ""; // There might have been a widget with a focused element that got // hidden or updated, if so re-focus it. @@ -654,24 +620,50 @@ removeChildren(display.selectionDiv); if (different) { - display.lastSizeC = display.wrapper.clientHeight; + display.lastSizeC = update.wrapperHeight; startWorker(cm, 400); } - updateHeightsInViewport(cm); + display.updateLineNumbers = null; return true; } - function adjustContentWidth(cm) { - var display = cm.display; - var width = measureChar(cm, display.maxLine, display.maxLine.text.length).left; - display.maxLineChanged = false; - var minWidth = Math.max(0, width + 3); - var maxScrollLeft = Math.max(0, display.sizer.offsetLeft + minWidth + scrollerCutOff - display.scroller.clientWidth); - display.sizer.style.minWidth = minWidth + "px"; - if (maxScrollLeft < cm.doc.scrollLeft) - setScrollLeft(cm, Math.min(display.scroller.scrollLeft, maxScrollLeft), true); + function postUpdateDisplay(cm, update) { + var force = update.force, viewport = update.viewport; + for (var first = true;; first = false) { + updateHeightsInViewport(cm); + if (first && cm.options.lineWrapping && update.oldScrollerWidth != cm.display.scroller.clientWidth) { + force = true; + } else { + force = false; + // Clip forced viewport to actual scrollable area. + if (viewport && viewport.top != null) + viewport = {top: Math.min(cm.doc.height + paddingVert(cm.display) - scrollerCutOff - + cm.display.scroller.clientHeight, viewport.top)}; + // Updated line heights might result in the drawn area not + // actually covering the viewport. Keep looping until it does. + var visible = visibleLines(cm.display, cm.doc, viewport); + if (visible.from >= cm.display.viewFrom && visible.to <= cm.display.viewTo) + break; + } + if (!updateDisplayIfNeeded(cm, update)) break; + } + + signalLater(cm, "update", cm); + if (cm.display.viewFrom != update.oldViewFrom || cm.display.viewTo != update.oldViewTo) + signalLater(cm, "viewportChange", cm, cm.display.viewFrom, cm.display.viewTo); + } + + function updateDisplaySimple(cm, viewport) { + var update = new DisplayUpdate(cm, viewport); + if (updateDisplayIfNeeded(cm, update)) { + postUpdateDisplay(cm, update); + var barMeasure = measureForScrollbars(cm); + updateSelection(cm); + setDocumentHeight(cm, barMeasure); + updateScrollbars(cm, barMeasure); + } } function setDocumentHeight(cm, measure) { @@ -1257,10 +1249,10 @@ // SELECTION DRAWING // Redraw the selection and/or cursor - function updateSelection(cm) { - var display = cm.display, doc = cm.doc; - var curFragment = document.createDocumentFragment(); - var selFragment = document.createDocumentFragment(); + function drawSelection(cm) { + var display = cm.display, doc = cm.doc, result = {}; + var curFragment = result.cursors = document.createDocumentFragment(); + var selFragment = result.selection = document.createDocumentFragment(); for (var i = 0; i < doc.sel.ranges.length; i++) { var range = doc.sel.ranges[i]; @@ -1275,16 +1267,23 @@ if (cm.options.moveInputWithCursor) { var headPos = cursorCoords(cm, doc.sel.primary().head, "div"); var wrapOff = display.wrapper.getBoundingClientRect(), lineOff = display.lineDiv.getBoundingClientRect(); - var top = Math.max(0, Math.min(display.wrapper.clientHeight - 10, - headPos.top + lineOff.top - wrapOff.top)); - var left = Math.max(0, Math.min(display.wrapper.clientWidth - 10, - headPos.left + lineOff.left - wrapOff.left)); - display.inputDiv.style.top = top + "px"; - display.inputDiv.style.left = left + "px"; + result.teTop = Math.max(0, Math.min(display.wrapper.clientHeight - 10, + headPos.top + lineOff.top - wrapOff.top)); + result.teLeft = Math.max(0, Math.min(display.wrapper.clientWidth - 10, + headPos.left + lineOff.left - wrapOff.left)); } - removeChildrenAndAdd(display.cursorDiv, curFragment); - removeChildrenAndAdd(display.selectionDiv, selFragment); + return result; + } + + function updateSelection(cm, drawn) { + if (!drawn) drawn = drawSelection(cm); + removeChildrenAndAdd(cm.display.cursorDiv, drawn.cursors); + removeChildrenAndAdd(cm.display.selectionDiv, drawn.selection); + if (drawn.teTop != null) { + cm.display.inputDiv.style.top = drawn.teTop + "px"; + cm.display.inputDiv.style.left = drawn.teLeft + "px"; + } } // Draws a cursor for the given range @@ -1967,28 +1966,88 @@ if (!group) return; try { fireCallbacksForOps(group); } - finally { - cm.curOp = operationGroup = null; + finally { + operationGroup = null; for (var i = 0; i < group.ops.length; i++) - endOperationInner(group.ops[i]); + group.ops[i].cm.curOp = null; + endOperations(group); } } - function endOperationInner(op) { - var cm = op.cm, display = cm.display, doc = cm.doc; + // The DOM updates done when an operation finishes are batched so + // that the minimum number of relayouts are required. + function endOperations(group) { + var ops = group.ops; + for (var i = 0; i < ops.length; i++) // Read DOM + endOperation_R1(ops[i]); + for (var i = 0; i < ops.length; i++) // Write DOM (maybe) + endOperation_W1(ops[i]); + for (var i = 0; i < ops.length; i++) // Read DOM + endOperation_R2(ops[i]); + for (var i = 0; i < ops.length; i++) // Write DOM (maybe) + endOperation_W2(ops[i]); + for (var i = 0; i < ops.length; i++) // Read DOM + endOperation_finish(ops[i]); + } + + function endOperation_R1(op) { + var cm = op.cm, display = cm.display; if (op.updateMaxLine) findMaxLine(cm); - // If it looks like an update might be needed, call updateDisplay - if (op.viewChanged || op.forceUpdate || op.scrollTop != null || - op.scrollToPos && (op.scrollToPos.from.line < display.viewFrom || - op.scrollToPos.to.line >= display.viewTo) || - display.maxLineChanged && cm.options.lineWrapping) { - var updated = updateDisplay(cm, {top: op.scrollTop, ensure: op.scrollToPos}, op.forceUpdate); - if (cm.display.scroller.offsetHeight) doc.scrollTop = cm.display.scroller.scrollTop; + op.mustUpdate = op.viewChanged || op.forceUpdate || op.scrollTop != null || + op.scrollToPos && (op.scrollToPos.from.line < display.viewFrom || + op.scrollToPos.to.line >= display.viewTo) || + display.maxLineChanged && cm.options.lineWrapping; + op.update = op.mustUpdate && + new DisplayUpdate(cm, op.mustUpdate && {top: op.scrollTop, ensure: op.scrollToPos}, op.forceUpdate); + } + + function endOperation_W1(op) { + op.updatedDisplay = op.mustUpdate && updateDisplayIfNeeded(op.cm, op.update); + } + + function endOperation_R2(op) { + var cm = op.cm, display = cm.display; + if (op.updatedDisplay) postUpdateDisplay(cm, op.update); + + // If the max line changed since it was last measured, measure it, + // and ensure the document's width matches it. + // updateDisplayIfNeeded will use these properties to do the actual resizing + if (display.maxLineChanged && !cm.options.lineWrapping) { + op.adjustWidthTo = measureChar(cm, display.maxLine, display.maxLine.text.length).left; + op.maxScrollLeft = Math.max(0, display.sizer.offsetLeft + op.adjustWidthTo + + scrollerCutOff - display.scroller.clientWidth); } - // If no update was run, but the selection changed, redraw that. - if (!updated && op.selectionChanged) updateSelection(cm); - if (!updated && op.startHeight != doc.height) updateScrollbars(cm); + + op.barMeasure = measureForScrollbars(cm); + if (op.updatedDisplay || op.selectionChanged) + op.newSelectionNodes = drawSelection(cm); + } + + function endOperation_W2(op) { + var cm = op.cm; + + if (op.adjustWidthTo != null) { + cm.display.sizer.style.minWidth = op.adjustWidthTo + "px"; + if (op.maxScrollLeft < cm.doc.scrollLeft) + setScrollLeft(cm, Math.min(cm.display.scroller.scrollLeft, op.maxScrollLeft), true); + } + + if (op.newSelectionNodes) + updateSelection(cm, op.newSelectionNodes); + if (op.updatedDisplay) + setDocumentHeight(cm, op.barMeasure); + if (op.updatedDisplay || op.startHeight != cm.doc.height) + updateScrollbars(cm, op.barMeasure); + + if (op.selectionChanged) restartBlink(cm); + + if (cm.state.focused && op.updateInput) + resetInput(cm, op.typing); + } + + function endOperation_finish(op) { + var cm = op.cm, display = cm.display, doc = cm.doc; // Abort mouse wheel delta measurement, when scrolling explicitly if (display.wheelStartX != null && (op.scrollTop != null || op.scrollLeft != null || op.scrollToPos)) @@ -2011,11 +2070,6 @@ if (op.scrollToPos.isCursor && cm.state.focused) maybeScrollWindow(cm, coords); } - if (op.selectionChanged) restartBlink(cm); - - if (cm.state.focused && op.updateInput) - resetInput(cm, op.typing); - // Fire events for markers that are hidden/unidden by editing or // undoing var hidden = op.maybeHiddenMarkers, unhidden = op.maybeUnhiddenMarkers; @@ -2024,6 +2078,19 @@ if (unhidden) for (var i = 0; i < unhidden.length; ++i) if (unhidden[i].lines.length) signal(unhidden[i], "unhide"); + if (display.wrapper.offsetHeight) + doc.scrollTop = cm.display.scroller.scrollTop; + + // Apply workaround for two webkit bugs + if (op.updatedDisplay && webkit) { + if (cm.options.lineWrapping) + checkForWebkitWidthBug(cm, op.barMeasure); // (Issue #2420) + if (op.barMeasure.scrollWidth > op.barMeasure.clientWidth && + op.barMeasure.scrollWidth < op.barMeasure.clientWidth + 1 && + !hScrollbarTakesSpace(cm)) + updateScrollbars(cm); // (Issue #2562) + } + // Fire change events, and delayed event handlers if (op.changeObjs) signal(cm, "changes", cm, op.changeObjs); @@ -2916,10 +2983,10 @@ function setScrollTop(cm, val) { if (Math.abs(cm.doc.scrollTop - val) < 2) return; cm.doc.scrollTop = val; - if (!gecko) updateDisplay(cm, {top: val}); + if (!gecko) updateDisplaySimple(cm, {top: val}); if (cm.display.scroller.scrollTop != val) cm.display.scroller.scrollTop = val; if (cm.display.scrollbarV.scrollTop != val) cm.display.scrollbarV.scrollTop = val; - if (gecko) updateDisplay(cm); + if (gecko) updateDisplaySimple(cm); startWorker(cm, 100); } // Sync scroller and scrollbar, ensure the gutter elements are @@ -3002,7 +3069,7 @@ var top = cm.doc.scrollTop, bot = top + display.wrapper.clientHeight; if (pixels < 0) top = Math.max(0, top + pixels - 50); else bot = Math.min(cm.doc.height, bot + pixels + 50); - updateDisplay(cm, {top: top, bottom: bot}); + updateDisplaySimple(cm, {top: top, bottom: bot}); } if (wheelSamples < 20) { From c698ab758b4682c2aca55135c9948735dd75a05f Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Fri, 4 Jul 2014 12:26:41 +0200 Subject: [PATCH 0822/4131] [multi-editor operations] Add a few tests --- test/test.js | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/test/test.js b/test/test.js index 4ef4ef547d..dcfffb7c07 100644 --- a/test/test.js +++ b/test/test.js @@ -1988,3 +1988,38 @@ testCM("resizeLineWidget", function(cm) { cm.setSize(40); is(widget.parentNode.offsetWidth < 42); }); + +testCM("combinedOperations", function(cm) { + var place = document.getElementById("testground"); + var other = CodeMirror(place, {value: "123"}); + try { + cm.operation(function() { + cm.addLineClass(0, "wrap", "foo"); + other.addLineClass(0, "wrap", "foo"); + }); + eq(byClassName(cm.getWrapperElement(), "foo").length, 1); + eq(byClassName(other.getWrapperElement(), "foo").length, 1); + cm.operation(function() { + cm.removeLineClass(0, "wrap", "foo"); + other.removeLineClass(0, "wrap", "foo"); + }); + eq(byClassName(cm.getWrapperElement(), "foo").length, 0); + eq(byClassName(other.getWrapperElement(), "foo").length, 0); + } finally { + place.removeChild(other.getWrapperElement()); + } +}, {value: "abc"}); + +testCM("eventOrder", function(cm) { + var seen = []; + cm.on("change", function() { + if (!seen.length) cm.replaceSelection("."); + seen.push("change"); + }); + cm.on("cursorActivity", function() { + cm.replaceSelection("!"); + seen.push("activity"); + }); + cm.replaceSelection("/"); + eq(seen.join(","), "change,change,activity,change"); +}); From 63591907b0dcd51c2f64dc967143e044ecac6923 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 7 Jul 2014 14:30:27 +0200 Subject: [PATCH 0823/4131] Work around IE10- client rect + zoom issue Issue #2665 --- lib/codemirror.js | 24 ++++++++++++++++++++++++ test/lint/lint.js | 2 +- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/lib/codemirror.js b/lib/codemirror.js index 1bf02d2089..cc7caace19 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -1667,6 +1667,8 @@ rect = nullRect; } + if (ie && ie_version < 11) rect = maybeUpdateRectForZooming(cm.display.measure, rect); + var rtop = rect.top - prepared.rect.top, rbot = rect.bottom - prepared.rect.top; var mid = (rtop + rbot) / 2; var heights = prepared.view.measure.heights; @@ -1678,9 +1680,22 @@ top: top, bottom: bot}; if (!rect.left && !rect.right) result.bogus = true; if (!cm.options.singleCursorHeightPerLine) { result.rtop = rtop; result.rbottom = rbot; } + return result; } + // Work around problem with bounding client rects on ranges being + // returned incorrectly when zoomed on IE10 and below. + function maybeUpdateRectForZooming(measure, rect) { + if (!window.screen || screen.logicalXDPI == null || + screen.logicalXDPI == screen.deviceXDPI || !hasBadZoomedRects(measure)) + return rect; + var scaleX = screen.logicalXDPI / screen.deviceXDPI; + var scaleY = screen.logicalYDPI / screen.deviceYDPI; + return {left: rect.left * scaleX, right: rect.right * scaleX, + top: rect.top * scaleY, bottom: rect.bottom * scaleY}; + } + function clearLineMeasurementCacheFor(lineView) { if (lineView.measure) { lineView.measure.cache = {}; @@ -7432,6 +7447,15 @@ return typeof e.oncopy == "function"; })(); + var badZoomedRects = null; + function hasBadZoomedRects(measure) { + if (badZoomedRects != null) return badZoomedRects; + var node = removeChildrenAndAdd(measure, elt("span", "x")); + var normal = node.getBoundingClientRect(); + var fromRange = range(node, 0, 1).getBoundingClientRect(); + return badZoomedRects = Math.abs(normal.left - fromRange.left) > 1; + } + // KEY NAMES var keyNames = {3: "Enter", 8: "Backspace", 9: "Tab", 13: "Enter", 16: "Shift", 17: "Ctrl", 18: "Alt", diff --git a/test/lint/lint.js b/test/lint/lint.js index ef4c13bd9a..c2c45262a6 100644 --- a/test/lint/lint.js +++ b/test/lint/lint.js @@ -19,7 +19,7 @@ var topAllowedGlobals = Object.create(null); ("Error RegExp Number String Array Function Object Math Date undefined " + "parseInt parseFloat Infinity NaN isNaN " + "window document navigator prompt alert confirm console " + - "FileReader Worker postMessage importScripts " + + "screen FileReader Worker postMessage importScripts " + "setInterval clearInterval setTimeout clearTimeout " + "CodeMirror " + "test exports require module define") From 57761d076413ad7e49f1e45d94b122dd8dfb2c55 Mon Sep 17 00:00:00 2001 From: Jaydeep Solanki Date: Sat, 5 Jul 2014 06:06:24 +0530 Subject: [PATCH 0824/4131] [ruby mode] Better heuristic for distinguishing division from regexps --- mode/ruby/ruby.js | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/mode/ruby/ruby.js b/mode/ruby/ruby.js index b68ee2912a..d6c9d8796e 100644 --- a/mode/ruby/ruby.js +++ b/mode/ruby/ruby.js @@ -46,9 +46,23 @@ CodeMirror.defineMode("ruby", function(config) { var ch = stream.next(), m; if (ch == "`" || ch == "'" || ch == '"') { return chain(readQuoted(ch, "string", ch == '"' || ch == "`"), stream, state); - } else if (ch == "/" && !stream.eol() && stream.peek() != " ") { - if (stream.eat("=")) return "operator"; - return chain(readQuoted(ch, "string-2", true), stream, state); + } else if (ch == "/") { + var currentIndex = stream.current().length; + if (stream.skipTo("/")) { + var search_till = stream.current().length; + stream.backUp(stream.current().length - currentIndex); + var balance = 0; // balance brackets + while (stream.current().length < search_till) { + var chchr = stream.next(); + if (chchr == "(") balance += 1; + else if (chchr == ")") balance -= 1; + if (balance < 0) break; + } + stream.backUp(stream.current().length - currentIndex); + if (balance == 0) + return chain(readQuoted(ch, "string-2", true), stream, state); + } + return "operator"; } else if (ch == "%") { var style = "string", embed = true; if (stream.eat("s")) style = "atom"; From 347affcf2784dc8ed6e13abba517f7bd4968e715 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 7 Jul 2014 23:22:38 +0200 Subject: [PATCH 0825/4131] Handle altGr in early return from onKeyPress Issue #2671 --- lib/codemirror.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/codemirror.js b/lib/codemirror.js index cc7caace19..dcbacc258b 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -3233,7 +3233,7 @@ function onKeyPress(e) { var cm = this; - if (signalDOMEvent(cm, e) || e.ctrlKey || mac && e.metaKey) return; + if (signalDOMEvent(cm, e) || e.ctrlKey && !e.altKey || mac && e.metaKey) return; var keyCode = e.keyCode, charCode = e.charCode; if (presto && keyCode == lastStoppedKey) {lastStoppedKey = null; e_preventDefault(e); return;} if (((presto && (!e.which || e.which < 10)) || khtml) && handleKeyBinding(cm, e)) return; From 93c846bd2b3190459aed37399a3b5583d578911a Mon Sep 17 00:00:00 2001 From: binny Date: Wed, 2 Jul 2014 00:09:42 +0530 Subject: [PATCH 0826/4131] [vim] reselectSelection for visualBlock --- keymap/vim.js | 78 ++++++++++++++++++++++++++++++++---------------- test/vim_test.js | 24 ++++++++++++--- 2 files changed, 73 insertions(+), 29 deletions(-) diff --git a/keymap/vim.js b/keymap/vim.js index 6ff5edce4c..ab61e17afb 100644 --- a/keymap/vim.js +++ b/keymap/vim.js @@ -1858,6 +1858,8 @@ }, // delete is a javascript keyword. 'delete': function(cm, operatorArgs, vim, curStart, curEnd) { + // Save the '>' mark before cm.replaceRange clears it. + var selectionEnd = vim.visualMode ? vim.marks['>'].find() : null; // 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 && @@ -1876,6 +1878,10 @@ } else { cm.replaceRange('', curStart, curEnd); } + // restore the saved bookmark + if (selectionEnd) { + vim.marks['>'] = cm.setBookmark(selectionEnd); + } if (operatorArgs.linewise) { cm.setCursor(motions.moveToFirstNonWhiteSpaceCharacter(cm)); } else { @@ -2085,7 +2091,6 @@ curStart = cm.getCursor('anchor'); curEnd = cm.getCursor('head'); if (vim.visualLine) { - vim.visualLine = false; if (actionArgs.blockwise) { // This means Ctrl-V pressed in linewise visual vim.visualBlock = true; @@ -2097,8 +2102,8 @@ } else { exitVisualMode(cm); } + vim.visualLine = false; } else if (vim.visualBlock) { - vim.visualBlock = false; if (actionArgs.linewise) { // Shift-V pressed in blockwise visual mode vim.visualLine = true; @@ -2118,6 +2123,7 @@ } 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. @@ -2142,27 +2148,40 @@ : curStart); }, reselectLastSelection: function(cm, _actionArgs, vim) { + var curStart = vim.marks['<'].find(); + var curEnd = vim.marks['>'].find(); var lastSelection = vim.lastSelection; if (lastSelection) { - var curStart = lastSelection.curStartMark.find(); - var curEnd = lastSelection.curEndMark.find(); - cm.setSelection(curStart, curEnd); + // 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) { - updateLastSelection(cm, vim); - var selectionStart = cm.getCursor('anchor'); - var selectionEnd = cm.getCursor('head'); updateMark(cm, vim, '<', cursorIsBefore(selectionStart, selectionEnd) ? selectionStart - : selectionEnd); + : selectionEnd); updateMark(cm, vim, '>', cursorIsBefore(selectionStart, selectionEnd) ? selectionEnd - : selectionStart); + : selectionStart); } + // Last selection is updated now + vim.visualMode = true; if (lastSelection.visualLine) { - vim.visualMode = true; vim.visualLine = true; - } - else { - vim.visualMode = 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" : ""}); } @@ -2552,6 +2571,10 @@ } start++; } + // Update selectionEnd and selectionStart + // after selection crossing + selectionEnd.ch = selections[0].head.ch; + selectionStart.ch = selections[0].anchor.ch; cm.setSelections(selections, primIndex); return selectionStart; } @@ -2586,22 +2609,27 @@ } return [selectionStart, selectionEnd]; } - function updateLastSelection(cm, vim) { - // We need the vim mark '<' to get the selection in case of yank and put - var selectionStart = vim.marks['<'].find() || cm.getCursor('anchor'); - var selectionEnd = vim.marks['>'].find() ||cm.getCursor('head'); - // To accommodate the effect lastPastedText in the last selection + function updateLastSelection(cm, vim, selectionStart, selectionEnd) { + if (!selectionStart || !selectionEnd) { + selectionStart = vim.marks['<'].find() || cm.getCursor('anchor'); + selectionEnd = vim.marks['>'].find() || cm.getCursor('head'); + } + // To accommodate the effect of lastPastedText in the last selection if (vim.lastPastedText) { - selectionEnd = cm.posFromIndex(cm.indexFromPos(selectionStart) + vim.lastPastedText.length-1); + selectionEnd = cm.posFromIndex(cm.indexFromPos(selectionStart) + 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) > -1; // 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(selectionStart), 'curEndMark': cm.setBookmark(selectionEnd), 'visualMode': vim.visualMode, 'visualLine': vim.visualLine}; - if (cursorIsBefore(selectionEnd, selectionStart)) { - vim.lastSelection.curStartMark = cm.setBookmark(selectionEnd); - vim.lastSelection.curEndMark = cm.setBookmark(selectionStart); - } + vim.lastSelection = {'curStartMark': cm.setBookmark(swap ? selectionEnd : selectionStart), + 'curEndMark': cm.setBookmark(swap ? selectionStart : selectionEnd), + 'visualMode': vim.visualMode, + 'visualLine': vim.visualLine, + 'visualBlock': vim.visualBlock}; } function exitVisualMode(cm) { diff --git a/test/vim_test.js b/test/vim_test.js index b09d730d50..1c9e8c3c9a 100644 --- a/test/vim_test.js +++ b/test/vim_test.js @@ -1655,7 +1655,8 @@ testVim('reselect_visual', function(cm, vim, helpers) { eq('123456\n2345\nbar', cm.getValue()); cm.setCursor(0, 0); helpers.doKeys('g', 'v'); - helpers.assertCursorAt(1, 3); + // here the fake cursor is at (1, 3) + helpers.assertCursorAt(2, 0); eqPos(makeCursor(1, 0), cm.getCursor('anchor')); helpers.doKeys('v'); cm.setCursor(2, 0); @@ -1669,17 +1670,32 @@ testVim('reselect_visual', function(cm, vim, helpers) { }, { value: '123456\nfoo\nbar' }); testVim('reselect_visual_line', function(cm, vim, helpers) { helpers.doKeys('l', 'V', 'j', 'j', 'V', 'g', 'v', 'd'); - eq('\nfoo\nand\nbar', cm.getValue()); + eq('foo\nand\nbar', cm.getValue()); cm.setCursor(1, 0); helpers.doKeys('V', 'y', 'j'); helpers.doKeys('V', 'p' , 'g', 'v', 'd'); - eq('\nfoo\nbar', cm.getValue()); + eq('foo\nand', cm.getValue()); }, { value: 'hello\nthis\nis\nfoo\nand\nbar' }); +testVim('reselect_visual_block', function(cm, vim, helpers) { + cm.setCursor(1, 2); + helpers.doKeys('', 'k', 'h', ''); + cm.setCursor(2, 1); + helpers.doKeys('v', 'l', 'g', 'v'); + helpers.assertCursorAt(0, 1); + // Ensure selection is done with visual block mode rather than one + // continuous range. + eq(cm.getSelections().join(''), '23oo') + helpers.doKeys('g', 'v'); + helpers.assertCursorAt(2, 3); + // Ensure selection of deleted range + cm.setCursor(1, 1); + helpers.doKeys('v', '', 'j', 'd', 'g', 'v'); + eq(cm.getSelections().join(''), 'or'); +}, { value: '123456\nfoo\nbar' }); testVim('s_normal', function(cm, vim, helpers) { cm.setCursor(0, 1); helpers.doKeys('s'); helpers.doInsertModeKeys('Esc'); - helpers.assertCursorAt(0, 0); eq('ac', cm.getValue()); }, { value: 'abc'}); testVim('s_visual', function(cm, vim, helpers) { From 238b451301227eb8987a4204fc726e1f1207777f Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Tue, 8 Jul 2014 23:44:59 +0200 Subject: [PATCH 0827/4131] Fix broken double-checking of display coverage Both a potential infinite loop, due to updateDisplayIfNeeded not using the updated set of visibile lines, and the fact that the current check wasn't really covering changing document size, due to it happening before the call to setDocumentHeight Issue #2683 --- lib/codemirror.js | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/lib/codemirror.js b/lib/codemirror.js index dcbacc258b..19abaf50b7 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -632,7 +632,6 @@ function postUpdateDisplay(cm, update) { var force = update.force, viewport = update.viewport; for (var first = true;; first = false) { - updateHeightsInViewport(cm); if (first && cm.options.lineWrapping && update.oldScrollerWidth != cm.display.scroller.clientWidth) { force = true; } else { @@ -643,11 +642,16 @@ cm.display.scroller.clientHeight, viewport.top)}; // Updated line heights might result in the drawn area not // actually covering the viewport. Keep looping until it does. - var visible = visibleLines(cm.display, cm.doc, viewport); - if (visible.from >= cm.display.viewFrom && visible.to <= cm.display.viewTo) + update.visible = visibleLines(cm.display, cm.doc, viewport); + if (update.visible.from >= cm.display.viewFrom && update.visible.to <= cm.display.viewTo) break; } if (!updateDisplayIfNeeded(cm, update)) break; + updateHeightsInViewport(cm); + var barMeasure = measureForScrollbars(cm); + updateSelection(cm); + setDocumentHeight(cm, barMeasure); + updateScrollbars(cm, barMeasure); } signalLater(cm, "update", cm); @@ -2023,7 +2027,7 @@ function endOperation_R2(op) { var cm = op.cm, display = cm.display; - if (op.updatedDisplay) postUpdateDisplay(cm, op.update); + if (op.updatedDisplay) updateHeightsInViewport(cm); // If the max line changed since it was last measured, measure it, // and ensure the document's width matches it. @@ -2064,6 +2068,8 @@ function endOperation_finish(op) { var cm = op.cm, display = cm.display, doc = cm.doc; + if (op.updatedDisplay) postUpdateDisplay(cm, op.update); + // Abort mouse wheel delta measurement, when scrolling explicitly if (display.wheelStartX != null && (op.scrollTop != null || op.scrollLeft != null || op.scrollToPos)) display.wheelStartX = display.wheelStartY = null; From 6c0cd2b56b50837a010bd27f322a57edfbe9fee9 Mon Sep 17 00:00:00 2001 From: Richard van der Meer Date: Tue, 8 Jul 2014 11:51:35 +0200 Subject: [PATCH 0828/4131] [vbscript mode] Fixed "Cannot read property 'substr' of null" Error occurs when entering multiple dots --- mode/vbscript/vbscript.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mode/vbscript/vbscript.js b/mode/vbscript/vbscript.js index bff2594477..b66df2239a 100644 --- a/mode/vbscript/vbscript.js +++ b/mode/vbscript/vbscript.js @@ -291,7 +291,7 @@ CodeMirror.defineMode("vbscript", function(conf, parserConf) { style = state.tokenize(stream, state); current = stream.current(); - if (style.substr(0, 8) === 'variable' || style==='builtin' || style==='keyword'){//|| knownWords.indexOf(current.substring(1)) > -1) { + if (style && (style.substr(0, 8) === 'variable' || style==='builtin' || style==='keyword')){//|| knownWords.indexOf(current.substring(1)) > -1) { if (style === 'builtin' || style === 'keyword') style='variable'; if (knownWords.indexOf(current.substr(1)) > -1) style='variable-2'; From e92998af5dd97c771821f03c223b88442974bc6b Mon Sep 17 00:00:00 2001 From: Yunchi Luo Date: Tue, 8 Jul 2014 20:35:07 -0700 Subject: [PATCH 0829/4131] [vim] Add features list to demo page --- demo/vim.html | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/demo/vim.html b/demo/vim.html index f92ff9e6d8..cc616759f0 100644 --- a/demo/vim.html +++ b/demo/vim.html @@ -45,17 +45,32 @@

    Vim bindings demo

    return (--n >= 0) ? (unsigned char) *bufp++ : EOF; } -
    - -
    +
    Key buffer:

    The vim keybindings are enabled by including keymap/vim.js and setting the vimMode option to true. This will also automatically change the keyMap option to "vim".

    +

    Features

    + +
      +
    • All common motions and operators, including text objects
    • +
    • Operator motion orthogonality
    • +
    • Visual mode - characterwise, linewise, partial support for blockwise
    • +
    • Full macro support (q, @)
    • +
    • Incremental highlighted search (/, ?, #, *, g#, g*)
    • +
    • Search/replace with confirm (:substitute, :%s)
    • +
    • Search history
    • +
    • Jump lists (Ctrl-o, Ctrl-i)
    • +
    • Key/command mapping with API (:map, :nmap, :vmap)
    • +
    • Sort (:sort)
    • +
    • Marks (`, ')
    • +
    • :global
    • +
    • Insert mode behaves identical to base CodeMirror
    • +
    • Cross-buffer yank/paste
    • +
    +

    Note that while the vim mode tries to emulate the most useful features of vim as faithfully as possible, it does not strive to become a complete vim implementation

    @@ -69,13 +84,6 @@

    Vim bindings demo

    matchBrackets: true, showCursorWhenSelecting: true }); - var editor2 = CodeMirror.fromTextArea(document.getElementById("code2"), { - lineNumbers: true, - mode: "text/x-csrc", - vimMode: true, - matchBrackets: true, - showCursorWhenSelecting: true - }); var commandDisplay = document.getElementById('command-display'); var keys = ''; CodeMirror.on(editor, 'vim-keypress', function(key) { From 770c0970cf2e3541ad21ee6fa0c7d78b21b368e0 Mon Sep 17 00:00:00 2001 From: binny Date: Wed, 9 Jul 2014 19:15:58 +0530 Subject: [PATCH 0830/4131] [vim] change for blockwise visual --- keymap/vim.js | 51 ++++++++++++++++++++++++++++++++++++------------ test/vim_test.js | 14 +++++++++++++ 2 files changed, 52 insertions(+), 13 deletions(-) diff --git a/keymap/vim.js b/keymap/vim.js index ab61e17afb..c1b0df4683 100644 --- a/keymap/vim.js +++ b/keymap/vim.js @@ -1831,17 +1831,39 @@ }; var operators = { - change: function(cm, operatorArgs, _vim, curStart, curEnd) { + 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 replacement = new Array(selections.length).join('1').split('1'); vimGlobalState.registerController.pushText( - operatorArgs.registerName, 'change', cm.getRange(curStart, curEnd), + operatorArgs.registerName, 'change', text, operatorArgs.linewise); if (operatorArgs.linewise) { - // Push the next line back down, if there is a next line. - var replacement = curEnd.line > cm.lastLine() ? '' : '\n'; - cm.replaceRange(replacement, curStart, curEnd); - cm.indentLine(curStart.line, 'smart'); - // null ch so setCursor moves to end of line. - curStart.ch = null; + // 'C' in visual block extends the block till eol for all lines + if (vim.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); @@ -1851,15 +1873,20 @@ curEnd = offsetCursor(curEnd, 0, - match[0].length); } } - cm.replaceRange('', curStart, curEnd); + if (vim.visualBlock) { + cm.replaceSelections(replacement); + } else { + cm.setCursor(curStart); + cm.replaceRange('', curStart, curEnd); + } } actions.enterInsertMode(cm, {}, cm.state.vim); - cm.setCursor(curStart); }, // delete is a javascript keyword. 'delete': function(cm, operatorArgs, vim, curStart, curEnd) { // Save the '>' mark before cm.replaceRange clears it. var selectionEnd = vim.visualMode ? vim.marks['>'].find() : null; + var text = cm.getSelection(); // 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 && @@ -1868,7 +1895,7 @@ curStart.ch = lineLength(cm, curStart.line); } vimGlobalState.registerController.pushText( - operatorArgs.registerName, 'delete', cm.getRange(curStart, curEnd), + operatorArgs.registerName, 'delete', text, operatorArgs.linewise); if (vim.visualBlock) { var selections = cm.listSelections(); @@ -1926,8 +1953,6 @@ var curStart = ranges[0].anchor; var curEnd = ranges[0].head; if (!operatorArgs.shouldMoveCursor) { - // extendSelection swaps curStart and curEnd, so make sure - // curStart < curEnd cm.setCursor(cursorIsBefore(curStart, curEnd) ? curStart : curEnd); } }, diff --git a/test/vim_test.js b/test/vim_test.js index 1c9e8c3c9a..76a2699780 100644 --- a/test/vim_test.js +++ b/test/vim_test.js @@ -895,6 +895,20 @@ testVim('cc_append', function(cm, vim, helpers) { helpers.doKeys('c', 'c'); eq(expectedLineCount, cm.lineCount()); }); +testVim('c_visual_block', function(cm, vim, helpers) { + cm.setCursor(0, 1); + helpers.doKeys('', '2', 'j', 'l', 'l', 'l', 'c'); + var replacement = new Array(cm.listSelections().length+1).join('hello ').split(' '); + replacement.pop(); + cm.replaceSelections(replacement); + eq('1hello\n5hello\nahellofg', cm.getValue()); + cm.setCursor(2, 3); + helpers.doKeys('', '2', 'k', 'h', 'C'); + replacement = new Array(cm.listSelections().length+1).join('world ').split(' '); + replacement.pop(); + cm.replaceSelections(replacement); + eq('1hworld\n5hworld\nahworld', cm.getValue()); +}, {value: '1234\n5678\nabcdefg'}); // Swapcase commands edit in place and do not modify registers. testVim('g~w_repeat', function(cm, vim, helpers) { // Assert that dw does delete newline if it should go to the next line, and From 5285494ab15ba444bc95f956c389502796b0bce1 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Fri, 11 Jul 2014 08:51:22 +0200 Subject: [PATCH 0831/4131] Ignore auto indentation beyond column 80 Issue #2688 --- lib/codemirror.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/codemirror.js b/lib/codemirror.js index 19abaf50b7..49fd45a084 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -3812,7 +3812,7 @@ how = "not"; } else if (how == "smart") { indentation = cm.doc.mode.indent(state, line.text.slice(curSpaceString.length), line.text); - if (indentation == Pass) { + if (indentation == Pass || indentation > 80) { if (!aggressive) return; how = "prev"; } From ce7536377698f682eaf3959408c70df665f690cf Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Fri, 11 Jul 2014 08:56:12 +0200 Subject: [PATCH 0832/4131] Bump indentation-ignoring threshold to 150 You might actually want to align things on long lines Issue #2688 --- lib/codemirror.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/codemirror.js b/lib/codemirror.js index 49fd45a084..ad77be2cb9 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -3812,7 +3812,7 @@ how = "not"; } else if (how == "smart") { indentation = cm.doc.mode.indent(state, line.text.slice(curSpaceString.length), line.text); - if (indentation == Pass || indentation > 80) { + if (indentation == Pass || indentation > 150) { if (!aggressive) return; how = "prev"; } From ae978a7e9372f7bae489510c68740741dfe67e05 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Fri, 11 Jul 2014 11:20:31 +0200 Subject: [PATCH 0833/4131] Bind Cmd-Home to goDocStart on Mac Closes #2687 --- doc/manual.html | 2 +- lib/codemirror.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/manual.html b/doc/manual.html index 2deb8422a5..490143e31b 100644 --- a/doc/manual.html +++ b/doc/manual.html @@ -815,7 +815,7 @@

    Commands

    Redo the last change to the selection, or the last text change if no selection changes remain.
    -
    goDocStartCtrl-Up (PC), Cmd-Up (Mac)
    +
    goDocStartCtrl-Up (PC), Cmd-Up (Mac), Cmd-Home (Mac)
    Move the cursor to the start of the document.
    goDocEndCtrl-Down (PC), Cmd-End (Mac), Cmd-Down (Mac)
    diff --git a/lib/codemirror.js b/lib/codemirror.js index ad77be2cb9..bf5d6baa2e 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -4824,7 +4824,7 @@ }; keyMap.macDefault = { "Cmd-A": "selectAll", "Cmd-D": "deleteLine", "Cmd-Z": "undo", "Shift-Cmd-Z": "redo", "Cmd-Y": "redo", - "Cmd-Up": "goDocStart", "Cmd-End": "goDocEnd", "Cmd-Down": "goDocEnd", "Alt-Left": "goGroupLeft", + "Cmd-Home": "goDocStart", "Cmd-Up": "goDocStart", "Cmd-End": "goDocEnd", "Cmd-Down": "goDocEnd", "Alt-Left": "goGroupLeft", "Alt-Right": "goGroupRight", "Cmd-Left": "goLineStart", "Cmd-Right": "goLineEnd", "Alt-Backspace": "delGroupBefore", "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", From 0b3d49f4cfc458d481a21b38d7be44fb48c1b46f Mon Sep 17 00:00:00 2001 From: Tim Alby Date: Thu, 10 Jul 2014 17:31:43 +0100 Subject: [PATCH 0834/4131] Fix key-binding behaviour on Mac in wrap mode Bind Cmd-Left to goLineLeft and Cmd-right to goLineRight instead of goLineStart and goLineEnd Create and bind delVisualLeft and delVisualRight to Cmd-Backspace and Cmd-Delete --- doc/manual.html | 16 +++++++++++----- lib/codemirror.js | 18 ++++++++++++++++-- 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/doc/manual.html b/doc/manual.html index 490143e31b..ed0d076a9f 100644 --- a/doc/manual.html +++ b/doc/manual.html @@ -797,9 +797,15 @@

    Commands

    deleteLineCtrl-D (PC), Cmd-D (Mac)
    Deletes the whole line under the cursor, including newline at the end.
    -
    delLineLeftCmd-Backspace (Mac)
    +
    delLineLeft
    Delete the part of the line before the cursor.
    +
    delWrappedLineLeftCmd-Backspace (Mac)
    +
    Delete the part of the line from the left side of the visual line the cursor is on to the cursor.
    + +
    delWrappedLineRightCmd-Delete (Mac)
    +
    Delete the part of the line from the cursor to the right side of the visual line the cursor is on.
    +
    undoCtrl-Z (PC), Cmd-Z (Mac)
    Undo the last change.
    @@ -821,7 +827,7 @@

    Commands

    goDocEndCtrl-Down (PC), Cmd-End (Mac), Cmd-Down (Mac)
    Move the cursor to the end of the document.
    -
    goLineStartAlt-Left (PC), Cmd-Left (Mac), Ctrl-A (Mac)
    +
    goLineStartAlt-Left (PC), Ctrl-A (Mac)
    Move the cursor to the start of the line.
    goLineStartSmartHome
    @@ -829,14 +835,14 @@

    Commands

    already there, to the actual start of the line (including whitespace). -
    goLineEndAlt-Right (PC), Cmd-Right (Mac), Ctrl-E (Mac)
    +
    goLineEndAlt-Right (PC), Ctrl-E (Mac)
    Move the cursor to the end of the line.
    -
    goLineLeft
    +
    goLineLeftCmd-Left (Mac)
    Move the cursor to the left side of the visual line it is on. If this line is wrapped, that may not be the start of the line.
    -
    goLineRight
    +
    goLineRightCmd-Right (Mac)
    Move the cursor to the right side of the visual line it is on.
    goLineUpUp, Ctrl-P (Mac)
    diff --git a/lib/codemirror.js b/lib/codemirror.js index bf5d6baa2e..3fef17d95e 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -4687,6 +4687,20 @@ return {from: Pos(range.from().line, 0), to: range.from()}; }); }, + delWrappedLineLeft: function(cm) { + deleteNearSelection(cm, function(range) { + var top = cm.charCoords(range.head, "div").top + 5; + var leftPos = cm.coordsChar({left: 0, top: top}, "div"); + return {from: leftPos, to: range.from()}; + }); + }, + delWrappedLineRight: function(cm) { + deleteNearSelection(cm, function(range) { + var top = cm.charCoords(range.head, "div").top + 5; + var rightPos = cm.coordsChar({left: cm.display.lineDiv.offsetWidth + 100, top: top}, "div"); + return {from: range.from(), to: rightPos }; + }); + }, undo: function(cm) {cm.undo();}, redo: function(cm) {cm.redo();}, undoSelection: function(cm) {cm.undoSelection();}, @@ -4825,10 +4839,10 @@ 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", - "Alt-Right": "goGroupRight", "Cmd-Left": "goLineStart", "Cmd-Right": "goLineEnd", "Alt-Backspace": "delGroupBefore", + "Alt-Right": "goGroupRight", "Cmd-Left": "goLineLeft", "Cmd-Right": "goLineRight", "Alt-Backspace": "delGroupBefore", "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": "delLineLeft", + "Cmd-[": "indentLess", "Cmd-]": "indentMore", "Cmd-Backspace": "delWrappedLineLeft", "Cmd-Delete": "delWrappedLineRight", "Cmd-U": "undoSelection", "Shift-Cmd-U": "redoSelection", fallthrough: ["basic", "emacsy"] }; From 0392fd3bb51fe8b2ac0f385ff12e18299900630d Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Fri, 11 Jul 2014 11:55:55 +0200 Subject: [PATCH 0835/4131] Catch and suppress input of certain code point on Mac Ctrl-arrow key presses were, for some reason, inserting such characters into our textarea. Issue #2689 --- lib/codemirror.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/codemirror.js b/lib/codemirror.js index 3fef17d95e..f52f7865c6 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -2388,8 +2388,11 @@ var text = input.value; // If nothing changed, bail. if (text == prevInput && !cm.somethingSelected()) return false; - // Work around nonsensical selection resetting in IE9/10 - if (ie && ie_version >= 9 && cm.display.inputHasSelection === text) { + // Work around nonsensical selection resetting in IE9/10, and + // inexplicable appearance of private area unicode characters on + // some key combos in Mac (#2689). + if (ie && ie_version >= 9 && cm.display.inputHasSelection === text || + mac && /[\uf700-\uf7ff]/.test(text)) { resetInput(cm); return false; } From f02df0b41300a1069ab5e0e3ebae3431b6b507b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roberto=20Abdelkader=20Mart=C3=ADnez=20P=C3=A9rez?= Date: Sun, 6 Jul 2014 04:30:44 +0200 Subject: [PATCH 0836/4131] [lint addon] Do not constrain severity names Issue #2681 --- addon/lint/lint.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/addon/lint/lint.js b/addon/lint/lint.js index 604e2e6058..a87e70c09e 100644 --- a/addon/lint/lint.js +++ b/addon/lint/lint.js @@ -11,7 +11,6 @@ })(function(CodeMirror) { "use strict"; var GUTTER_ID = "CodeMirror-lint-markers"; - var SEVERITIES = /^(?:error|warning)$/; function showTooltip(e, content) { var tt = document.createElement("div"); @@ -110,7 +109,7 @@ function annotationTooltip(ann) { var severity = ann.severity; - if (!SEVERITIES.test(severity)) severity = "error"; + if (!severity) severity = "error"; var tip = document.createElement("div"); tip.className = "CodeMirror-lint-message-" + severity; tip.appendChild(document.createTextNode(ann.message)); @@ -141,7 +140,7 @@ for (var i = 0; i < anns.length; ++i) { var ann = anns[i]; var severity = ann.severity; - if (!SEVERITIES.test(severity)) severity = "error"; + if (!severity) severity = "error"; maxSeverity = getMaxSeverity(maxSeverity, severity); if (options.formatAnnotation) ann = options.formatAnnotation(ann); From 13acf661b6976badca64e69861f054111757084b Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 14 Jul 2014 11:07:30 +0200 Subject: [PATCH 0837/4131] Don't treat %= as the start of a string Closes #2692 --- mode/ruby/ruby.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mode/ruby/ruby.js b/mode/ruby/ruby.js index d6c9d8796e..e7de7b57f1 100644 --- a/mode/ruby/ruby.js +++ b/mode/ruby/ruby.js @@ -69,7 +69,7 @@ CodeMirror.defineMode("ruby", function(config) { else if (stream.eat(/[WQ]/)) style = "string"; else if (stream.eat(/[r]/)) style = "string-2"; else if (stream.eat(/[wxq]/)) { style = "string"; embed = false; } - var delim = stream.eat(/[^\w\s]/); + var delim = stream.eat(/[^\w\s=]/); if (!delim) return "operator"; if (matching.propertyIsEnumerable(delim)) delim = matching[delim]; return chain(readQuoted(delim, style, embed, true), stream, state); From f4ae5b42c929edc78c2df0888ae1b0179098652a Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Tue, 15 Jul 2014 11:13:36 +0200 Subject: [PATCH 0838/4131] Track last copied text, in order to find selection boundaries on paste Issue #2697 --- lib/codemirror.js | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/lib/codemirror.js b/lib/codemirror.js index f52f7865c6..fcaaab28bd 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -2366,6 +2366,11 @@ cm.display.poll.set(20, p); } + // This will be set to an array of strings when copying, so that, + // when pasting, we know what kind of selections the copied text + // was made out of. + var lastCopied = null; + // Read input from the textarea, and update the document to match. // When something is selected, it is present in the textarea, and // selected (unless it is huge, in which case a placeholder is @@ -2409,7 +2414,13 @@ var inserted = text.slice(same), textLines = splitLines(inserted); // When pasing N lines into N selections, insert one line per selection - var multiPaste = cm.state.pasteIncoming && textLines.length > 1 && doc.sel.ranges.length == textLines.length; + var multiPaste = null; + if (cm.state.pasteIncoming && doc.sel.ranges.length > 1) { + if (lastCopied && lastCopied.join("\n") == inserted) + multiPaste = lastCopied.length == doc.sel.ranges.length && map(lastCopied, splitLines); + else if (textLines.length == doc.sel.ranges.length) + multiPaste = map(textLines, function(l) { return [l]; }); + } // Normal behavior is to insert the new text into every selection for (var i = doc.sel.ranges.length - 1; i >= 0; i--) { @@ -2422,7 +2433,7 @@ else if (cm.state.overwrite && range.empty() && !cm.state.pasteIncoming) to = Pos(to.line, Math.min(getLine(doc, to.line).text.length, to.ch + lst(textLines).length)); var updateInput = cm.curOp.updateInput; - var changeEvent = {from: from, to: to, text: multiPaste ? [textLines[i]] : textLines, + var changeEvent = {from: from, to: to, text: multiPaste ? multiPaste[i] : textLines, origin: cm.state.pasteIncoming ? "paste" : cm.state.cutIncoming ? "cut" : "+input"}; makeChange(cm.doc, changeEvent); signalLater(cm, "inputRead", cm, changeEvent); @@ -2589,27 +2600,29 @@ function prepareCopyCut(e) { if (cm.somethingSelected()) { + lastCopied = cm.getSelections(); if (d.inaccurateSelection) { d.prevInput = ""; d.inaccurateSelection = false; - d.input.value = cm.getSelection(); + d.input.value = lastCopied.join("\n"); selectInput(d.input); } } else { - var text = "", ranges = []; + var text = [], ranges = []; for (var i = 0; i < cm.doc.sel.ranges.length; i++) { var line = cm.doc.sel.ranges[i].head.line; var lineRange = {anchor: Pos(line, 0), head: Pos(line + 1, 0)}; ranges.push(lineRange); - text += cm.getRange(lineRange.anchor, lineRange.head); + text.push(cm.getRange(lineRange.anchor, lineRange.head)); } if (e.type == "cut") { cm.setSelections(ranges, null, sel_dontScroll); } else { d.prevInput = ""; - d.input.value = text; + d.input.value = text.join("\n"); selectInput(d.input); } + lastCopied = text; } if (e.type == "cut") cm.state.cutIncoming = true; } From bc87689c02950857049470355f20e8a29eb19639 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Wed, 16 Jul 2014 10:04:41 +0200 Subject: [PATCH 0839/4131] Remove unused extra argument to computeSelAfterChange --- lib/codemirror.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/codemirror.js b/lib/codemirror.js index fcaaab28bd..0aad3fda68 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -3549,7 +3549,7 @@ antiChanges.push(historyChangeFromChange(doc, change)); - var after = i ? computeSelAfterChange(doc, change, null) : lst(source); + var after = i ? computeSelAfterChange(doc, change) : lst(source); makeChangeSingleDoc(doc, change, after, mergeOldSpans(doc, change)); if (!i && doc.cm) doc.cm.scrollIntoView(change); var rebased = []; @@ -3608,7 +3608,7 @@ change.removed = getBetween(doc, change.from, change.to); - if (!selAfter) selAfter = computeSelAfterChange(doc, change, null); + if (!selAfter) selAfter = computeSelAfterChange(doc, change); if (doc.cm) makeChangeSingleDocInEditor(doc.cm, change, spans); else updateDoc(doc, change, spans); setSelectionNoUndo(doc, selAfter, sel_dontScroll); From 59138ec896618d730046fda7002d57eef02bd6a8 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Wed, 16 Jul 2014 12:55:59 +0200 Subject: [PATCH 0840/4131] [javascript mode] Indent properly in case of function arg in wrapped arg list --- mode/javascript/javascript.js | 2 ++ mode/javascript/test.js | 6 ++++++ 2 files changed, 8 insertions(+) diff --git a/mode/javascript/javascript.js b/mode/javascript/javascript.js index 315674be74..fdb066eb1f 100644 --- a/mode/javascript/javascript.js +++ b/mode/javascript/javascript.js @@ -298,6 +298,8 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { var result = function() { var state = cx.state, indent = state.indented; if (state.lexical.type == "stat") indent = state.lexical.indented; + else for (var outer = state.lexical; outer && outer.type == ")" && outer.align; outer = outer.prev) + indent = outer.indented; state.lexical = new JSLexical(indent, cx.stream.column(), type, null, state.lexical, info); }; result.lex = true; diff --git a/mode/javascript/test.js b/mode/javascript/test.js index a9cc993d3d..77cc695fef 100644 --- a/mode/javascript/test.js +++ b/mode/javascript/test.js @@ -128,6 +128,12 @@ " [keyword else]", " [number 3];"); + MT("indent_funarg", + "[variable foo]([number 10000],", + " [keyword function]([def a]) {", + " [keyword debugger];", + "};"); + MT("indent_below_if", "[keyword for] (;;)", " [keyword if] ([variable foo])", From 2fa988d3b46d47a732bdbf6d5ac1f52f49b6a6e0 Mon Sep 17 00:00:00 2001 From: Sander AKA Redsandro Date: Thu, 17 Jul 2014 16:44:50 +0200 Subject: [PATCH 0841/4131] Disable replace for readOnly content Disable the `replace()` when the selected `CodeMirror` is `readOnly`. --- addon/search/search.js | 1 + 1 file changed, 1 insertion(+) diff --git a/addon/search/search.js b/addon/search/search.js index 3ce7cc95d8..b177dce6ed 100644 --- a/addon/search/search.js +++ b/addon/search/search.js @@ -110,6 +110,7 @@ var replacementQueryDialog = 'With: '; var doReplaceConfirm = "Replace? "; function replace(cm, all) { + if (cm.getOption("readOnly")) return; dialog(cm, replaceQueryDialog, "Replace:", cm.getSelection(), function(query) { if (!query) return; query = parseQuery(query); From ddd36cb0b085358e797cd64ff08ed819005b9f60 Mon Sep 17 00:00:00 2001 From: binny Date: Sat, 5 Jul 2014 07:02:00 +0530 Subject: [PATCH 0842/4131] [vim] visual block replace --- keymap/vim.js | 33 ++++++++++++++++++++++----------- test/vim_test.js | 13 +++++++++++++ 2 files changed, 35 insertions(+), 11 deletions(-) diff --git a/keymap/vim.js b/keymap/vim.js index c1b0df4683..b239929f07 100644 --- a/keymap/vim.js +++ b/keymap/vim.js @@ -2370,10 +2370,11 @@ var curStart = cm.getCursor(); var replaceTo; var curEnd; - if (vim.visualMode){ - curStart=cm.getCursor('start'); - curEnd=cm.getCursor('end'); - }else{ + var selections = cm.listSelections(); + if (vim.visualMode) { + curStart = cm.getCursor('start'); + curEnd = cm.getCursor('end'); + } else { var line = cm.getLine(curStart.line); replaceTo = curStart.ch + actionArgs.repeat; if (replaceTo > line.length) { @@ -2381,19 +2382,29 @@ } curEnd = Pos(curStart.line, replaceTo); } - if (replaceWith=='\n'){ + if (replaceWith=='\n') { if (!vim.visualMode) cm.replaceRange('', curStart, curEnd); // special case, where vim help says to replace by just one line-break (CodeMirror.commands.newlineAndIndentContinueComment || CodeMirror.commands.newlineAndIndent)(cm); - }else { - var replaceWithStr=cm.getRange(curStart, curEnd); + } else { + var replaceWithStr = cm.getRange(curStart, curEnd); //replace all characters in range by selected, but keep linebreaks - replaceWithStr=replaceWithStr.replace(/[^\n]/g,replaceWith); - cm.replaceRange(replaceWithStr, curStart, curEnd); - if (vim.visualMode){ + 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(' '); + replaceWithStr = cm.getSelection(); + replaceWithStr = replaceWithStr.replace(/\t/g, spaces).replace(/[^\n]/g, replaceWith).split('\n'); + cm.replaceSelections(replaceWithStr); + } else { + cm.replaceRange(replaceWithStr, curStart, curEnd); + } + if (vim.visualMode) { + curStart = cursorIsBefore(selections[0].anchor, selections[0].head) ? + selections[0].anchor : selections[0].head; cm.setCursor(curStart); exitVisualMode(cm); - }else{ + } else { cm.setCursor(offsetCursor(curEnd, 0, -1)); } } diff --git a/test/vim_test.js b/test/vim_test.js index 76a2699780..342737de52 100644 --- a/test/vim_test.js +++ b/test/vim_test.js @@ -1332,6 +1332,19 @@ testVim('r', function(cm, vim, helpers) { helpers.doKeys('v', 'j', 'h', 'r', ''); eq('wuuu \n her', cm.getValue(),'Replacing selection by space-characters failed'); }, { value: 'wordet\nanother' }); +testVim('r_visual_block', function(cm, vim, helpers) { + cm.setCursor(2, 3); + helpers.doKeys('', 'k', 'k', 'h', 'h', 'r', 'l'); + eq('1lll\n5lll\nalllefg', cm.getValue()); + helpers.doKeys('', 'l', 'j', 'r', ''); + eq('1 l\n5 l\nalllefg', cm.getValue()); + cm.setCursor(2, 0); + helpers.doKeys('o'); + helpers.doInsertModeKeys('Esc'); + cm.replaceRange('\t\t', cm.getCursor()); + helpers.doKeys('', 'h', 'h', 'r', 'r'); + eq('1 l\n5 l\nalllefg\nrrrrrrrr', cm.getValue()); +}, {value: '1234\n5678\nabcdefg'}); testVim('R', function(cm, vim, helpers) { cm.setCursor(0, 1); helpers.doKeys('R'); From bce69920dfdce2b5eeb910bf7a7cff147a3bd5ca Mon Sep 17 00:00:00 2001 From: binny Date: Tue, 15 Jul 2014 05:32:25 +0530 Subject: [PATCH 0843/4131] [vim] changeCase for blockwise visual --- keymap/vim.js | 89 +++++++++++++++++++++++++++++++++++------------- test/vim_test.js | 16 +++++++-- 2 files changed, 79 insertions(+), 26 deletions(-) diff --git a/keymap/vim.js b/keymap/vim.js index b239929f07..e7bb885bf2 100644 --- a/keymap/vim.js +++ b/keymap/vim.js @@ -2348,6 +2348,9 @@ } } cm.setCursor(curPosFinal); + if (vim.visualMode) { + exitVisualMode(cm); + } }, undo: function(cm, actionArgs) { cm.operation(function() { @@ -2449,17 +2452,26 @@ repeatLastEdit(cm, vim, repeat, false /** repeatForInsert */); }, changeCase: function(cm, actionArgs, vim) { - var selectedAreaRange = getSelectedAreaRange(cm, vim); - var selectionStart = selectedAreaRange[0]; - var selectionEnd = selectedAreaRange[1]; + 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 - var lastSelectionCurEnd = vim.lastSelection.curEndMark.find(); + lastSelectionCurEnd = vim.lastSelection.curEndMark.find(); + blockSelection = vim.lastSelection.visualBlock; + } var toLower = actionArgs.toLower; - var text = cm.getRange(selectionStart, selectionEnd); - cm.replaceRange(toLower ? text.toLowerCase() : text.toUpperCase(), selectionStart, selectionEnd); + text = toLower ? text.toLowerCase() : text.toUpperCase(); + cm.replaceSelections(vim.visualBlock || blockSelection ? text.split('\n') : [text]); // restore the last selection curEnd marker - vim.lastSelection.curEndMark = cm.setBookmark(lastSelectionCurEnd); + if (lastSelectionCurEnd) { + vim.lastSelection.curEndMark = cm.setBookmark(lastSelectionCurEnd); + } cm.setCursor(selectionStart); + if (vim.visualMode) { + exitVisualMode(cm); + } } }; @@ -2623,27 +2635,56 @@ return -1; } function getSelectedAreaRange(cm, vim) { - var selectionStart = cm.getCursor('anchor'); - var selectionEnd = cm.getCursor('head'); var lastSelection = vim.lastSelection; - if (!vim.visualMode) { - var lastSelectionCurStart = vim.lastSelection.curStartMark.find(); - var lastSelectionCurEnd = vim.lastSelection.curEndMark.find(); - var line = lastSelectionCurEnd.line - lastSelectionCurStart.line; - var ch = line ? lastSelectionCurEnd.ch : lastSelectionCurEnd.ch - lastSelectionCurStart.ch; - selectionEnd = {line: selectionEnd.line + line, ch: line ? selectionEnd.ch : ch + selectionEnd.ch}; - if (lastSelection.visualLine) { - return [{line: selectionStart.line, ch: 0}, {line: selectionEnd.line, ch: lineLength(cm, selectionEnd.line)}]; + var getCurrentSelectedAreaRange = function() { + var selections = cm.listSelections(); + var start = selections[0]; + var end = selections[selections.length-1]; + var selectionStart = cursorIsBefore(start.anchor, start.head) ? start.anchor : start.head; + var selectionEnd = cursorIsBefore(end.anchor, end.head) ? end.head : end.anchor; + return [selectionStart, selectionEnd]; + }; + var getLastSelectedAreaRange = function() { + var start = lastSelection.curStartMark.find(); + var end = lastSelection.curEndMark.find(); + var selectionStart = cm.getCursor(); + var selectionEnd = cm.getCursor(); + if (lastSelection.visualBlock) { + var anchor = Pos(Math.min(start.line, end.line), Math.min(start.ch, end.ch)); + var head = Pos(Math.max(start.line, end.line), Math.max(start.ch, end.ch)); + var width = head.ch - anchor.ch; + var height = head.line - anchor.line; + selectionEnd = Pos(selectionStart.line + height, selectionStart.ch + width); + var endCh = cm.clipPos(selectionEnd).ch; + // We do not want selection crossing while selecting here. + // So, we cut down the selection. + while (endCh != selectionEnd.ch) { + if (endCh-1 == selectionStart.ch) { + break; + } + selectionEnd.line--; + endCh = cm.clipPos(selectionEnd).ch; + } + cm.setCursor(selectionStart); + selectBlock(cm, selectionEnd); + } else { + var line = end.line - start.line; + var ch = end.ch - start.ch; + selectionEnd = {line: selectionEnd.line + line, ch: line ? selectionEnd.ch : ch + selectionEnd.ch}; + if (lastSelection.visualLine) { + selectionStart = Pos(selectionStart.line, 0); + selectionEnd = Pos(selectionEnd.line, lineLength(cm, selectionEnd.line)); + } + cm.setSelection(selectionStart, selectionEnd); } + return [selectionStart, selectionEnd]; + }; + if (!vim.visualMode) { + // In case of replaying the action. + return getLastSelectedAreaRange(); } else { - if (cursorIsBefore(selectionEnd, selectionStart)) { - var tmp = selectionStart; - selectionStart = selectionEnd; - selectionEnd = tmp; - } - exitVisualMode(cm); + return getCurrentSelectedAreaRange(); } - return [selectionStart, selectionEnd]; } function updateLastSelection(cm, vim, selectionStart, selectionEnd) { if (!selectionStart || !selectionEnd) { diff --git a/test/vim_test.js b/test/vim_test.js index 342737de52..2fb1843169 100644 --- a/test/vim_test.js +++ b/test/vim_test.js @@ -1683,7 +1683,7 @@ testVim('reselect_visual', function(cm, vim, helpers) { cm.setCursor(0, 0); helpers.doKeys('g', 'v'); // here the fake cursor is at (1, 3) - helpers.assertCursorAt(2, 0); + helpers.assertCursorAt(1, 4); eqPos(makeCursor(1, 0), cm.getCursor('anchor')); helpers.doKeys('v'); cm.setCursor(2, 0); @@ -1753,7 +1753,7 @@ testVim('o_visual_block', function(cm, vim, helpers) { helpers.doKeys('o'); helpers.assertCursorAt(3, 1); }, { value: 'abcd\nefgh\nijkl\nmnop'}); -testVim('uppercase/lowercase_visual', function(cm, vim, helpers) { +testVim('changeCase_visual', function(cm, vim, helpers) { cm.setCursor(0, 0); helpers.doKeys('v', 'l', 'l'); helpers.doKeys('U'); @@ -1772,6 +1772,18 @@ testVim('uppercase/lowercase_visual', function(cm, vim, helpers) { helpers.doKeys('V', 'U', 'j', '.'); eq('ABCDEF\nGHIJKL\nMnopq\nSHORT LINE\nLONG LINE OF TEXT', cm.getValue()); }, { value: 'abcdef\nghijkl\nmnopq\nshort line\nlong line of text'}); +testVim('changeCase_visual_block', function(cm, vim, helpers) { + cm.setCursor(2, 1); + helpers.doKeys('', 'k', 'k', 'h', 'U'); + eq('ABcdef\nGHijkl\nMNopq\nfoo', cm.getValue()); + cm.setCursor(0, 2); + helpers.doKeys('.'); + eq('ABCDef\nGHIJkl\nMNOPq\nfoo', cm.getValue()); + // check when last line is shorter. + cm.setCursor(2, 2); + helpers.doKeys('.'); + eq('ABCDef\nGHIJkl\nMNOPq\nfoO', cm.getValue()); +}, { value: 'abcdef\nghijkl\nmnopq\nfoo'}); testVim('visual_paste', function(cm, vim, helpers) { cm.setCursor(0, 0); helpers.doKeys('v', 'l', 'l', 'y', 'j', 'v', 'l', 'p'); From 9312c712a80d665e569e29ea8448e6bb52c03b69 Mon Sep 17 00:00:00 2001 From: binny Date: Fri, 18 Jul 2014 05:30:15 +0530 Subject: [PATCH 0844/4131] [vim] using dot to replay actions and operators --- keymap/vim.js | 111 ++++++++++++++++++++++++++++++++--------------- test/vim_test.js | 17 +++++++- 2 files changed, 92 insertions(+), 36 deletions(-) diff --git a/keymap/vim.js b/keymap/vim.js index e7bb885bf2..16f51b3bf1 100644 --- a/keymap/vim.js +++ b/keymap/vim.js @@ -1411,6 +1411,7 @@ 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; @@ -1437,6 +1438,24 @@ 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; + } } else if (vim.visualMode) { var selOffset = Pos(); selOffset.line = curEnd.line - curStart.line; @@ -1457,8 +1476,8 @@ operatorArgs.registerName = registerName; // Keep track of linewise as it affects how paste and change behave. operatorArgs.linewise = linewise; - if (!vim.visualBlock) { - cm.extendSelection(curStart, curEnd); + if (!vim.visualBlock && !blockSelected) { + cm.setSelection(curStart, curEnd); } operators[operator](cm, operatorArgs, vim, curStart, curEnd, curOriginal); @@ -1838,6 +1857,8 @@ var curEnd = cursorIsBefore(end.anchor, end.head) ? end.head : end.anchor; var text = cm.getSelection(); 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); @@ -1880,34 +1901,52 @@ cm.replaceRange('', curStart, curEnd); } } + vim.marks['>'] = cm.setBookmark(selectionEnd); actions.enterInsertMode(cm, {}, cm.state.vim); }, // delete is a javascript keyword. - 'delete': function(cm, operatorArgs, vim, curStart, curEnd) { + '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 = vim.visualMode ? vim.marks['>'].find() : null; + var selectionEnd, selectionStart; + 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(); + } var text = cm.getSelection(); + vimGlobalState.registerController.pushText( + operatorArgs.registerName, 'delete', text, + operatorArgs.linewise); + 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 > cm.firstLine()) { + curEnd.line == cm.lastLine() && curStart.line == curEnd.line) { + var tmp = copyCursor(curEnd); curStart.line--; curStart.ch = lineLength(cm, curStart.line); - } - vimGlobalState.registerController.pushText( - operatorArgs.registerName, 'delete', text, - operatorArgs.linewise); - if (vim.visualBlock) { - var selections = cm.listSelections(); - curStart = selections[0].anchor; - var replacement = new Array(selections.length).join('1').split('1'); - cm.replaceSelections(replacement); - } else { + curEnd = tmp; cm.replaceRange('', curStart, curEnd); + } else { + cm.replaceSelections(replacement); } // restore the saved bookmark if (selectionEnd) { - vim.marks['>'] = cm.setBookmark(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; + } } if (operatorArgs.linewise) { cm.setCursor(motions.moveToFirstNonWhiteSpaceCharacter(cm)); @@ -2645,29 +2684,26 @@ return [selectionStart, selectionEnd]; }; var getLastSelectedAreaRange = function() { - var start = lastSelection.curStartMark.find(); - var end = lastSelection.curEndMark.find(); var selectionStart = cm.getCursor(); var selectionEnd = cm.getCursor(); - if (lastSelection.visualBlock) { - var anchor = Pos(Math.min(start.line, end.line), Math.min(start.ch, end.ch)); - var head = Pos(Math.max(start.line, end.line), Math.max(start.ch, end.ch)); - var width = head.ch - anchor.ch; - var height = head.line - anchor.line; + var block = lastSelection.visualBlock; + if (block) { + var width = block.width; + var height = block.height; selectionEnd = Pos(selectionStart.line + height, selectionStart.ch + width); - var endCh = cm.clipPos(selectionEnd).ch; - // We do not want selection crossing while selecting here. - // So, we cut down the selection. - while (endCh != selectionEnd.ch) { - if (endCh-1 == selectionStart.ch) { - break; - } - selectionEnd.line--; - endCh = cm.clipPos(selectionEnd).ch; + var selections = []; + // selectBlock creates a 'proper' rectangular block. + // We do not want that in all cases, so we manually set selections. + for (var i = selectionStart.line; i < selectionEnd.line; i++) { + var anchor = Pos(i, selectionStart.ch); + var head = Pos(i, selectionEnd.ch); + var range = {anchor: anchor, head: head}; + selections.push(range); } - cm.setCursor(selectionStart); - selectBlock(cm, selectionEnd); + cm.setSelections(selections); } else { + var start = lastSelection.curStartMark.find(); + var end = lastSelection.curEndMark.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}; @@ -2700,13 +2736,18 @@ // This check ensures to set the cursor // position where we left off in previous selection var swap = getIndex(ranges, selectionStart) > -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), 'visualMode': vim.visualMode, 'visualLine': vim.visualLine, - 'visualBlock': vim.visualBlock}; + 'visualBlock': block}; } function exitVisualMode(cm) { diff --git a/test/vim_test.js b/test/vim_test.js index 2fb1843169..7c24634a89 100644 --- a/test/vim_test.js +++ b/test/vim_test.js @@ -944,7 +944,22 @@ testVim('visual_block_~', function(cm, vim, helpers) { helpers.assertCursorAt(2, 0); eq('hello\nwoRLd\nAbcDe', cm.getValue()); },{value: 'hello\nwOrld\nabcde' }); - +testVim('._swapCase_visualBlock', function(cm, vim, helpers) { + helpers.doKeys('', 'j', 'j', 'l', '~'); + cm.setCursor(0, 3); + helpers.doKeys('.'); + eq('HelLO\nWorLd\nAbcdE', cm.getValue()); +},{value: 'hEllo\nwOrlD\naBcDe' }); +testVim('._delete_visualBlock', function(cm, vim, helpers) { + helpers.doKeys('', 'j', 'x'); + eq('ive\ne\nsome\nsugar', cm.getValue()); + helpers.doKeys('.'); + eq('ve\n\nsome\nsugar', cm.getValue()); + helpers.doKeys('j', 'j', '.'); + eq('ve\n\nome\nugar', cm.getValue()); + helpers.doKeys('u', '', '.'); + eq('ve\n\nme\ngar', cm.getValue()); +},{value: 'give\nme\nsome\nsugar' }); testVim('>{motion}', function(cm, vim, helpers) { cm.setCursor(1, 3); var expectedLineCount = cm.lineCount(); From 252a9d6cb8afd782762bf10c75760cbbd75a5c43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guillaume=20Mass=C3=A9?= Date: Sat, 12 Jul 2014 20:20:08 -0400 Subject: [PATCH 0845/4131] [clike mode] Enable multilineString for scala It is a good approximation --- mode/clike/clike.js | 1 + 1 file changed, 1 insertion(+) diff --git a/mode/clike/clike.js b/mode/clike/clike.js index 3e253624b4..2873e3629b 100644 --- a/mode/clike/clike.js +++ b/mode/clike/clike.js @@ -369,6 +369,7 @@ CodeMirror.defineMode("clike", function(config, parserConfig) { ), + multiLineStrings: true, blockKeywords: words("catch class do else finally for forSome if match switch try while"), atoms: words("true false null"), hooks: { From 58d2a8a8b28e6f45ca98729952870de92184cf05 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Sun, 20 Jul 2014 09:34:51 +0200 Subject: [PATCH 0846/4131] [yaml mode] Be less restrictive about keys in front of colons Issue #2695 --- mode/yaml/yaml.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mode/yaml/yaml.js b/mode/yaml/yaml.js index 4ebe5c81cf..15a5916df1 100644 --- a/mode/yaml/yaml.js +++ b/mode/yaml/yaml.js @@ -80,7 +80,7 @@ CodeMirror.defineMode("yaml", function() { } /* pairs (associative arrays) -> key */ - if (!state.pair && stream.match(/^\s*\S+(?=\s*:($|\s))/i)) { + if (!state.pair && stream.match(/^\s*[^\-:{}"\[\]][^:{}"\[\]]*(?=\s*:($|\s))/i)) { state.pair = true; state.keyCol = stream.indentation(); return "atom"; From dff9738301bedfc57e0a3f3a2168edb05fd5dcf9 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Sun, 20 Jul 2014 09:41:56 +0200 Subject: [PATCH 0847/4131] [puppet mode] Make regexp for regexps non-greedy Issue #2696 --- mode/puppet/puppet.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mode/puppet/puppet.js b/mode/puppet/puppet.js index 66698bb6ad..b407ded883 100644 --- a/mode/puppet/puppet.js +++ b/mode/puppet/puppet.js @@ -176,7 +176,7 @@ CodeMirror.defineMode("puppet", function () { // Match characters that we are going to assume // are trying to be regex if (ch == '/') { - stream.match(/.*\//); + stream.match(/.*?\//); return 'variable-3'; } // Match all the numbers From 4e7e863c0e34f9fc450351d408a3f585d3843549 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Sun, 20 Jul 2014 10:26:22 +0200 Subject: [PATCH 0848/4131] Remove a few unneccesary property accesses --- lib/codemirror.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/codemirror.js b/lib/codemirror.js index 0aad3fda68..8b3feac507 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -3815,7 +3815,7 @@ if (how == "smart") { // Fall back to "prev" when the mode doesn't have an indentation // method. - if (!cm.doc.mode.indent) how = "prev"; + if (!doc.mode.indent) how = "prev"; else state = getStateBefore(cm, n); } @@ -3827,7 +3827,7 @@ indentation = 0; how = "not"; } else if (how == "smart") { - indentation = cm.doc.mode.indent(state, line.text.slice(curSpaceString.length), line.text); + indentation = doc.mode.indent(state, line.text.slice(curSpaceString.length), line.text); if (indentation == Pass || indentation > 150) { if (!aggressive) return; how = "prev"; @@ -3851,7 +3851,7 @@ if (pos < indentation) indentString += spaceStr(indentation - pos); if (indentString != curSpaceString) { - replaceRange(cm.doc, indentString, Pos(n, 0), Pos(n, curSpaceString.length), "+input"); + replaceRange(doc, indentString, Pos(n, 0), Pos(n, curSpaceString.length), "+input"); } else { // Ensure that, if the cursor was in the whitespace at the start // of the line, it is moved to the end of that space. From 1ddba34bb6e467282eeda6a79bd16c9650668169 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Sun, 20 Jul 2014 10:56:24 +0200 Subject: [PATCH 0849/4131] Force stable y scroll when focusing textarea in onContextMenu Closes #2712 --- lib/codemirror.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/codemirror.js b/lib/codemirror.js index 8b3feac507..09ea0a3134 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -3319,7 +3319,9 @@ "px; left: " + (e.clientX - 5) + "px; z-index: 1000; background: " + (ie ? "rgba(255, 255, 255, .05)" : "transparent") + "; outline: none; border-width: 0; outline: none; overflow: hidden; opacity: .05; filter: alpha(opacity=5);"; + if (webkit) var oldScrollY = window.scrollY; // Work around Chrome issue (#2712) focusInput(cm); + if (webkit) window.scrollTo(null, oldScrollY); resetInput(cm); // Adds "Select all" to context menu in FF if (!cm.somethingSelected()) display.input.value = display.prevInput = " "; From 1d35536ee0f23be031beba12309a38db9f49b4d5 Mon Sep 17 00:00:00 2001 From: Yunchi Luo Date: Sun, 20 Jul 2014 14:01:11 -0700 Subject: [PATCH 0850/4131] [vim] Do not open prompt if no cm.openDialog --- keymap/vim.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/keymap/vim.js b/keymap/vim.js index 16f51b3bf1..a47b005d02 100644 --- a/keymap/vim.js +++ b/keymap/vim.js @@ -561,7 +561,9 @@ MacroModeState.prototype = { exitMacroRecordMode: function() { var macroModeState = vimGlobalState.macroModeState; - macroModeState.onRecordingDone(); // close dialog + if (macroModeState.onRecordingDone) { + macroModeState.onRecordingDone(); // close dialog + } macroModeState.onRecordingDone = undefined; macroModeState.isRecording = false; }, @@ -571,8 +573,10 @@ if (register) { register.clear(); this.latestRegister = registerName; - this.onRecordingDone = cm.openDialog( - '(recording)['+registerName+']', null, {bottom:true}); + if (cm.openDialog) { + this.onRecordingDone = cm.openDialog( + '(recording)['+registerName+']', null, {bottom:true}); + } this.isRecording = true; } } From 1d4b525f8127e79aaee811ff2b6972a3fa76a7bd Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 21 Jul 2014 08:28:07 +0200 Subject: [PATCH 0851/4131] [yaml mode] Tweak key regexp Issue #2695 --- mode/yaml/yaml.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mode/yaml/yaml.js b/mode/yaml/yaml.js index 15a5916df1..332aef6a23 100644 --- a/mode/yaml/yaml.js +++ b/mode/yaml/yaml.js @@ -80,7 +80,7 @@ CodeMirror.defineMode("yaml", function() { } /* pairs (associative arrays) -> key */ - if (!state.pair && stream.match(/^\s*[^\-:{}"\[\]][^:{}"\[\]]*(?=\s*:($|\s))/i)) { + if (!state.pair && stream.match(/^\s*(?:[,\[\]{}&*!|>'"%@`][^\s'":]|[^,\[\]{}#&*!|>'"%@`])[^#]*?(?=\s*:($|\s))/)) { state.pair = true; state.keyCol = stream.indentation(); return "atom"; From e02b946bfdf68ac4c3933b99e119a8fa9898efb6 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 21 Jul 2014 08:33:42 +0200 Subject: [PATCH 0852/4131] Also split pasted content by selection when selection length is a multiple of clipboard length Issue #2697 --- lib/codemirror.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/codemirror.js b/lib/codemirror.js index 09ea0a3134..31c6d71be5 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -2417,7 +2417,7 @@ var multiPaste = null; if (cm.state.pasteIncoming && doc.sel.ranges.length > 1) { if (lastCopied && lastCopied.join("\n") == inserted) - multiPaste = lastCopied.length == doc.sel.ranges.length && map(lastCopied, splitLines); + multiPaste = doc.sel.ranges.length % lastCopied.length == 0 && map(lastCopied, splitLines); else if (textLines.length == doc.sel.ranges.length) multiPaste = map(textLines, function(l) { return [l]; }); } @@ -2433,7 +2433,7 @@ else if (cm.state.overwrite && range.empty() && !cm.state.pasteIncoming) to = Pos(to.line, Math.min(getLine(doc, to.line).text.length, to.ch + lst(textLines).length)); var updateInput = cm.curOp.updateInput; - var changeEvent = {from: from, to: to, text: multiPaste ? multiPaste[i] : textLines, + var changeEvent = {from: from, to: to, text: multiPaste ? multiPaste[i % multiPaste.length] : textLines, origin: cm.state.pasteIncoming ? "paste" : cm.state.cutIncoming ? "cut" : "+input"}; makeChange(cm.doc, changeEvent); signalLater(cm, "inputRead", cm, changeEvent); From ee088bc36b3fca2771835cc42febcabeb19e791c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Haso=C5=88?= Date: Mon, 14 Jul 2014 08:32:17 +0200 Subject: [PATCH 0853/4131] [bower.json] Normalized a package name The package name on http://bower.io/search/ is lowercase. --- bower.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bower.json b/bower.json index b103179156..407b86d649 100644 --- a/bower.json +++ b/bower.json @@ -1,5 +1,5 @@ { - "name": "CodeMirror", + "name": "codemirror", "version":"4.3.1", "main": ["lib/codemirror.js", "lib/codemirror.css"], "ignore": [ From 485a7da897e378025268e686f4eb79377973219e Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 21 Jul 2014 08:51:28 +0200 Subject: [PATCH 0854/4131] Mark release 4.4 --- AUTHORS | 9 +++++++++ bower.json | 2 +- doc/compress.html | 1 + doc/manual.html | 2 +- doc/releases.html | 14 ++++++++++++++ index.html | 2 +- lib/codemirror.js | 2 +- package.json | 2 +- 8 files changed, 29 insertions(+), 5 deletions(-) diff --git a/AUTHORS b/AUTHORS index f5f569721e..0c2f67c31a 100644 --- a/AUTHORS +++ b/AUTHORS @@ -18,6 +18,7 @@ Alberto Pose Albert Xing Alexander Pavlov Alexander Schepanovski +Alexander Shvets Alexander Solovyov Alexandre Bique alexey-k @@ -168,6 +169,7 @@ Jason Grout Jason Johnston Jason San Jose Jason Siefken +Jaydeep Solanki Jean Boussier jeffkenton Jeff Pickhardt @@ -205,6 +207,7 @@ kubelsmieci Lanny Laszlo Vidacs leaf corcoran +Leonid Khachaturov Leonya Khachaturov Liam Newman LM @@ -269,6 +272,7 @@ Niels van Groningen Nikita Beloglazov Nikita Vasilyev Nikolay Kostov +nilp0inter nlwillia pablo Page @@ -291,7 +295,9 @@ Radek Piórkowski Rahul Randy Edmunds Rasmus Erik Voel Jensen +Richard van der Meer Richard Z.H. Wang +Roberto Abdelkader Martínez Pérez robertop23 Robert Plummer Ruslan Osmanov @@ -299,6 +305,7 @@ Ryan Prior sabaca Samuel Ainsworth sandeepshetty +Sander AKA Redsandro santec Sascha Peilicke satchmorun @@ -330,6 +337,7 @@ Thaddee Tyl think Thomas Dvornik Thomas Schmid +Tim Alby Tim Baumann Timothy Farrell Timothy Hatcher @@ -349,6 +357,7 @@ Volker Mische wenli Wesley Wiser William Jamieson +William Stein Wojtek Ptak Xavier Mendez YNH Webdev diff --git a/bower.json b/bower.json index 407b86d649..8c57fcdd4b 100644 --- a/bower.json +++ b/bower.json @@ -1,6 +1,6 @@ { "name": "codemirror", - "version":"4.3.1", + "version":"4.4.0", "main": ["lib/codemirror.js", "lib/codemirror.css"], "ignore": [ "**/.*", diff --git a/doc/compress.html b/doc/compress.html index ede45e1c6e..859210c45c 100644 --- a/doc/compress.html +++ b/doc/compress.html @@ -36,6 +36,7 @@

    Script compression helper

    Version: + + +

    MIME types defined: application/x-slim.

    + +

    + Parsing/Highlighting Tests: + normal, + verbose. +

    + diff --git a/mode/slim/slim.js b/mode/slim/slim.js new file mode 100644 index 0000000000..5e737131aa --- /dev/null +++ b/mode/slim/slim.js @@ -0,0 +1,575 @@ +// CodeMirror, copyright (c) by Marijn Haverbeke and others +// Distributed under an MIT license: http://codemirror.net/LICENSE + +// Slim Highlighting for CodeMirror copyright (c) HicknHack Software Gmbh + +(function(mod) { + if (typeof exports == "object" && typeof module == "object") // CommonJS + mod(require("../../lib/codemirror"), require("../htmlmixed/htmlmixed"), require("../ruby/ruby")); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror", "../htmlmixed/htmlmixed", "../ruby/ruby"], mod); + else // Plain browser env + mod(CodeMirror); +})(function(CodeMirror) { +"use strict"; + + CodeMirror.defineMode("slim", function(config) { + var htmlMode = CodeMirror.getMode(config, {name: "htmlmixed"}); + var rubyMode = CodeMirror.getMode(config, "ruby"); + var modes = { html: htmlMode, ruby: rubyMode }; + var embedded = { + ruby: "ruby", + javascript: "javascript", + css: "text/css", + sass: "text/x-sass", + scss: "text/x-scss", + less: "text/x-less", + styl: "text/x-styl", // no highlighting so far + coffee: "coffeescript", + asciidoc: "text/x-asciidoc", + markdown: "text/x-markdown", + textile: "text/x-textile", // no highlighting so far + creole: "text/x-creole", // no highlighting so far + wiki: "text/x-wiki", // no highlighting so far + mediawiki: "text/x-mediawiki", // no highlighting so far + rdoc: "text/x-rdoc", // no highlighting so far + builder: "text/x-builder", // no highlighting so far + nokogiri: "text/x-nokogiri", // no highlighting so far + erb: "application/x-erb" + }; + var embeddedRegexp = function(map){ + var arr = []; + for(var key in map) arr.push(key); + return new RegExp("^("+arr.join('|')+"):"); + }(embedded); + + var styleMap = { + "commentLine": "comment", + "slimSwitch": "operator special", + "slimTag": "tag", + "slimId": "attribute def", + "slimClass": "attribute qualifier", + "slimAttribute": "attribute", + "slimSubmode": "keyword special", + "closeAttributeTag": null, + "slimDoctype": null, + "lineContinuation": null + }; + var closing = { + "{": "}", + "[": "]", + "(": ")" + }; + + var nameStartChar = "_a-zA-Z\xC0-\xD6\xD8-\xF6\xF8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD"; + var nameChar = nameStartChar + "\\-0-9\xB7\u0300-\u036F\u203F-\u2040"; + var nameRegexp = new RegExp("^[:"+nameStartChar+"](?::["+nameChar+"]|["+nameChar+"]*)"); + var attributeNameRegexp = new RegExp("^[:"+nameStartChar+"][:\\."+nameChar+"]*(?=\\s*=)"); + var wrappedAttributeNameRegexp = new RegExp("^[:"+nameStartChar+"][:\\."+nameChar+"]*"); + var classNameRegexp = /^\.-?[_a-zA-Z]+[\w\-]*/; + var classIdRegexp = /^#[_a-zA-Z]+[\w\-]*/; + + function backup(pos, tokenize, style) { + var restore = function(stream, state) { + state.tokenize = tokenize; + if (stream.pos < pos) { + stream.pos = pos; + return style; + } + return state.tokenize(stream, state); + }; + return function(stream, state) { + state.tokenize = restore; + return tokenize(stream, state); + }; + } + + function maybeBackup(stream, state, pat, offset, style) { + var cur = stream.current(); + var idx = cur.search(pat); + if (idx > -1) { + state.tokenize = backup(stream.pos, state.tokenize, style); + stream.backUp(cur.length - idx - offset); + } + return style; + } + + function continueLine(state, column) { + state.stack = { + parent: state.stack, + style: "continuation", + indented: column, + tokenize: state.line + }; + state.line = state.tokenize; + } + function finishContinue(state) { + if (state.line == state.tokenize) { + state.line = state.stack.tokenize; + state.stack = state.stack.parent; + } + } + + function lineContinuable(column, tokenize) { + return function(stream, state) { + finishContinue(state); + if (stream.match(/^\\$/)) { + continueLine(state, column); + return "lineContinuation"; + } + var style = tokenize(stream, state); + if (stream.eol() && stream.current().match(/(?:^|[^\\])(?:\\\\)*\\$/)) { + stream.backUp(1); + } + return style; + }; + } + function commaContinuable(column, tokenize) { + return function(stream, state) { + finishContinue(state); + var style = tokenize(stream, state); + if (stream.eol() && stream.current().match(/,$/)) { + continueLine(state, column); + } + return style; + }; + } + + function rubyInQuote(endQuote, tokenize) { + // TODO: add multi line support + return function(stream, state) { + var ch = stream.peek(); + if (ch == endQuote && state.rubyState.tokenize.length == 1) { + // step out of ruby context as it seems to complete processing all the braces + stream.next(); + state.tokenize = tokenize; + return "closeAttributeTag"; + } else { + return ruby(stream, state); + } + }; + } + function startRubySplat(tokenize) { + var rubyState; + var runSplat = function(stream, state) { + if (state.rubyState.tokenize.length == 1 && !state.rubyState.context.prev) { + stream.backUp(1); + if (stream.eatSpace()) { + state.rubyState = rubyState; + state.tokenize = tokenize; + return tokenize(stream, state); + } + stream.next(); + } + return ruby(stream, state); + }; + return function(stream, state) { + rubyState = state.rubyState; + state.rubyState = rubyMode.startState(); + state.tokenize = runSplat; + return ruby(stream, state); + }; + } + + function ruby(stream, state) { + return rubyMode.token(stream, state.rubyState); + } + + function htmlLine(stream, state) { + if (stream.match(/^\\$/)) { + return "lineContinuation"; + } + return html(stream, state); + } + function html(stream, state) { + if (stream.match(/^#\{/)) { + state.tokenize = rubyInQuote("}", state.tokenize); + return null; + } + return maybeBackup(stream, state, /[^\\]#\{/, 1, htmlMode.token(stream, state.htmlState)); + } + + function startHtmlLine(lastTokenize) { + return function(stream, state) { + var style = htmlLine(stream, state); + if (stream.eol()) state.tokenize = lastTokenize; + return style; + }; + } + + function startHtmlMode(stream, state, offset) { + state.stack = { + parent: state.stack, + style: "html", + indented: stream.column() + offset, // pipe + space + tokenize: state.line + }; + state.line = state.tokenize = html; + return null; + } + + function comment(stream, state) { + stream.skipToEnd(); + return state.stack.style; + } + + function commentMode(stream, state) { + state.stack = { + parent: state.stack, + style: "comment", + indented: state.indented + 1, + tokenize: state.line + }; + state.line = comment; + return comment(stream, state); + } + + function attributeWrapper(stream, state) { + if (stream.eat(state.stack.endQuote)) { + state.line = state.stack.line; + state.tokenize = state.stack.tokenize; + state.stack = state.stack.parent; + return null; + } + if (stream.match(wrappedAttributeNameRegexp)) { + state.tokenize = attributeWrapperAssign; + return "slimAttribute"; + } + stream.next(); + return null; + } + function attributeWrapperAssign(stream, state) { + if (stream.match(/^==?/)) { + state.tokenize = attributeWrapperValue; + return null; + } + return attributeWrapper(stream, state); + } + function attributeWrapperValue(stream, state) { + var ch = stream.peek(); + if (ch == '"' || ch == "\'") { + state.tokenize = readQuoted(ch, "string", true, false, attributeWrapper); + stream.next(); + return state.tokenize(stream, state); + } + if (ch == '[') { + return startRubySplat(attributeWrapper)(stream, state); + } + if (stream.match(/^(true|false|nil)\b/)) { + state.tokenize = attributeWrapper; + return "keyword"; + } + return startRubySplat(attributeWrapper)(stream, state); + } + + function startAttributeWrapperMode(state, endQuote, tokenize) { + state.stack = { + parent: state.stack, + style: "wrapper", + indented: state.indented + 1, + tokenize: tokenize, + line: state.line, + endQuote: endQuote + }; + state.line = state.tokenize = attributeWrapper; + return null; + } + + function sub(stream, state) { + if (stream.match(/^#\{/)) { + state.tokenize = rubyInQuote("}", state.tokenize); + return null; + } + var subStream = new CodeMirror.StringStream(stream.string.slice(state.stack.indented), stream.tabSize); + subStream.pos = stream.pos - state.stack.indented; + subStream.start = stream.start - state.stack.indented; + subStream.lastColumnPos = stream.lastColumnPos - state.stack.indented; + subStream.lastColumnValue = stream.lastColumnValue - state.stack.indented; + var style = state.subMode.token(subStream, state.subState); + stream.pos = subStream.pos + state.stack.indented; + return style; + } + function firstSub(stream, state) { + state.stack.indented = stream.column(); + state.line = state.tokenize = sub; + return state.tokenize(stream, state); + } + + function createMode(mode) { + var query = embedded[mode]; + var spec = CodeMirror.mimeModes[query]; + if (spec) { + return CodeMirror.getMode(config, spec); + } + var factory = CodeMirror.modes[query]; + if (factory) { + return factory(config, {name: query}); + } + return CodeMirror.getMode(config, "null"); + } + + function getMode(mode) { + if (!modes.hasOwnProperty(mode)) { + return modes[mode] = createMode(mode); + } + return modes[mode]; + } + + function startSubMode(mode, state) { + var subMode = getMode(mode); + var subState = subMode.startState && subMode.startState(); + + state.subMode = subMode; + state.subState = subState; + + state.stack = { + parent: state.stack, + style: "sub", + indented: state.indented + 1, + tokenize: state.line + }; + state.line = state.tokenize = firstSub; + return "slimSubmode"; + } + + function doctypeLine(stream, _state) { + stream.skipToEnd(); + return "slimDoctype"; + } + + function startLine(stream, state) { + var ch = stream.peek(); + if (ch == '<') { + return (state.tokenize = startHtmlLine(state.tokenize))(stream, state); + } + if (stream.match(/^[|']/)) { + return startHtmlMode(stream, state, 1); + } + if (stream.match(/^\/(!|\[\w+])?/)) { + return commentMode(stream, state); + } + if (stream.match(/^(-|==?[<>]?)/)) { + state.tokenize = lineContinuable(stream.column(), commaContinuable(stream.column(), ruby)); + return "slimSwitch"; + } + if (stream.match(/^doctype\b/)) { + state.tokenize = doctypeLine; + return "keyword"; + } + + var m = stream.match(embeddedRegexp); + if (m) { + return startSubMode(m[1], state); + } + + return slimTag(stream, state); + } + + function slim(stream, state) { + if (state.startOfLine) { + return startLine(stream, state); + } + return slimTag(stream, state); + } + + function slimTag(stream, state) { + if (stream.eat('*')) { + state.tokenize = startRubySplat(slimTagExtras); + return null; + } + if (stream.match(nameRegexp)) { + state.tokenize = slimTagExtras; + return "slimTag"; + } + return slimClass(stream, state); + } + function slimTagExtras(stream, state) { + if (stream.match(/^(<>?|> state.indented && state.last != "slimSubmode") { + state.line = state.tokenize = state.stack.tokenize; + state.stack = state.stack.parent; + state.subMode = null; + state.subState = null; + } + } + if (stream.eatSpace()) return null; + var style = state.tokenize(stream, state); + state.startOfLine = false; + if (style) state.last = style; + return styleMap.hasOwnProperty(style) ? styleMap[style] : style; + }, + + blankLine: function(state) { + if (state.subMode && state.subMode.blankLine) { + return state.subMode.blankLine(state.subState); + } + }, + + innerMode: function(state) { + if (state.subMode) return {state: state.subState, mode: state.subMode}; + return {state: state, mode: mode}; + } + + //indent: function(state) { + // return state.indented; + //} + }; + return mode; + }, "htmlmixed", "ruby"); + + CodeMirror.defineMIME("text/x-slim", "slim"); + CodeMirror.defineMIME("application/x-slim", "slim"); +}); diff --git a/mode/slim/test.js b/mode/slim/test.js new file mode 100644 index 0000000000..be4ddacb62 --- /dev/null +++ b/mode/slim/test.js @@ -0,0 +1,96 @@ +// CodeMirror, copyright (c) by Marijn Haverbeke and others +// Distributed under an MIT license: http://codemirror.net/LICENSE + +// Slim Highlighting for CodeMirror copyright (c) HicknHack Software Gmbh + +(function() { + var mode = CodeMirror.getMode({tabSize: 4, indentUnit: 2}, "slim"); + function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); } + + // Requires at least one media query + MT("elementName", + "[tag h1] Hey There"); + + MT("oneElementPerLine", + "[tag h1] Hey There .h2"); + + MT("idShortcut", + "[attribute&def #test] Hey There"); + + MT("tagWithIdShortcuts", + "[tag h1][attribute&def #test] Hey There"); + + MT("classShortcut", + "[attribute&qualifier .hello] Hey There"); + + MT("tagWithIdAndClassShortcuts", + "[tag h1][attribute&def #test][attribute&qualifier .hello] Hey There"); + + MT("docType", + "[keyword doctype] xml"); + + MT("comment", + "[comment / Hello WORLD]"); + + MT("notComment", + "[tag h1] This is not a / comment "); + + MT("attributes", + "[tag a]([attribute title]=[string \"test\"]) [attribute href]=[string \"link\"]}"); + + MT("multiLineAttributes", + "[tag a]([attribute title]=[string \"test\"]", + " ) [attribute href]=[string \"link\"]}"); + + MT("htmlCode", + "[tag&bracket <][tag h1][tag&bracket >]Title[tag&bracket ]"); + + MT("rubyBlock", + "[operator&special =][variable-2 @item]"); + + MT("selectorRubyBlock", + "[tag a][attribute&qualifier .test][operator&special =] [variable-2 @item]"); + + MT("nestedRubyBlock", + "[tag a]", + " [operator&special =][variable puts] [string \"test\"]"); + + MT("multilinePlaintext", + "[tag p]", + " | Hello,", + " World"); + + MT("multilineRuby", + "[tag p]", + " [comment /# this is a comment]", + " [comment and this is a comment too]", + " | Date/Time", + " [operator&special -] [variable now] [operator =] [tag DateTime][operator .][property now]", + " [tag strong][operator&special =] [variable now]", + " [operator&special -] [keyword if] [variable now] [operator >] [tag DateTime][operator .][property parse]([string \"December 31, 2006\"])", + " [operator&special =][string \"Happy\"]", + " [operator&special =][string \"Belated\"]", + " [operator&special =][string \"Birthday\"]"); + + MT("multilineComment", + "[comment /]", + " [comment Multiline]", + " [comment Comment]"); + + MT("hamlAfterRubyTag", + "[attribute&qualifier .block]", + " [tag strong][operator&special =] [variable now]", + " [attribute&qualifier .test]", + " [operator&special =][variable now]", + " [attribute&qualifier .right]"); + + MT("stretchedRuby", + "[operator&special =] [variable puts] [string \"Hello\"],", + " [string \"World\"]"); + + MT("interpolationInHashAttribute", + "[tag div]{[attribute id] = [string \"]#{[variable test]}[string _]#{[variable ting]}[string \"]} test"); + + MT("interpolationInHTMLAttribute", + "[tag div]([attribute title]=[string \"]#{[variable test]}[string _]#{[variable ting]()}[string \"]) Test"); +})(); diff --git a/test/index.html b/test/index.html index 9930301eb5..a10bd182d4 100644 --- a/test/index.html +++ b/test/index.html @@ -94,6 +94,8 @@

    Test Suite

    + + From b6e9eea8bb4daec6a0ff23f97104d251a0940414 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 14 Aug 2014 14:17:48 +0200 Subject: [PATCH 0896/4131] [slim mode] Integrate Issue #2755 --- doc/compress.html | 1 + mode/index.html | 1 + mode/meta.js | 1 + mode/slim/slim.js | 8 ++++---- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/doc/compress.html b/doc/compress.html index 859210c45c..8d25e4b4e9 100644 --- a/doc/compress.html +++ b/doc/compress.html @@ -152,6 +152,7 @@

    Script compression helper

    + diff --git a/mode/index.html b/mode/index.html index 1aa0b8d821..1c106ae8e0 100644 --- a/mode/index.html +++ b/mode/index.html @@ -95,6 +95,7 @@

    Language modes

  • SCSS
  • Shell
  • Sieve
  • +
  • Slim
  • Smalltalk
  • Smarty
  • Smarty/HTML mixed
  • diff --git a/mode/meta.js b/mode/meta.js index 3627cd7470..e3c32b6f6c 100644 --- a/mode/meta.js +++ b/mode/meta.js @@ -86,6 +86,7 @@ CodeMirror.modeInfo = [ {name: "SCSS", mime: "text/x-scss", mode: "css"}, {name: "Shell", mime: "text/x-sh", mode: "shell"}, {name: "Sieve", mime: "application/sieve", mode: "sieve"}, + {name: "Slim", mime: "text/x-slim", mode: "slim"}, {name: "Smalltalk", mime: "text/x-stsrc", mode: "smalltalk"}, {name: "Smarty", mime: "text/x-smarty", mode: "smarty"}, {name: "SmartyMixed", mime: "text/x-smarty", mode: "smartymixed"}, diff --git a/mode/slim/slim.js b/mode/slim/slim.js index 5e737131aa..164464d066 100644 --- a/mode/slim/slim.js +++ b/mode/slim/slim.js @@ -104,10 +104,10 @@ state.line = state.tokenize; } function finishContinue(state) { - if (state.line == state.tokenize) { - state.line = state.stack.tokenize; - state.stack = state.stack.parent; - } + if (state.line == state.tokenize) { + state.line = state.stack.tokenize; + state.stack = state.stack.parent; + } } function lineContinuable(column, tokenize) { From bbc53ebda20b9a0a5b889d10a3ca4a44a43b3c9a Mon Sep 17 00:00:00 2001 From: Hakan Tunc Date: Mon, 28 Jul 2014 14:36:45 -0500 Subject: [PATCH 0897/4131] Add mimetype text/x-nesc --- mode/clike/clike.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/mode/clike/clike.js b/mode/clike/clike.js index 2873e3629b..ee2c77a025 100644 --- a/mode/clike/clike.js +++ b/mode/clike/clike.js @@ -437,4 +437,15 @@ CodeMirror.defineMode("clike", function(config, parserConfig) { modeProps: {fold: ["brace", "include"]} }); + def("text/x-nesc", { + name: "clike", + keywords: words(cKeywords + "as atomic async call command component components configuration event generic " + + "implementation includes interface module new norace nx_struct nx_union post provides " + + "signal task uses abstract extends"), + blockKeywords: words("case do else for if switch while struct"), + atoms: words("null"), + hooks: {"#": cppHook}, + modeProps: {fold: ["brace", "include"]} + }); + }); From a46ad916a6f40a0208c3f04b9fb35dcb7153f691 Mon Sep 17 00:00:00 2001 From: amuntean Date: Mon, 28 Jul 2014 13:31:06 +0200 Subject: [PATCH 0898/4131] [merge] new allowEditingOriginals option to edit all compared files --- addon/merge/merge.css | 6 ++++++ addon/merge/merge.js | 27 ++++++++++++++++++++++----- 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/addon/merge/merge.css b/addon/merge/merge.css index 63237fc8e9..5d24b9bb7f 100644 --- a/addon/merge/merge.css +++ b/addon/merge/merge.css @@ -62,6 +62,12 @@ color: #44c; } +.CodeMirror-merge-copy-reverse { + position: absolute; + cursor: pointer; + color: #44c; +} + .CodeMirror-merge-copybuttons-left .CodeMirror-merge-copy { left: 2px; } .CodeMirror-merge-copybuttons-right .CodeMirror-merge-copy { right: 2px; } diff --git a/addon/merge/merge.js b/addon/merge/merge.js index bde461fcea..d9b277664b 100644 --- a/addon/merge/merge.js +++ b/addon/merge/merge.js @@ -37,7 +37,7 @@ constructor: DiffView, init: function(pane, orig, options) { this.edit = this.mv.edit; - this.orig = CodeMirror(pane, copyObj({value: orig, readOnly: true}, copyObj(options))); + this.orig = CodeMirror(pane, copyObj({value: orig, readOnly: !this.mv.options.allowEditingOriginals}, copyObj(options))); this.diff = getDiff(asString(orig), asString(options.value)); this.diffOutOfDate = false; @@ -282,16 +282,27 @@ if (dv.copyButtons) { var copy = dv.copyButtons.appendChild(elt("div", dv.type == "left" ? "\u21dd" : "\u21dc", "CodeMirror-merge-copy")); - copy.title = "Revert chunk"; + var editOriginals = dv.mv.options.allowEditingOriginals; + copy.title = editOriginals ? "Push to left" : "Revert chunk"; copy.chunk = {topEdit: topEdit, botEdit: botEdit, topOrig: topOrig, botOrig: botOrig}; copy.style.top = top + "px"; + + if (editOriginals) { + var topReverse = dv.orig.heightAtLine(topEdit, "local") - sTopEdit; + var copyReverse = dv.copyButtons.appendChild(elt("div", dv.type == "right" ? "\u21dd" : "\u21dc", + "CodeMirror-merge-copy-reverse")); + copyReverse.title = "Push to right"; + copyReverse.chunk = {topEdit: topOrig, botEdit: botOrig, topOrig: topEdit, botOrig: botEdit}; + copyReverse.style.top = topReverse + "px"; + dv.type == "right" ? copyReverse.style.left = "2px" : copyReverse.style.right = "2px"; + } } }); } - function copyChunk(dv, chunk) { + function copyChunk(dv, to, from, chunk) { if (dv.diffOutOfDate) return; - dv.edit.replaceRange(dv.orig.getRange(Pos(chunk.topOrig, 0), Pos(chunk.botOrig, 0)), + to.replaceRange(from.getRange(Pos(chunk.topOrig, 0), Pos(chunk.botOrig, 0)), Pos(chunk.topEdit, 0), Pos(chunk.botEdit, 0)); } @@ -326,6 +337,7 @@ (hasRight ? rightPane : editPane).className += " CodeMirror-merge-pane-rightmost"; wrap.push(elt("div", null, null, "height: 0; clear: both;")); + var wrapElt = this.wrap = node.appendChild(elt("div", wrap, "CodeMirror-merge CodeMirror-merge-" + panes + "pane")); this.edit = CodeMirror(editPane, copyObj(options)); @@ -353,7 +365,12 @@ dv.copyButtons = elt("div", null, "CodeMirror-merge-copybuttons-" + dv.type); CodeMirror.on(dv.copyButtons, "click", function(e) { var node = e.target || e.srcElement; - if (node.chunk) copyChunk(dv, node.chunk); + if (!node.chunk) return; + if (node.className == "CodeMirror-merge-copy-reverse") { + copyChunk(dv, dv.orig, dv.edit, node.chunk); + return; + } + copyChunk(dv, dv.edit, dv.orig, node.chunk); }); gapElts.unshift(dv.copyButtons); } From 162c6073e60fcc6635ba31e8ed7a0d35da68a5e0 Mon Sep 17 00:00:00 2001 From: Doug Wikle Date: Mon, 21 Jul 2014 08:29:29 -0400 Subject: [PATCH 0899/4131] [verilog mode] Addressed indentation issue Blocking indentation for import/export keywords --- mode/verilog/test.js | 144 +++++++++++++++++++++++++++++++++++++--- mode/verilog/verilog.js | 5 ++ 2 files changed, 138 insertions(+), 11 deletions(-) diff --git a/mode/verilog/test.js b/mode/verilog/test.js index e78860deb9..376d198685 100644 --- a/mode/verilog/test.js +++ b/mode/verilog/test.js @@ -5,7 +5,7 @@ var mode = CodeMirror.getMode({indentUnit: 4}, "verilog"); function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); } - MT("Binary literals", + MT("binary_literals", "[number 1'b0]", "[number 1'b1]", "[number 1'bx]", @@ -30,14 +30,14 @@ "[number 'b0101]" ); - MT("Octal literals", + MT("octal_literals", "[number 3'o7]", "[number 3'O7]", "[number 3'so7]", "[number 3'SO7]" ); - MT("Decimal literals", + MT("decimal_literals", "[number 0]", "[number 1]", "[number 7]", @@ -52,7 +52,7 @@ "[number 32 'd 123]" ); - MT("Hex literals", + MT("hex_literals", "[number 4'h0]", "[number 4'ha]", "[number 4'hF]", @@ -69,7 +69,7 @@ "[number 32'hFFF?]" ); - MT("Real number literals", + MT("real_number_literals", "[number 1.2]", "[number 0.1]", "[number 2394.26331]", @@ -82,36 +82,158 @@ "[number 236.123_763_e-12]" ); - MT("Operators", + MT("operators", "[meta ^]" ); - MT("Keywords", + MT("keywords", "[keyword logic]", "[keyword logic] [variable foo]", "[keyword reg] [variable abc]" ); - MT("Variables", + MT("variables", "[variable _leading_underscore]", "[variable _if]", "[number 12] [variable foo]", "[variable foo] [number 14]" ); - MT("Tick defines", + MT("tick_defines", "[def `FOO]", "[def `foo]", "[def `FOO_bar]" ); - MT("System calls", + MT("system_calls", "[meta $display]", "[meta $vpi_printf]" ); - MT("Line comment", "[comment // Hello world]"); + MT("line_comment", "[comment // Hello world]"); + // Alignment tests + MT("align_port_map_style1", + /** + * mod mod(.a(a), + * .b(b) + * ); + */ + "[variable mod] [variable mod][bracket (].[variable a][bracket (][variable a][bracket )],", + " .[variable b][bracket (][variable b][bracket )]", + " [bracket )];", + "" + ); + + MT("align_port_map_style2", + /** + * mod mod( + * .a(a), + * .b(b) + * ); + */ + "[variable mod] [variable mod][bracket (]", + " .[variable a][bracket (][variable a][bracket )],", + " .[variable b][bracket (][variable b][bracket )]", + "[bracket )];", + "" + ); + + // Indentation tests + MT("indent_single_statement_if", + "[keyword if] [bracket (][variable foo][bracket )]", + " [keyword break];", + "" + ); + + MT("no_indent_after_single_line_if", + "[keyword if] [bracket (][variable foo][bracket )] [keyword break];", + "" + ); + + MT("indent_after_if_begin_same_line", + "[keyword if] [bracket (][variable foo][bracket )] [keyword begin]", + " [keyword break];", + " [keyword break];", + "[keyword end]", + "" + ); + + MT("indent_after_if_begin_next_line", + "[keyword if] [bracket (][variable foo][bracket )]", + " [keyword begin]", + " [keyword break];", + " [keyword break];", + " [keyword end]", + "" + ); + + MT("indent_single_statement_if_else", + "[keyword if] [bracket (][variable foo][bracket )]", + " [keyword break];", + "[keyword else]", + " [keyword break];", + "" + ); + + MT("indent_if_else_begin_same_line", + "[keyword if] [bracket (][variable foo][bracket )] [keyword begin]", + " [keyword break];", + " [keyword break];", + "[keyword end] [keyword else] [keyword begin]", + " [keyword break];", + " [keyword break];", + "[keyword end]", + "" + ); + + MT("indent_if_else_begin_next_line", + "[keyword if] [bracket (][variable foo][bracket )]", + " [keyword begin]", + " [keyword break];", + " [keyword break];", + " [keyword end]", + "[keyword else]", + " [keyword begin]", + " [keyword break];", + " [keyword break];", + " [keyword end]", + "" + ); + + MT("indent_if_nested_without_begin", + "[keyword if] [bracket (][variable foo][bracket )]", + " [keyword if] [bracket (][variable foo][bracket )]", + " [keyword if] [bracket (][variable foo][bracket )]", + " [keyword break];", + "" + ); + + MT("indent_case", + "[keyword case] [bracket (][variable state][bracket )]", + " [variable FOO]:", + " [keyword break];", + " [variable BAR]:", + " [keyword break];", + "[keyword endcase]", + "" + ); + + MT("unindent_after_end_with_preceding_text", + "[keyword begin]", + " [keyword break]; [keyword end]", + "" + ); + + MT("export_function_does_not_indent", + "[keyword export] [string \"DPI-C\"] [keyword function] [variable helloFromSV];", + "" + ); + + MT("export_task_does_not_indent", + "[keyword export] [string \"DPI-C\"] [keyword task] [variable helloFromSV];", + "" + ); })(); diff --git a/mode/verilog/verilog.js b/mode/verilog/verilog.js index 3414ec022e..46209b2492 100644 --- a/mode/verilog/verilog.js +++ b/mode/verilog/verilog.js @@ -95,6 +95,11 @@ CodeMirror.defineMode("verilog", function(config, parserConfig) { openClose["do" ] = "while"; openClose["fork" ] = "join;join_any;join_none"; + // This is a bit of a hack but will work to not indent after import/epxort statements + // as long as the function/task name is on the same line + openClose["import"] = "function;task"; + openClose["export"] = "function;task"; + for (var i in noIndentKeywords) { var keyword = noIndentKeywords[i]; if (openClose[keyword]) { From d0916042da46ae396e3cba45de623f2a24c137f1 Mon Sep 17 00:00:00 2001 From: TheHowl Date: Sun, 25 May 2014 14:49:59 +0200 Subject: [PATCH 0900/4131] [php mode] Add json, curl, mysqli extensions --- mode/php/php.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mode/php/php.js b/mode/php/php.js index 75b003ff75..f8821ed651 100644 --- a/mode/php/php.js +++ b/mode/php/php.js @@ -95,7 +95,7 @@ "die echo empty exit eval include include_once isset list require require_once return " + "print unset __halt_compiler self static parent yield insteadof finally"; var phpAtoms = "true false null TRUE FALSE NULL __CLASS__ __DIR__ __FILE__ __LINE__ __METHOD__ __FUNCTION__ __NAMESPACE__ __TRAIT__"; - var phpBuiltin = "func_num_args func_get_arg func_get_args strlen strcmp strncmp strcasecmp strncasecmp each error_reporting define defined trigger_error user_error set_error_handler restore_error_handler get_declared_classes get_loaded_extensions extension_loaded get_extension_funcs debug_backtrace constant bin2hex hex2bin sleep usleep time mktime gmmktime strftime gmstrftime strtotime date gmdate getdate localtime checkdate flush wordwrap htmlspecialchars htmlentities html_entity_decode md5 md5_file crc32 getimagesize image_type_to_mime_type phpinfo phpversion phpcredits strnatcmp strnatcasecmp substr_count strspn strcspn strtok strtoupper strtolower strpos strrpos strrev hebrev hebrevc nl2br basename dirname pathinfo stripslashes stripcslashes strstr stristr strrchr str_shuffle str_word_count strcoll substr substr_replace quotemeta ucfirst ucwords strtr addslashes addcslashes rtrim str_replace str_repeat count_chars chunk_split trim ltrim strip_tags similar_text explode implode setlocale localeconv parse_str str_pad chop strchr sprintf printf vprintf vsprintf sscanf fscanf parse_url urlencode urldecode rawurlencode rawurldecode readlink linkinfo link unlink exec system escapeshellcmd escapeshellarg passthru shell_exec proc_open proc_close rand srand getrandmax mt_rand mt_srand mt_getrandmax base64_decode base64_encode abs ceil floor round is_finite is_nan is_infinite bindec hexdec octdec decbin decoct dechex base_convert number_format fmod ip2long long2ip getenv putenv getopt microtime gettimeofday getrusage uniqid quoted_printable_decode set_time_limit get_cfg_var magic_quotes_runtime set_magic_quotes_runtime get_magic_quotes_gpc get_magic_quotes_runtime import_request_variables error_log serialize unserialize memory_get_usage var_dump var_export debug_zval_dump print_r highlight_file show_source highlight_string ini_get ini_get_all ini_set ini_alter ini_restore get_include_path set_include_path restore_include_path setcookie header headers_sent connection_aborted connection_status ignore_user_abort parse_ini_file is_uploaded_file move_uploaded_file intval floatval doubleval strval gettype settype is_null is_resource is_bool is_long is_float is_int is_integer is_double is_real is_numeric is_string is_array is_object is_scalar ereg ereg_replace eregi eregi_replace split spliti join sql_regcase dl pclose popen readfile rewind rmdir umask fclose feof fgetc fgets fgetss fread fopen fpassthru ftruncate fstat fseek ftell fflush fwrite fputs mkdir rename copy tempnam tmpfile file file_get_contents stream_select stream_context_create stream_context_set_params stream_context_set_option stream_context_get_options stream_filter_prepend stream_filter_append fgetcsv flock get_meta_tags stream_set_write_buffer set_file_buffer set_socket_blocking stream_set_blocking socket_set_blocking stream_get_meta_data stream_register_wrapper stream_wrapper_register stream_set_timeout socket_set_timeout socket_get_status realpath fnmatch fsockopen pfsockopen pack unpack get_browser crypt opendir closedir chdir getcwd rewinddir readdir dir glob fileatime filectime filegroup fileinode filemtime fileowner fileperms filesize filetype file_exists is_writable is_writeable is_readable is_executable is_file is_dir is_link stat lstat chown touch clearstatcache mail ob_start ob_flush ob_clean ob_end_flush ob_end_clean ob_get_flush ob_get_clean ob_get_length ob_get_level ob_get_status ob_get_contents ob_implicit_flush ob_list_handlers ksort krsort natsort natcasesort asort arsort sort rsort usort uasort uksort shuffle array_walk count end prev next reset current key min max in_array array_search extract compact array_fill range array_multisort array_push array_pop array_shift array_unshift array_splice array_slice array_merge array_merge_recursive array_keys array_values array_count_values array_reverse array_reduce array_pad array_flip array_change_key_case array_rand array_unique array_intersect array_intersect_assoc array_diff array_diff_assoc array_sum array_filter array_map array_chunk array_key_exists pos sizeof key_exists assert assert_options version_compare ftok str_rot13 aggregate session_name session_module_name session_save_path session_id session_regenerate_id session_decode session_register session_unregister session_is_registered session_encode session_start session_destroy session_unset session_set_save_handler session_cache_limiter session_cache_expire session_set_cookie_params session_get_cookie_params session_write_close preg_match preg_match_all preg_replace preg_replace_callback preg_split preg_quote preg_grep overload ctype_alnum ctype_alpha ctype_cntrl ctype_digit ctype_lower ctype_graph ctype_print ctype_punct ctype_space ctype_upper ctype_xdigit virtual apache_request_headers apache_note apache_lookup_uri apache_child_terminate apache_setenv apache_response_headers apache_get_version getallheaders mysql_connect mysql_pconnect mysql_close mysql_select_db mysql_create_db mysql_drop_db mysql_query mysql_unbuffered_query mysql_db_query mysql_list_dbs mysql_list_tables mysql_list_fields mysql_list_processes mysql_error mysql_errno mysql_affected_rows mysql_insert_id mysql_result mysql_num_rows mysql_num_fields mysql_fetch_row mysql_fetch_array mysql_fetch_assoc mysql_fetch_object mysql_data_seek mysql_fetch_lengths mysql_fetch_field mysql_field_seek mysql_free_result mysql_field_name mysql_field_table mysql_field_len mysql_field_type mysql_field_flags mysql_escape_string mysql_real_escape_string mysql_stat mysql_thread_id mysql_client_encoding mysql_get_client_info mysql_get_host_info mysql_get_proto_info mysql_get_server_info mysql_info mysql mysql_fieldname mysql_fieldtable mysql_fieldlen mysql_fieldtype mysql_fieldflags mysql_selectdb mysql_createdb mysql_dropdb mysql_freeresult mysql_numfields mysql_numrows mysql_listdbs mysql_listtables mysql_listfields mysql_db_name mysql_dbname mysql_tablename mysql_table_name pg_connect pg_pconnect pg_close pg_connection_status pg_connection_busy pg_connection_reset pg_host pg_dbname pg_port pg_tty pg_options pg_ping pg_query pg_send_query pg_cancel_query pg_fetch_result pg_fetch_row pg_fetch_assoc pg_fetch_array pg_fetch_object pg_fetch_all pg_affected_rows pg_get_result pg_result_seek pg_result_status pg_free_result pg_last_oid pg_num_rows pg_num_fields pg_field_name pg_field_num pg_field_size pg_field_type pg_field_prtlen pg_field_is_null pg_get_notify pg_get_pid pg_result_error pg_last_error pg_last_notice pg_put_line pg_end_copy pg_copy_to pg_copy_from pg_trace pg_untrace pg_lo_create pg_lo_unlink pg_lo_open pg_lo_close pg_lo_read pg_lo_write pg_lo_read_all pg_lo_import pg_lo_export pg_lo_seek pg_lo_tell pg_escape_string pg_escape_bytea pg_unescape_bytea pg_client_encoding pg_set_client_encoding pg_meta_data pg_convert pg_insert pg_update pg_delete pg_select pg_exec pg_getlastoid pg_cmdtuples pg_errormessage pg_numrows pg_numfields pg_fieldname pg_fieldsize pg_fieldtype pg_fieldnum pg_fieldprtlen pg_fieldisnull pg_freeresult pg_result pg_loreadall pg_locreate pg_lounlink pg_loopen pg_loclose pg_loread pg_lowrite pg_loimport pg_loexport http_response_code get_declared_traits getimagesizefromstring socket_import_stream stream_set_chunk_size trait_exists header_register_callback class_uses session_status session_register_shutdown echo print global static exit array empty eval isset unset die include require include_once require_once"; + var phpBuiltin = "func_num_args func_get_arg func_get_args strlen strcmp strncmp strcasecmp strncasecmp each error_reporting define defined trigger_error user_error set_error_handler restore_error_handler get_declared_classes get_loaded_extensions extension_loaded get_extension_funcs debug_backtrace constant bin2hex hex2bin sleep usleep time mktime gmmktime strftime gmstrftime strtotime date gmdate getdate localtime checkdate flush wordwrap htmlspecialchars htmlentities html_entity_decode md5 md5_file crc32 getimagesize image_type_to_mime_type phpinfo phpversion phpcredits strnatcmp strnatcasecmp substr_count strspn strcspn strtok strtoupper strtolower strpos strrpos strrev hebrev hebrevc nl2br basename dirname pathinfo stripslashes stripcslashes strstr stristr strrchr str_shuffle str_word_count strcoll substr substr_replace quotemeta ucfirst ucwords strtr addslashes addcslashes rtrim str_replace str_repeat count_chars chunk_split trim ltrim strip_tags similar_text explode implode setlocale localeconv parse_str str_pad chop strchr sprintf printf vprintf vsprintf sscanf fscanf parse_url urlencode urldecode rawurlencode rawurldecode readlink linkinfo link unlink exec system escapeshellcmd escapeshellarg passthru shell_exec proc_open proc_close rand srand getrandmax mt_rand mt_srand mt_getrandmax base64_decode base64_encode abs ceil floor round is_finite is_nan is_infinite bindec hexdec octdec decbin decoct dechex base_convert number_format fmod ip2long long2ip getenv putenv getopt microtime gettimeofday getrusage uniqid quoted_printable_decode set_time_limit get_cfg_var magic_quotes_runtime set_magic_quotes_runtime get_magic_quotes_gpc get_magic_quotes_runtime import_request_variables error_log serialize unserialize memory_get_usage var_dump var_export debug_zval_dump print_r highlight_file show_source highlight_string ini_get ini_get_all ini_set ini_alter ini_restore get_include_path set_include_path restore_include_path setcookie header headers_sent connection_aborted connection_status ignore_user_abort parse_ini_file is_uploaded_file move_uploaded_file intval floatval doubleval strval gettype settype is_null is_resource is_bool is_long is_float is_int is_integer is_double is_real is_numeric is_string is_array is_object is_scalar ereg ereg_replace eregi eregi_replace split spliti join sql_regcase dl pclose popen readfile rewind rmdir umask fclose feof fgetc fgets fgetss fread fopen fpassthru ftruncate fstat fseek ftell fflush fwrite fputs mkdir rename copy tempnam tmpfile file file_get_contents stream_select stream_context_create stream_context_set_params stream_context_set_option stream_context_get_options stream_filter_prepend stream_filter_append fgetcsv flock get_meta_tags stream_set_write_buffer set_file_buffer set_socket_blocking stream_set_blocking socket_set_blocking stream_get_meta_data stream_register_wrapper stream_wrapper_register stream_set_timeout socket_set_timeout socket_get_status realpath fnmatch fsockopen pfsockopen pack unpack get_browser crypt opendir closedir chdir getcwd rewinddir readdir dir glob fileatime filectime filegroup fileinode filemtime fileowner fileperms filesize filetype file_exists is_writable is_writeable is_readable is_executable is_file is_dir is_link stat lstat chown touch clearstatcache mail ob_start ob_flush ob_clean ob_end_flush ob_end_clean ob_get_flush ob_get_clean ob_get_length ob_get_level ob_get_status ob_get_contents ob_implicit_flush ob_list_handlers ksort krsort natsort natcasesort asort arsort sort rsort usort uasort uksort shuffle array_walk count end prev next reset current key min max in_array array_search extract compact array_fill range array_multisort array_push array_pop array_shift array_unshift array_splice array_slice array_merge array_merge_recursive array_keys array_values array_count_values array_reverse array_reduce array_pad array_flip array_change_key_case array_rand array_unique array_intersect array_intersect_assoc array_diff array_diff_assoc array_sum array_filter array_map array_chunk array_key_exists pos sizeof key_exists assert assert_options version_compare ftok str_rot13 aggregate session_name session_module_name session_save_path session_id session_regenerate_id session_decode session_register session_unregister session_is_registered session_encode session_start session_destroy session_unset session_set_save_handler session_cache_limiter session_cache_expire session_set_cookie_params session_get_cookie_params session_write_close preg_match preg_match_all preg_replace preg_replace_callback preg_split preg_quote preg_grep overload ctype_alnum ctype_alpha ctype_cntrl ctype_digit ctype_lower ctype_graph ctype_print ctype_punct ctype_space ctype_upper ctype_xdigit virtual apache_request_headers apache_note apache_lookup_uri apache_child_terminate apache_setenv apache_response_headers apache_get_version getallheaders mysql_connect mysql_pconnect mysql_close mysql_select_db mysql_create_db mysql_drop_db mysql_query mysql_unbuffered_query mysql_db_query mysql_list_dbs mysql_list_tables mysql_list_fields mysql_list_processes mysql_error mysql_errno mysql_affected_rows mysql_insert_id mysql_result mysql_num_rows mysql_num_fields mysql_fetch_row mysql_fetch_array mysql_fetch_assoc mysql_fetch_object mysql_data_seek mysql_fetch_lengths mysql_fetch_field mysql_field_seek mysql_free_result mysql_field_name mysql_field_table mysql_field_len mysql_field_type mysql_field_flags mysql_escape_string mysql_real_escape_string mysql_stat mysql_thread_id mysql_client_encoding mysql_get_client_info mysql_get_host_info mysql_get_proto_info mysql_get_server_info mysql_info mysql mysql_fieldname mysql_fieldtable mysql_fieldlen mysql_fieldtype mysql_fieldflags mysql_selectdb mysql_createdb mysql_dropdb mysql_freeresult mysql_numfields mysql_numrows mysql_listdbs mysql_listtables mysql_listfields mysql_db_name mysql_dbname mysql_tablename mysql_table_name pg_connect pg_pconnect pg_close pg_connection_status pg_connection_busy pg_connection_reset pg_host pg_dbname pg_port pg_tty pg_options pg_ping pg_query pg_send_query pg_cancel_query pg_fetch_result pg_fetch_row pg_fetch_assoc pg_fetch_array pg_fetch_object pg_fetch_all pg_affected_rows pg_get_result pg_result_seek pg_result_status pg_free_result pg_last_oid pg_num_rows pg_num_fields pg_field_name pg_field_num pg_field_size pg_field_type pg_field_prtlen pg_field_is_null pg_get_notify pg_get_pid pg_result_error pg_last_error pg_last_notice pg_put_line pg_end_copy pg_copy_to pg_copy_from pg_trace pg_untrace pg_lo_create pg_lo_unlink pg_lo_open pg_lo_close pg_lo_read pg_lo_write pg_lo_read_all pg_lo_import pg_lo_export pg_lo_seek pg_lo_tell pg_escape_string pg_escape_bytea pg_unescape_bytea pg_client_encoding pg_set_client_encoding pg_meta_data pg_convert pg_insert pg_update pg_delete pg_select pg_exec pg_getlastoid pg_cmdtuples pg_errormessage pg_numrows pg_numfields pg_fieldname pg_fieldsize pg_fieldtype pg_fieldnum pg_fieldprtlen pg_fieldisnull pg_freeresult pg_result pg_loreadall pg_locreate pg_lounlink pg_loopen pg_loclose pg_loread pg_lowrite pg_loimport pg_loexport http_response_code get_declared_traits getimagesizefromstring socket_import_stream stream_set_chunk_size trait_exists header_register_callback class_uses session_status session_register_shutdown echo print global static exit array empty eval isset unset die include require include_once require_once json_decode json_encode json_last_error json_last_error_msg curl_close curl_copy_handle curl_errno curl_error curl_escape curl_exec curl_file_create curl_getinfo curl_init curl_multi_add_handle curl_multi_close curl_multi_exec curl_multi_getcontent curl_multi_info_read curl_multi_init curl_multi_remove_handle curl_multi_select curl_multi_setopt curl_multi_strerror curl_pause curl_reset curl_setopt_array curl_setopt curl_share_close curl_share_init curl_share_setopt curl_strerror curl_unescape curl_version mysqli_affected_rows mysqli_autocommit mysqli_change_user mysqli_character_set_name mysqli_close mysqli_commit mysqli_connect_errno mysqli_connect_error mysqli_connect mysqli_data_seek mysqli_debug mysqli_dump_debug_info mysqli_errno mysqli_error_list mysqli_error mysqli_fetch_all mysqli_fetch_array mysqli_fetch_assoc mysqli_fetch_field_direct mysqli_fetch_field mysqli_fetch_fields mysqli_fetch_lengths mysqli_fetch_object mysqli_fetch_row mysqli_field_count mysqli_field_seek mysqli_field_tell mysqli_free_result mysqli_get_charset mysqli_get_client_info mysqli_get_client_stats mysqli_get_client_version mysqli_get_connection_stats mysqli_get_host_info mysqli_get_proto_info mysqli_get_server_info mysqli_get_server_version mysqli_info mysqli_init mysqli_insert_id mysqli_kill mysqli_more_results mysqli_multi_query mysqli_next_result mysqli_num_fields mysqli_num_rows mysqli_options mysqli_ping mysqli_prepare mysqli_query mysqli_real_connect mysqli_real_escape_string mysqli_real_query mysqli_reap_async_query mysqli_refresh mysqli_rollback mysqli_select_db mysqli_set_charset mysqli_set_local_infile_default mysqli_set_local_infile_handler mysqli_sqlstate mysqli_ssl_set mysqli_stat mysqli_stmt_init mysqli_store_result mysqli_thread_id mysqli_thread_safe mysqli_use_result mysqli_warning_count"; CodeMirror.registerHelper("hintWords", "php", [phpKeywords, phpAtoms, phpBuiltin].join(" ").split(" ")); CodeMirror.registerHelper("wordChars", "php", /[\w$]/); From d46fd84445330c370d61c9cf38fc5e2c90236e08 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 14 Aug 2014 18:02:28 +0200 Subject: [PATCH 0901/4131] [sql-hint addon] Clean up, fix handling of whitespace Closes #2761 --- addon/hint/sql-hint.js | 110 ++++++++++++++++++++--------------------- mode/sql/index.html | 10 +++- 2 files changed, 62 insertions(+), 58 deletions(-) diff --git a/addon/hint/sql-hint.js b/addon/hint/sql-hint.js index fd58b8834e..cc756a2485 100644 --- a/addon/hint/sql-hint.js +++ b/addon/hint/sql-hint.js @@ -21,7 +21,7 @@ function getKeywords(editor) { var mode = editor.doc.modeOption; - if(mode === "sql") mode = "text/x-sql"; + if (mode === "sql") mode = "text/x-sql"; return CodeMirror.resolveMode(mode).keywords; } @@ -32,12 +32,12 @@ } function addMatches(result, search, wordlist, formatter) { - for(var word in wordlist) { - if(!wordlist.hasOwnProperty(word)) continue; - if(Array.isArray(wordlist)) { + for (var word in wordlist) { + if (!wordlist.hasOwnProperty(word)) continue; + if (Array.isArray(wordlist)) { word = wordlist[word]; } - if(match(search, word)) { + if (match(search, word)) { result.push(formatter(word)); } } @@ -49,33 +49,30 @@ var string = token.string.substr(1); var prevCur = Pos(cur.line, token.start); var table = editor.getTokenAt(prevCur).string; - if( !tables.hasOwnProperty( table ) ){ + if (!tables.hasOwnProperty(table)) table = findTableByAlias(table, editor); - } var columns = tables[table]; - if(!columns) { - return; - } - addMatches(result, string, columns, - function(w) {return "." + w;}); + if (!columns) return; + + addMatches(result, string, columns, function(w) {return "." + w;}); } function eachWord(lineText, f) { - if( !lineText ){return;} + if (!lineText) return; var excepted = /[,;]/g; - var words = lineText.split( " " ); - for( var i = 0; i < words.length; i++ ){ - f( words[i]?words[i].replace( excepted, '' ) : '' ); + var words = lineText.split(" "); + for (var i = 0; i < words.length; i++) { + f(words[i]?words[i].replace(excepted, '') : ''); } } - function convertCurToNumber( cur ){ + function convertCurToNumber(cur) { // max characters of a line is 999,999. - return cur.line + cur.ch / Math.pow( 10, 6 ); + return cur.line + cur.ch / Math.pow(10, 6); } - function convertNumberToCur( num ){ - return Pos(Math.floor( num ), +num.toString().split( '.' ).pop()); + function convertNumberToCur(num) { + return Pos(Math.floor(num), +num.toString().split('.').pop()); } function findTableByAlias(alias, editor) { @@ -86,26 +83,26 @@ var table = ""; var separator = []; var validRange = { - start: Pos( 0, 0 ), - end: Pos( editor.lastLine(), editor.getLineHandle( editor.lastLine() ).length ) + start: Pos(0, 0), + end: Pos(editor.lastLine(), editor.getLineHandle(editor.lastLine()).length) }; //add separator - var indexOfSeparator = fullQuery.indexOf( CONS.QUERY_DIV ); - while( indexOfSeparator != -1 ){ - separator.push( doc.posFromIndex(indexOfSeparator)); - indexOfSeparator = fullQuery.indexOf( CONS.QUERY_DIV, indexOfSeparator+1); + var indexOfSeparator = fullQuery.indexOf(CONS.QUERY_DIV); + while(indexOfSeparator != -1) { + separator.push(doc.posFromIndex(indexOfSeparator)); + indexOfSeparator = fullQuery.indexOf(CONS.QUERY_DIV, indexOfSeparator+1); } - separator.unshift( Pos( 0, 0 ) ); - separator.push( Pos( editor.lastLine(), editor.getLineHandle( editor.lastLine() ).text.length ) ); + separator.unshift(Pos(0, 0)); + separator.push(Pos(editor.lastLine(), editor.getLineHandle(editor.lastLine()).text.length)); - //find valieRange + //find valid range var prevItem = 0; - var current = convertCurToNumber( editor.getCursor() ); - for( var i=0; i< separator.length; i++){ - var _v = convertCurToNumber( separator[i] ); - if( current > prevItem && current <= _v ){ - validRange = { start: convertNumberToCur( prevItem ), end: convertNumberToCur( _v ) }; + var current = convertCurToNumber(editor.getCursor()); + for (var i=0; i< separator.length; i++) { + var _v = convertCurToNumber(separator[i]); + if (current > prevItem && current <= _v) { + validRange = { start: convertNumberToCur(prevItem), end: convertNumberToCur(_v) }; break; } prevItem = _v; @@ -113,52 +110,51 @@ var query = doc.getRange(validRange.start, validRange.end, false); - for(var i=0; i < query.length; i++){ + for (var i = 0; i < query.length; i++) { var lineText = query[i]; - eachWord( lineText, function( word ){ + eachWord(lineText, function(word) { var wordUpperCase = word.toUpperCase(); - if( wordUpperCase === aliasUpperCase && tables.hasOwnProperty( previousWord ) ){ + if (wordUpperCase === aliasUpperCase && tables.hasOwnProperty(previousWord)) { table = previousWord; } - if( wordUpperCase !== CONS.ALIAS_KEYWORD ){ + if (wordUpperCase !== CONS.ALIAS_KEYWORD) { previousWord = word; } }); - if( table ){ break; } + if (table) break; } return table; } - function sqlHint(editor, options) { + CodeMirror.registerHelper("hint", "sql", function(editor, options) { tables = (options && options.tables) || {}; keywords = keywords || getKeywords(editor); var cur = editor.getCursor(); - var token = editor.getTokenAt(cur), end = token.end; var result = []; - var search = token.string.trim(); - + var token = editor.getTokenAt(cur), start, end, search; + if (token.string.match(/^\.?[\w@]+$/)) { + search = token.string; + start = token.start; + end = token.end; + } else { + start = end = cur.ch; + search = ""; + } if (search.charAt(0) == ".") { columnCompletion(result, editor); if (!result.length) { - while (token.start && search.charAt(0) == ".") { + 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;}); + addMatches(result, search, tables, function(w) {return w;}); } } else { - addMatches(result, search, keywords, - function(w) {return w.toUpperCase();}); - addMatches(result, search, tables, - function(w) {return w;}); + addMatches(result, search, tables, function(w) {return w;}); + addMatches(result, search, keywords, function(w) {return w.toUpperCase();}); } - return { - list: result, - from: Pos(cur.line, token.start), - to: Pos(cur.line, end) - }; - } - CodeMirror.registerHelper("hint", "sql", sqlHint); + return {list: result, from: Pos(cur.line, start), to: Pos(cur.line, end)}; + }); }); diff --git a/mode/sql/index.html b/mode/sql/index.html index 79a2e74e0f..7dd5f3075e 100644 --- a/mode/sql/index.html +++ b/mode/sql/index.html @@ -7,6 +7,9 @@ + + + + + +
    +

    Modelica mode

    + +
    + + + +

    Simple mode that tries to handle Modelica as well as it can.

    + +

    MIME types defined: text/x-modelica + (Modlica code).

    +
    diff --git a/mode/modelica/modelica.js b/mode/modelica/modelica.js new file mode 100644 index 0000000000..77ec7a3c18 --- /dev/null +++ b/mode/modelica/modelica.js @@ -0,0 +1,245 @@ +// CodeMirror, copyright (c) by Marijn Haverbeke and others +// Distributed under an MIT license: http://codemirror.net/LICENSE + +// Modelica support for CodeMirror, copyright (c) by Lennart Ochel + +(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.defineMode("modelica", function(config, parserConfig) { + + var indentUnit = config.indentUnit; + var keywords = parserConfig.keywords || {}; + var builtin = parserConfig.builtin || {}; + var atoms = parserConfig.atoms || {}; + + var isSingleOperatorChar = /[;=\(:\),{}.*<>+\-\/^\[\]]/; + var isDoubleOperatorChar = /(:=|<=|>=|==|<>|\.\+|\.\-|\.\*|\.\/|\.\^)/; + var isDigit = /[0-9]/; + var isNonDigit = /[_a-zA-Z]/; + + function tokenLineComment(stream, state) { + stream.skipToEnd(); + state.tokenize = null; + return "comment"; + } + + function tokenBlockComment(stream, state) { + var maybeEnd = false, ch; + while (ch = stream.next()) { + if (maybeEnd && ch == "/") { + state.tokenize = null; + break; + } + maybeEnd = (ch == "*"); + } + return "comment"; + } + + function tokenString(stream, state) { + var escaped = false, ch; + while ((ch = stream.next()) != null) { + if (ch == '"' && !escaped) { + state.tokenize = null; + state.sol = false; + break; + } + escaped = !escaped && ch == "\\"; + } + + return "string"; + } + + function tokenIdent(stream, state) { + stream.eatWhile(isDigit); + while (stream.eat(isDigit) || stream.eat(isNonDigit)) { } + + + var cur = stream.current(); + + if(state.sol && (cur == "package" || cur == "model" || cur == "when" || cur == "connector")) state.level++; + else if(state.sol && cur == "end" && state.level > 0) state.level--; + + state.tokenize = null; + state.sol = false; + + if (keywords.propertyIsEnumerable(cur)) return "keyword"; + else if (builtin.propertyIsEnumerable(cur)) return "builtin"; + else if (atoms.propertyIsEnumerable(cur)) return "atom"; + else return "variable"; + } + + function tokenQIdent(stream, state) { + while (stream.eat(/[^']/)) { } + + state.tokenize = null; + state.sol = false; + + if(stream.eat("'")) + return "variable"; + else + return "error"; + } + + function tokenUnsignedNuber(stream, state) { + stream.eatWhile(isDigit); + if (stream.eat('.')) { + stream.eatWhile(isDigit); + } + if (stream.eat('e') || stream.eat('E')) { + if (!stream.eat('-')) + stream.eat('+'); + stream.eatWhile(isDigit); + } + + state.tokenize = null; + state.sol = false; + return "number"; + } + + // Interface + return { + startState: function() { + return { + tokenize: null, + level: 0, + sol: true + }; + }, + + token: function(stream, state) { + if(state.tokenize != null) { + return state.tokenize(stream, state); + } + + if(stream.sol()) { + state.sol = true; + } + + // WHITESPACE + if(stream.eatSpace()) { + state.tokenize = null; + return null; + } + + var ch = stream.next(); + + // LINECOMMENT + if(ch == '/' && stream.eat('/')) { + state.tokenize = tokenLineComment; + } + // BLOCKCOMMENT + else if(ch == '/' && stream.eat('*')) { + state.tokenize = tokenBlockComment; + } + // TWO SYMBOL TOKENS + else if(isDoubleOperatorChar.test(ch+stream.peek())) { + stream.next(); + state.tokenize = null; + return "operator"; + } + // SINGLE SYMBOL TOKENS + else if(isSingleOperatorChar.test(ch)) { + state.tokenize = null; + return "operator"; + } + // IDENT + else if(isNonDigit.test(ch)) { + state.tokenize = tokenIdent; + } + // Q-IDENT + else if(ch == "'" && stream.peek() && stream.peek() != "'") { + state.tokenize = tokenQIdent; + } + // STRING + else if(ch == '"') { + state.tokenize = tokenString; + } + // UNSIGNED_NUBER + else if(isDigit.test(ch)) { + state.tokenize = tokenUnsignedNuber; + } + // ERROR + else { + state.tokenize = null; + return "error"; + } + + return state.tokenize(stream, state); + }, + + indent: function(state, textAfter) { + if (state.tokenize != null) return CodeMirror.Pass; + + var level = state.level; + if(/(algorithm)/.test(textAfter)) level--; + if(/(equation)/.test(textAfter)) level--; + if(/(initial algorithm)/.test(textAfter)) level--; + if(/(initial equation)/.test(textAfter)) level--; + if(/(end)/.test(textAfter)) level--; + + if(level > 0) + return indentUnit*level; + else + return 0; + }, + + blockCommentStart: "/*", + blockCommentEnd: "*/", + lineComment: "//" + }; + }); + + function words(str) { + var obj = {}, words = str.split(" "); + for (var i=0; i Date: Wed, 27 Aug 2014 00:39:53 -0700 Subject: [PATCH 0920/4131] [python mode] Make 'in' a keyword --- mode/python/python.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mode/python/python.js b/mode/python/python.js index 45dd63ba48..4e1f296ae1 100644 --- a/mode/python/python.js +++ b/mode/python/python.js @@ -15,12 +15,12 @@ return new RegExp("^((" + words.join(")|(") + "))\\b"); } - var wordOperators = wordRegexp(["and", "or", "not", "is", "in"]); + var wordOperators = wordRegexp(["and", "or", "not", "is"]); var commonKeywords = ["as", "assert", "break", "class", "continue", "def", "del", "elif", "else", "except", "finally", "for", "from", "global", "if", "import", "lambda", "pass", "raise", "return", - "try", "while", "with", "yield"]; + "try", "while", "with", "yield", "in"]; var commonBuiltins = ["abs", "all", "any", "bin", "bool", "bytearray", "callable", "chr", "classmethod", "compile", "complex", "delattr", "dict", "dir", "divmod", "enumerate", "eval", "filter", "float", "format", "frozenset", From 43379968f6a62b89e2b350acd9174971e3e50706 Mon Sep 17 00:00:00 2001 From: Hiroyuki Makino Date: Thu, 28 Aug 2014 23:03:04 +0900 Subject: [PATCH 0921/4131] [release notes] Fix section structure --- doc/releases.html | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/doc/releases.html b/doc/releases.html index 4b6d384b9e..f88a0373a6 100644 --- a/doc/releases.html +++ b/doc/releases.html @@ -25,9 +25,9 @@

    Release notes and version history

    -
    +
    -

    Version 4.x

    +

    Version 4.x

    21-08-2014: Version 4.5:

    @@ -114,7 +114,11 @@

    Version 4.x

  • Full list of patches.
  • -

    Version 3.x

    +
    + +
    + +

    Version 3.x

    22-04-2014: Version 3.24:

    From 3d8c1e506fd80feeb28a873a6dc6d1087d82327a Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 1 Sep 2014 13:32:06 +0200 Subject: [PATCH 0922/4131] Export findWordAt Closes #2790 --- doc/manual.html | 4 ++++ lib/codemirror.js | 42 +++++++++++++++++++++--------------------- 2 files changed, 25 insertions(+), 21 deletions(-) diff --git a/doc/manual.html b/doc/manual.html index 6069fa6aea..02f3a59aaf 100644 --- a/doc/manual.html +++ b/doc/manual.html @@ -1312,6 +1312,10 @@

    Cursor and selection methods

    be "line" or "page". The other arguments and the returned value have the same interpretation as they have in findPosH. + +
    cm.findWordAt(pos: {line, ch}) → {anchor: {line, ch}, head: {line, ch}}
    +
    Returns the start and end of the 'word' (the stretch of + letters, whitespace, or punctuation) at the given position.

    Configuration methods

    diff --git a/lib/codemirror.js b/lib/codemirror.js index 2c3b17df67..4270b98a45 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -2528,7 +2528,7 @@ var pos = posFromMouse(cm, e); if (!pos || clickInGutter(cm, e) || eventInWidget(cm.display, e)) return; e_preventDefault(e); - var word = findWordAt(cm, pos); + var word = cm.findWordAt(pos); extendSelection(cm.doc, word.anchor, word.head); })); else @@ -2807,7 +2807,7 @@ start = posFromMouse(cm, e, true, true); ourIndex = -1; } else if (type == "double") { - var word = findWordAt(cm, start); + var word = cm.findWordAt(start); if (cm.display.shift || doc.extend) ourRange = extendRange(doc, ourRange, word.anchor, word.head); else @@ -2861,7 +2861,7 @@ var anchor = oldRange.anchor, head = pos; if (type != "single") { if (type == "double") - var range = findWordAt(cm, pos); + var range = cm.findWordAt(pos); else var range = new Range(Pos(pos.line, 0), clipPos(doc, Pos(pos.line + 1, 0))); if (cmp(range.anchor, anchor) > 0) { @@ -3999,24 +3999,6 @@ return target; } - // Find the word at the given position (as returned by coordsChar). - function findWordAt(cm, pos) { - var doc = cm.doc, line = getLine(doc, pos.line).text; - var start = pos.ch, end = pos.ch; - if (line) { - var helper = cm.getHelper(pos, "wordChars"); - if ((pos.xRel < 0 || end == line.length) && start) --start; else ++end; - var startChar = line.charAt(start); - var check = isWordChar(startChar, helper) - ? function(ch) { return isWordChar(ch, helper); } - : /\s/.test(startChar) ? function(ch) {return /\s/.test(ch);} - : function(ch) {return !/\s/.test(ch) && !isWordChar(ch);}; - while (start > 0 && check(line.charAt(start - 1))) --start; - while (end < line.length && check(line.charAt(end))) ++end; - } - return new Range(Pos(pos.line, start), Pos(pos.line, end)); - } - // EDITOR METHODS // The publicly visible API. Note that methodOp(f) means @@ -4358,6 +4340,24 @@ doc.sel.ranges[i].goalColumn = goals[i]; }), + // Find the word at the given position (as returned by coordsChar). + findWordAt: function(pos) { + var doc = this.doc, line = getLine(doc, pos.line).text; + var start = pos.ch, end = pos.ch; + if (line) { + var helper = this.getHelper(pos, "wordChars"); + if ((pos.xRel < 0 || end == line.length) && start) --start; else ++end; + var startChar = line.charAt(start); + var check = isWordChar(startChar, helper) + ? function(ch) { return isWordChar(ch, helper); } + : /\s/.test(startChar) ? function(ch) {return /\s/.test(ch);} + : function(ch) {return !/\s/.test(ch) && !isWordChar(ch);}; + while (start > 0 && check(line.charAt(start - 1))) --start; + while (end < line.length && check(line.charAt(end))) ++end; + } + return new Range(Pos(pos.line, start), Pos(pos.line, end)); + }, + toggleOverwrite: function(value) { if (value != null && value == this.state.overwrite) return; if (this.state.overwrite = !this.state.overwrite) From 9b87ca9ca4f8c81f84ff755e921ddaf3aa7373fc Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 1 Sep 2014 13:34:35 +0200 Subject: [PATCH 0923/4131] [merge addon] Add diff_match_patch as explicit dependency Closes #2783 --- addon/merge/merge.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/addon/merge/merge.js b/addon/merge/merge.js index d9b277664b..da3ea47ccf 100644 --- a/addon/merge/merge.js +++ b/addon/merge/merge.js @@ -1,17 +1,17 @@ // CodeMirror, copyright (c) by Marijn Haverbeke and others // Distributed under an MIT license: http://codemirror.net/LICENSE +// declare global: diff_match_patch, DIFF_INSERT, DIFF_DELETE, DIFF_EQUAL + (function(mod) { if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); + mod(require("../../lib/codemirror"), require("diff_match_patch")); else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); + define(["../../lib/codemirror", "diff_match_patch"], mod); else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { + mod(CodeMirror, diff_match_patch); +})(function(CodeMirror, diff_match_patch) { "use strict"; - // declare global: diff_match_patch, DIFF_INSERT, DIFF_DELETE, DIFF_EQUAL - var Pos = CodeMirror.Pos; var svgNS = "http://www.w3.org/2000/svg"; From 59b7b9082be50d51e9b5589e6957668c5d3cb35a Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 1 Sep 2014 13:44:22 +0200 Subject: [PATCH 0924/4131] Add Hebrew code range to nonASCIISingleCaseWordChar regexp Fixes detection of Hebrew letters as word characters Closes #2789 --- lib/codemirror.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/codemirror.js b/lib/codemirror.js index 4270b98a45..f06b99bd72 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -7295,7 +7295,7 @@ return function(){return f.apply(null, args);}; } - var nonASCIISingleCaseWordChar = /[\u00df\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc\uac00-\ud7af]/; + var nonASCIISingleCaseWordChar = /[\u00df\u0590-\u05f4\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc\uac00-\ud7af]/; var isWordCharBasic = CodeMirror.isWordChar = function(ch) { return /\w/.test(ch) || ch > "\x80" && (ch.toUpperCase() != ch.toLowerCase() || nonASCIISingleCaseWordChar.test(ch)); From 623eb7badb58f5d7bc9bbd836f86f046180e2a1c Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 1 Sep 2014 17:59:23 +0200 Subject: [PATCH 0925/4131] Force scroll update from swapDoc Issue #2714 --- lib/codemirror.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/codemirror.js b/lib/codemirror.js index f06b99bd72..c865bc560b 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -2090,11 +2090,11 @@ display.wheelStartX = display.wheelStartY = null; // Propagate the scroll position to the actual DOM scroller - if (op.scrollTop != null && display.scroller.scrollTop != op.scrollTop) { + if (op.scrollTop != null && (display.scroller.scrollTop != op.scrollTop || op.forceScroll)) { var top = Math.max(0, Math.min(display.scroller.scrollHeight - display.scroller.clientHeight, op.scrollTop)); display.scroller.scrollTop = display.scrollbarV.scrollTop = doc.scrollTop = top; } - if (op.scrollLeft != null && display.scroller.scrollLeft != op.scrollLeft) { + if (op.scrollLeft != null && (display.scroller.scrollLeft != op.scrollLeft || op.forceScroll)) { var left = Math.max(0, Math.min(display.scroller.scrollWidth - display.scroller.clientWidth, op.scrollLeft)); display.scroller.scrollLeft = display.scrollbarH.scrollLeft = doc.scrollLeft = left; alignHorizontally(cm); @@ -4444,6 +4444,7 @@ clearCaches(this); resetInput(this); this.scrollTo(doc.scrollLeft, doc.scrollTop); + this.curOp.forceScroll = true; signalLater(this, "swapDoc", this, old); return old; }), From 376f3ec90d05272459bf0b79d4ff9005a284705e Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 1 Sep 2014 18:04:52 +0200 Subject: [PATCH 0926/4131] [sass mode] Make sure indentCount is initialized propertly Issue #2786 --- mode/sass/sass.js | 1 + 1 file changed, 1 insertion(+) diff --git a/mode/sass/sass.js b/mode/sass/sass.js index 68df323e18..b792a02aa3 100644 --- a/mode/sass/sass.js +++ b/mode/sass/sass.js @@ -303,6 +303,7 @@ CodeMirror.defineMode("sass", function(config) { return { tokenizer: tokenBase, scopes: [{offset: 0, type: "sass"}], + indentCount: 0, definedVars: [], definedMixins: [] }; From cb5416f1229e2c8555784cb089916a5953c07b1b Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Wed, 3 Sep 2014 08:36:11 +0200 Subject: [PATCH 0927/4131] [markdown mode] Fix handling of escaped characters Issue #2792 --- mode/markdown/markdown.js | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/mode/markdown/markdown.js b/mode/markdown/markdown.js index 81ed24e8d3..90a9282f85 100644 --- a/mode/markdown/markdown.js +++ b/mode/markdown/markdown.js @@ -360,15 +360,9 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) { var ch = stream.next(); - if (state.escape) { - state.escape = false; - return getType(state); - } - if (ch === '\\') { - if (modeCfg.highlightFormatting) state.formatting = "escape"; - state.escape = true; - return getType(state); + stream.next(); + if (modeCfg.highlightFormatting) return getType(state) + " escape"; } // Matches link titles present on next line @@ -650,7 +644,6 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) { inline: inlineNormal, text: handleText, - escape: false, formatting: false, linkText: false, linkHref: false, @@ -683,7 +676,6 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) { inline: s.inline, text: s.text, - escape: false, formatting: false, linkTitle: s.linkTitle, em: s.em, @@ -718,9 +710,6 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) { state.thisLineHasContent = true; } - // Reset state.escape - state.escape = false; - // Reset state.taskList state.taskList = false; From 31319ee225a60dcc750ba01a40e70bdedaaaafc7 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Wed, 3 Sep 2014 08:42:11 +0200 Subject: [PATCH 0928/4131] [markdown mode] Make test pass --- mode/markdown/markdown.js | 5 ++++- mode/markdown/test.js | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/mode/markdown/markdown.js b/mode/markdown/markdown.js index 90a9282f85..1bad78d65e 100644 --- a/mode/markdown/markdown.js +++ b/mode/markdown/markdown.js @@ -362,7 +362,10 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) { if (ch === '\\') { stream.next(); - if (modeCfg.highlightFormatting) return getType(state) + " escape"; + if (modeCfg.highlightFormatting) { + var type = getType(state); + return type ? type + " formatting-escape" : "formatting-escape"; + } } // Matches link titles present on next line diff --git a/mode/markdown/test.js b/mode/markdown/test.js index 77a3b659c0..96ca1aefc7 100644 --- a/mode/markdown/test.js +++ b/mode/markdown/test.js @@ -54,7 +54,7 @@ "[link&formatting&formatting-link <][link user@example.com][link&formatting&formatting-link >]"); FT("formatting_escape", - "[formatting&formatting-escape \\]*"); + "[formatting-escape \\*]"); MT("plainText", "foo"); From f593e03a09a156f1a7824757beaa001369f11422 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Wed, 3 Sep 2014 22:23:25 +0200 Subject: [PATCH 0929/4131] Set a min height on the lines element to prevent collapsing of wrapper Issue #2765 --- lib/codemirror.css | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/codemirror.css b/lib/codemirror.css index c0897771aa..1ab8acb296 100644 --- a/lib/codemirror.css +++ b/lib/codemirror.css @@ -213,6 +213,7 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;} .CodeMirror-lines { cursor: text; + min-height: 1px; /* prevents collapsing before first draw */ } .CodeMirror pre { /* Reset some styles that the rest of the page might have set */ From 17c992e979daf3a3aa75926d38144e3c9d4dc064 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 4 Sep 2014 08:44:24 +0200 Subject: [PATCH 0930/4131] Only apply IE<11 zooming compensation for client rects when getting rect from a range It does not happen when measuring a node Issue #2665 --- lib/codemirror.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/codemirror.js b/lib/codemirror.js index c865bc560b..151ee91a66 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -1665,6 +1665,7 @@ start = start - 1; collapse = "right"; } + if (ie && ie_version < 11) rect = maybeUpdateRectForZooming(cm.display.measure, rect); } else { // If it is a widget, simply get the box for the whole widget. if (start > 0) collapse = bias = "right"; var rects; @@ -1681,8 +1682,6 @@ rect = nullRect; } - if (ie && ie_version < 11) rect = maybeUpdateRectForZooming(cm.display.measure, rect); - var rtop = rect.top - prepared.rect.top, rbot = rect.bottom - prepared.rect.top; var mid = (rtop + rbot) / 2; var heights = prepared.view.measure.heights; From 616339b47245b3a044057afa460a3768ffa0369c Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 8 Sep 2014 12:52:49 +0200 Subject: [PATCH 0931/4131] [closetag addon] Work better with htmlmixed mode It now closes script and style tags when the slash is typed Closes #2797 --- addon/edit/closetag.js | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/addon/edit/closetag.js b/addon/edit/closetag.js index 69ea4446be..a0bec7dd43 100644 --- a/addon/edit/closetag.js +++ b/addon/edit/closetag.js @@ -102,11 +102,25 @@ var pos = ranges[i].head, tok = cm.getTokenAt(pos); var inner = CodeMirror.innerMode(cm.getMode(), tok.state), state = inner.state; if (tok.type == "string" || tok.string.charAt(0) != "<" || - tok.start != pos.ch - 1 || inner.mode.name != "xml" || - !state.context || !state.context.tagName || - closingTagExists(cm, state.context.tagName, pos, state)) + tok.start != pos.ch - 1) return CodeMirror.Pass; - replacements[i] = "/" + state.context.tagName + ">"; + // Kludge to get around the fact that we are not in XML mode + // when completing in JS/CSS snippet in htmlmixed mode. Does not + // work for other XML embedded languages (there is no general + // way to go from a mixed mode to its current XML state). + if (inner.mode.name != "xml") { + if (cm.getMode().name == "htmlmixed" && inner.mode.name == "javascript") + replacements[i] = "/script>"; + else if (cm.getMode().name == "htmlmixed" && inner.mode.name == "css") + replacements[i] = "/style>"; + else + return CodeMirror.Pass; + } else { + if (!state.context || !state.context.tagName || + closingTagExists(cm, state.context.tagName, pos, state)) + return CodeMirror.Pass; + replacements[i] = "/" + state.context.tagName + ">"; + } } cm.replaceSelections(replacements); ranges = cm.listSelections(); From 7817708c3165f1ca376bdc7181df6d036cb90ad8 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 8 Sep 2014 13:03:54 +0200 Subject: [PATCH 0932/4131] [javascript mode] Fix parsing of argument-less fat arrow functions Closes #2794 --- mode/javascript/javascript.js | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/mode/javascript/javascript.js b/mode/javascript/javascript.js index 46616bc021..2e24d3a55b 100644 --- a/mode/javascript/javascript.js +++ b/mode/javascript/javascript.js @@ -391,7 +391,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { function maybeoperatorNoComma(type, value, noComma) { var me = noComma == false ? maybeoperatorComma : maybeoperatorNoComma; var expr = noComma == false ? expression : expressionNoComma; - if (value == "=>") return cont(pushcontext, noComma ? arrowBodyNoComma : arrowBody, popcontext); + if (type == "=>") return cont(pushcontext, noComma ? arrowBodyNoComma : arrowBody, popcontext); if (type == "operator") { if (/\+\+|--/.test(value)) return cont(me); if (value == "?") return cont(expression, expect(":"), expr); @@ -417,13 +417,11 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { } function arrowBody(type) { findFatArrow(cx.stream, cx.state); - if (type == "{") return pass(statement); - return pass(expression); + return pass(type == "{" ? statement : expression); } function arrowBodyNoComma(type) { findFatArrow(cx.stream, cx.state); - if (type == "{") return pass(statement); - return pass(expressionNoComma); + return pass(type == "{" ? statement : expressionNoComma); } function maybelabel(type) { if (type == ":") return cont(poplex, statement); From 0a91c1427a2771a94731384f3537c78468be44f8 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 8 Sep 2014 13:22:02 +0200 Subject: [PATCH 0933/4131] [smalltalk mode] Use \s instead of space in regexps that denote whitespace Closes #2796 --- mode/smalltalk/smalltalk.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mode/smalltalk/smalltalk.js b/mode/smalltalk/smalltalk.js index 50f41cc615..bb510ba2e1 100644 --- a/mode/smalltalk/smalltalk.js +++ b/mode/smalltalk/smalltalk.js @@ -53,7 +53,7 @@ CodeMirror.defineMode('smalltalk', function(config) { stream.next(); token = nextSymbol(stream, new Context(nextSymbol, context)); } else { - if (stream.eatWhile(/[^ .{}\[\]()]/)) + if (stream.eatWhile(/[^\s.{}\[\]()]/)) token.name = 'string-2'; else token.name = 'meta'; @@ -61,7 +61,7 @@ CodeMirror.defineMode('smalltalk', function(config) { } else if (aChar === '$') { if (stream.next() === '<') { - stream.eatWhile(/[^ >]/); + stream.eatWhile(/[^\s>]/); stream.next(); } token.name = 'string-2'; From 1adaa01dbf7fb030b61731314dd245d9dbf8014e Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Tue, 9 Sep 2014 16:22:11 +0200 Subject: [PATCH 0934/4131] Add a requireJS demo --- addon/hint/html-hint.js | 4 ++-- demo/requirejs.html | 52 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 2 deletions(-) create mode 100644 demo/requirejs.html diff --git a/addon/hint/html-hint.js b/addon/hint/html-hint.js index addd9b7bc0..992218f288 100755 --- a/addon/hint/html-hint.js +++ b/addon/hint/html-hint.js @@ -3,9 +3,9 @@ (function(mod) { if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); + mod(require("../../lib/codemirror", "./xml-hint")); else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); + define(["../../lib/codemirror", "./xml-hint"], mod); else // Plain browser env mod(CodeMirror); })(function(CodeMirror) { diff --git a/demo/requirejs.html b/demo/requirejs.html new file mode 100644 index 0000000000..6399f8d769 --- /dev/null +++ b/demo/requirejs.html @@ -0,0 +1,52 @@ + + + + CodeMirror: HTML completion demo + + + + + + + + + + + + +
    +

    RequireJS module loading demo

    + +

    This demo does the same thing as + the HTML5 completion demo, but + loads its dependencies + with Require.js, rather than + explicitly. Press ctrl-space to activate + completion.

    + +
    + + +
    + From c012f411ee01c9802d046c2d76dc3b4b0001d67b Mon Sep 17 00:00:00 2001 From: Marcel Gerber Date: Tue, 9 Sep 2014 12:23:51 +0200 Subject: [PATCH 0935/4131] Improve isWordChar() for Arabic language --- lib/codemirror.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/codemirror.js b/lib/codemirror.js index 151ee91a66..ea2caaff62 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -7295,7 +7295,7 @@ return function(){return f.apply(null, args);}; } - var nonASCIISingleCaseWordChar = /[\u00df\u0590-\u05f4\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc\uac00-\ud7af]/; + var nonASCIISingleCaseWordChar = /[\u00df\u0590-\u05f4\u0600-\u06ff\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc\uac00-\ud7af]/; var isWordCharBasic = CodeMirror.isWordChar = function(ch) { return /\w/.test(ch) || ch > "\x80" && (ch.toUpperCase() != ch.toLowerCase() || nonASCIISingleCaseWordChar.test(ch)); From 8fac50ac265de832e08d428faffb36d464cb5bda Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 15 Sep 2014 11:32:38 +0200 Subject: [PATCH 0936/4131] Fix handling of electricChars in multi-line edits Closes #2804 --- lib/codemirror.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/codemirror.js b/lib/codemirror.js index ea2caaff62..246492a9fb 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -2456,16 +2456,16 @@ cm.options.smartIndent && range.head.ch < 100 && (!i || doc.sel.ranges[i - 1].head.line != range.head.line)) { var mode = cm.getModeAt(range.head); + var end = changeEnd(changeEvent); if (mode.electricChars) { for (var j = 0; j < mode.electricChars.length; j++) if (inserted.indexOf(mode.electricChars.charAt(j)) > -1) { - indentLine(cm, range.head.line, "smart"); + indentLine(cm, end.line, "smart"); break; } } else if (mode.electricInput) { - var end = changeEnd(changeEvent); if (mode.electricInput.test(getLine(doc, end.line).text.slice(0, end.ch))) - indentLine(cm, range.head.line, "smart"); + indentLine(cm, end.line, "smart"); } } } From c2ee5a6ec55f4542adc9838b467861019a3cad9b Mon Sep 17 00:00:00 2001 From: Marko Bonaci Date: Fri, 12 Sep 2014 19:14:38 +0200 Subject: [PATCH 0937/4131] Make parentheses visible while under `matchingbracket` rule Code: Brackets now become black when they are highlighted as "matching". JSON: key names are now in "white" (json was a bit saturated with orange - keys and string values). Cleanup: removed some unnecessary rules. Default face color normalized to #ffffec (was #ffffe9). --- theme/mbo.css | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/theme/mbo.css b/theme/mbo.css index 6cb2b18d9b..0ad6360b50 100644 --- a/theme/mbo.css +++ b/theme/mbo.css @@ -1,6 +1,10 @@ -/* Based on mbonaci's Brackets mbo theme */ +/****************************************************************/ +/* Based on mbonaci's Brackets mbo theme */ +/* https://github.com/mbonaci/global/blob/master/Mbo.tmTheme */ +/* Create your own: http://tmtheme-editor.herokuapp.com */ +/****************************************************************/ -.cm-s-mbo.CodeMirror {background: #2c2c2c; color: #ffffe9;} +.cm-s-mbo.CodeMirror {background: #2c2c2c; color: #ffffec;} .cm-s-mbo div.CodeMirror-selected {background: #716C62 !important;} .cm-s-mbo .CodeMirror-gutters {background: #4e4e4e; border-right: 0px;} .cm-s-mbo .CodeMirror-guttermarker { color: white; } @@ -15,6 +19,7 @@ .cm-s-mbo span.cm-property, .cm-s-mbo span.cm-attribute {color: #9ddfe9;} .cm-s-mbo span.cm-keyword {color: #ffb928;} .cm-s-mbo span.cm-string {color: #ffcf6c;} +.cm-s-mbo span.cm-string.cm-property {color: #ffffec;} .cm-s-mbo span.cm-variable {color: #ffffec;} .cm-s-mbo span.cm-variable-2 {color: #00a8c6;} @@ -23,17 +28,8 @@ .cm-s-mbo span.cm-tag {color: #9ddfe9;} .cm-s-mbo span.cm-link {color: #f54b07;} .cm-s-mbo span.cm-error {border-bottom: #636363; color: #ffffec;} +.cm-s-mbo span.cm-qualifier {color: #ffffec;} .cm-s-mbo .CodeMirror-activeline-background {background: #494b41 !important;} -.cm-s-mbo .CodeMirror-matchingbracket { - text-decoration: underline; - color: #f5e107 !important; - } - -.cm-s-mbo .CodeMirror-matchingtag { background: rgba(255, 255, 255, .37); } - -.cm-s-mbo span.cm-searching { - background-color: none; - background: none; - box-shadow: 0 0 0 1px #ffffec; -} +.cm-s-mbo .CodeMirror-matchingbracket {color: #222 !important;} +.cm-s-mbo .CodeMirror-matchingtag {background: rgba(255, 255, 255, .37);} From fcacef102486908b4331c8db9dc084daff7562bd Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 15 Sep 2014 15:29:33 +0200 Subject: [PATCH 0938/4131] [show-hint addon] Give active hint color more precedence To make it easy for client code to color completions without clashing with the selected styling. --- addon/hint/show-hint.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addon/hint/show-hint.css b/addon/hint/show-hint.css index 8a4ff052e3..924e638f7f 100644 --- a/addon/hint/show-hint.css +++ b/addon/hint/show-hint.css @@ -32,7 +32,7 @@ cursor: pointer; } -.CodeMirror-hint-active { +li.CodeMirror-hint-active { background: #08f; color: white; } From 640fbb28abf7dc4014c8c5ee6efe9309c091a98a Mon Sep 17 00:00:00 2001 From: snasa Date: Mon, 15 Sep 2014 22:30:25 -0700 Subject: [PATCH 0939/4131] Update shell.js --- mode/shell/shell.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mode/shell/shell.js b/mode/shell/shell.js index 77be75b97d..8e31f6f30b 100644 --- a/mode/shell/shell.js +++ b/mode/shell/shell.js @@ -128,7 +128,8 @@ CodeMirror.defineMode('shell', function() { startState: function() {return {tokens:[]};}, token: function(stream, state) { return tokenize(stream, state); - } + }, + lineComment: '#' }; }); From f09b6c5ec7bf2d7a7b2ee1ac8cc5c53b27f76f62 Mon Sep 17 00:00:00 2001 From: Daniele Di Sarli Date: Mon, 1 Sep 2014 21:53:17 +0200 Subject: [PATCH 0940/4131] Added wordsOnly option. Updated documentation. --- addon/search/match-highlighter.js | 32 +++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/addon/search/match-highlighter.js b/addon/search/match-highlighter.js index 14dd4d4184..e9a22721f7 100644 --- a/addon/search/match-highlighter.js +++ b/addon/search/match-highlighter.js @@ -8,12 +8,15 @@ // document. // // The option can be set to true to simply enable it, or to a -// {minChars, style, showToken} object to explicitly configure it. -// minChars is the minimum amount of characters that should be +// {minChars, style, wordsOnly, showToken, delay} object to explicitly +// configure it. minChars is the minimum amount of characters that should be // selected for the behavior to occur, and style is the token style to // apply to the matches. This will be prefixed by "cm-" to create an -// actual CSS class name. showToken, when enabled, will cause the -// current token to be highlighted when nothing is selected. +// actual CSS class name. If wordsOnly is enabled, the matches will be +// highlighted only if the selected text is a word. showToken, when enabled, +// will cause the current token to be highlighted when nothing is selected. +// delay is used to specify how much time to wait, in milliseconds, before +// highlighting the matches. (function(mod) { if (typeof exports == "object" && typeof module == "object") // CommonJS @@ -28,6 +31,7 @@ var DEFAULT_MIN_CHARS = 2; var DEFAULT_TOKEN_STYLE = "matchhighlight"; var DEFAULT_DELAY = 100; + var DEFAULT_WORDS_ONLY = false; function State(options) { if (typeof options == "object") { @@ -35,10 +39,12 @@ this.style = options.style; this.showToken = options.showToken; this.delay = options.delay; + this.wordsOnly = options.wordsOnly; } if (this.style == null) this.style = DEFAULT_TOKEN_STYLE; if (this.minChars == null) this.minChars = DEFAULT_MIN_CHARS; if (this.delay == null) this.delay = DEFAULT_DELAY; + if (this.wordsOnly == null) this.wordsOnly = DEFAULT_WORDS_ONLY; this.overlay = this.timeout = null; } @@ -81,12 +87,30 @@ } var from = cm.getCursor("from"), to = cm.getCursor("to"); if (from.line != to.line) return; + if (state.wordsOnly && !isWord(cm, from, to)) return; var selection = cm.getRange(from, to).replace(/^\s+|\s+$/g, ""); if (selection.length >= state.minChars) cm.addOverlay(state.overlay = makeOverlay(selection, false, state.style)); }); } + function isWord(cm, from, to) { + var str = cm.getRange(from, to); + if (str.match(/^\w+$/) !== null) { + if (from.ch > 0) { + var pos = {line: from.line, ch: from.ch - 1}; + var chr = cm.getRange(pos, from); + if (chr.match(/\W/) === null) return false; + } + if (to.ch < cm.getLine(from.line).length) { + var pos = {line: to.line, ch: to.ch + 1}; + var chr = cm.getRange(to, pos); + if (chr.match(/\W/) === null) return false; + } + return true; + } else return false; + } + function boundariesAround(stream, re) { return (!stream.start || !re.test(stream.string.charAt(stream.start - 1))) && (stream.pos == stream.string.length || !re.test(stream.string.charAt(stream.pos))); From cf15c70108b65fda224510177c9ac18e6727f9c0 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 18 Sep 2014 14:59:08 +0200 Subject: [PATCH 0941/4131] Add example of using markselection to style background to demo --- demo/markselection.html | 15 +++++++++++---- lib/codemirror.css | 9 ++++++++- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/demo/markselection.html b/demo/markselection.html index 93e38ec833..a182217fd5 100644 --- a/demo/markselection.html +++ b/demo/markselection.html @@ -12,6 +12,7 @@ .CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;} .CodeMirror-selected { background-color: blue !important; } .CodeMirror-selectedtext { color: white; } + .styled-background { background-color: #ff7; }
    -

    Addons

    +

    Addons

    The addon directory in the distribution contains a number of reusable components that implement extra editor diff --git a/index.html b/index.html index 7a2bbdcfce..cf9f943ac5 100644 --- a/index.html +++ b/index.html @@ -40,7 +40,7 @@

    CodeMirror is a versatile text editor implemented in JavaScript for the browser. It is specialized for - editing code, and comes with a number of language modes and addons + editing code, and comes with a number of language modes and addons that implement more advanced editing functionality.

    A rich programming API and a From 137737779912ef2cb67416e5e91852753acfe6ae Mon Sep 17 00:00:00 2001 From: Yunchi Luo Date: Tue, 14 Oct 2014 22:53:08 -0400 Subject: [PATCH 1004/4131] [vim] Fix uppercase key lookup --- keymap/vim.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/keymap/vim.js b/keymap/vim.js index 9abb0f52bc..a0a01e06c6 100644 --- a/keymap/vim.js +++ b/keymap/vim.js @@ -230,7 +230,7 @@ function lookupKey(e) { var keyCode = e.keyCode; if (modifierCodes.indexOf(keyCode) != -1) { return; } - var hasModifier = e.ctrlKey || e.shiftKey || e.metaKey; + var hasModifier = e.ctrlKey || e.metaKey; var key = CodeMirror.keyNames[keyCode]; key = specialKey[key] || key; var name = ''; From 0caeb00baf3abf8e89d0358fbc3c5ee7eb2d75dd Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 16 Oct 2014 09:45:57 +0200 Subject: [PATCH 1005/4131] Move ctrl-up/down bindings to mac keymap, bind them to goLineUp/Down on PC --- lib/codemirror.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/codemirror.js b/lib/codemirror.js index dbfe56a503..df514190d2 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -4864,7 +4864,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", @@ -4879,7 +4879,7 @@ "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. From 10d9bf1100c1636aa8d9eb381b86bef23bc3ca3d Mon Sep 17 00:00:00 2001 From: Norman Rzepka Date: Tue, 14 Oct 2014 13:24:42 +0200 Subject: [PATCH 1006/4131] continuelist: hitting enter twice cancels the list --- addon/edit/continuelist.js | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/addon/edit/continuelist.js b/addon/edit/continuelist.js index 8cee761aee..56f54c9227 100644 --- a/addon/edit/continuelist.js +++ b/addon/edit/continuelist.js @@ -12,6 +12,7 @@ "use strict"; var listRE = /^(\s*)([*+-]|(\d+)\.)(\s+)/, + emptyListRE = /^(\s*)([*+-]|(\d+)\.)(\s*)$/, unorderedBullets = "*+-"; CodeMirror.commands.newlineAndIndentContinueMarkdownList = function(cm) { @@ -25,12 +26,22 @@ 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] + : (parseInt(match[3], 10) + 1) + "."; + + replacements[i] = "\n" + indent + bullet + after; + } } cm.replaceSelections(replacements); From d913da999746ef1bd1510ed9f4e275d023c5a785 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 16 Oct 2014 09:54:20 +0200 Subject: [PATCH 1007/4131] [perl mode] Remove electric chars Issue #2870 --- mode/perl/perl.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mode/perl/perl.js b/mode/perl/perl.js index c12677d249..2a64c2ed41 100644 --- a/mode/perl/perl.js +++ b/mode/perl/perl.js @@ -789,7 +789,7 @@ CodeMirror.defineMode("perl",function(){ tail:null};}, token:function(stream,state){ return (state.tokenize||tokenPerl)(stream,state);}, - electricChars:"{}"};}); + };}); CodeMirror.registerHelper("wordChars", "perl", /[\w$]/); From 0462939fa2e8e2699aabcfbb9c86802cbdb6c828 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 16 Oct 2014 10:02:50 +0200 Subject: [PATCH 1008/4131] Fix superfluous comma --- mode/perl/perl.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mode/perl/perl.js b/mode/perl/perl.js index 2a64c2ed41..311574e74a 100644 --- a/mode/perl/perl.js +++ b/mode/perl/perl.js @@ -788,7 +788,7 @@ CodeMirror.defineMode("perl",function(){ style:null, tail:null};}, token:function(stream,state){ - return (state.tokenize||tokenPerl)(stream,state);}, + return (state.tokenize||tokenPerl)(stream,state);} };}); CodeMirror.registerHelper("wordChars", "perl", /[\w$]/); From c576c4cb4a9923b4acd172e7daa48fe67ef3c74f Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 16 Oct 2014 17:45:14 +0200 Subject: [PATCH 1009/4131] Don't use finally in the operation that initializes the editor Trying to call endOperation on a half-constructed editor will never end well, and the resulting errors will mask the actual error that happened. --- lib/codemirror.js | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/lib/codemirror.js b/lib/codemirror.js index df514190d2..7277b8bd0d 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -96,21 +96,20 @@ registerEventHandlers(this); ensureGlobalHandlers(); - var cm = this; - runInOp(this, function() { - cm.curOp.forceUpdate = true; - attachDoc(cm, doc); + startOperation(this); + this.curOp.forceUpdate = true; + attachDoc(this, doc); - if ((options.autofocus && !mobile) || activeElt() == display.input) - setTimeout(bind(onFocus, cm), 20); - else - onBlur(cm); + if ((options.autofocus && !mobile) || activeElt() == display.input) + setTimeout(bind(onFocus, this), 20); + else + onBlur(this); - for (var opt in optionHandlers) if (optionHandlers.hasOwnProperty(opt)) - optionHandlers[opt](cm, options[opt], Init); - maybeUpdateLineNumberWidth(cm); - for (var i = 0; i < initHooks.length; ++i) initHooks[i](cm); - }); + for (var opt in optionHandlers) if (optionHandlers.hasOwnProperty(opt)) + optionHandlers[opt](this, options[opt], Init); + maybeUpdateLineNumberWidth(this); + for (var i = 0; i < initHooks.length; ++i) initHooks[i](this); + endOperation(this); } // DISPLAY CONSTRUCTOR From 833ccba1d5d0b8d226ccc100b9b9eb6e854f3836 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 16 Oct 2014 17:51:41 +0200 Subject: [PATCH 1010/4131] Add simple mode addon --- addon/mode/simple.js | 200 +++++++++++++++++++++++++++++++++++++++++++ demo/simplemode.html | 172 +++++++++++++++++++++++++++++++++++++ doc/compress.html | 1 + doc/manual.html | 5 ++ 4 files changed, 378 insertions(+) create mode 100644 addon/mode/simple.js create mode 100644 demo/simplemode.html diff --git a/addon/mode/simple.js b/addon/mode/simple.js new file mode 100644 index 0000000000..7299eaeb34 --- /dev/null +++ b/addon/mode/simple.js @@ -0,0 +1,200 @@ +// 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); + 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) ensureState(states, data.next); + 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; + 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++) + state.pending.push({text: matches[j], token: rule.token[j - 1]}); + stream.backUp(matches[0].length - matches[1].length); + 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) { + if (rule.data.dedent && rule.data.dedentIfLineStart !== false) pos--; + if (rule.next) rules = states[rule.next]; + textAfter = textAfter.slice(m[0].length); + continue scan; + } + } + break; + } + return pos < 0 ? 0 : state.indent[pos]; + }; + } +}); diff --git a/demo/simplemode.html b/demo/simplemode.html new file mode 100644 index 0000000000..4b8de8cded --- /dev/null +++ b/demo/simplemode.html @@ -0,0 +1,172 @@ + + +CodeMirror: Simple Mode Demo + + + + + + + + + +

    + +
    +

    Simple Mode Demo

    + +

    The mode/simple +addon allows CodeMirror modes to be specified with a relatively simple +declarative format. This format is not as powerful as writing code +directly against the mode +interface, but is a lot easier to get started with, and +sufficiently expressive for many simple language modes.

    + +

    This interface is still in flux. It is unlikely to be scrapped or +overhauled completely, so do start writing code against it, but +details might change as it stabilizes, and you might have to tweak +your code when upgrading.

    + +

    Simple modes (loosely based on +the Common +JavaScript Syntax Highlighting Specification, which never took +off), are state machines, where each state has a number of rules that +match tokens. A rule describes a type of token that may occur in the +current state, and possibly a transition to another state caused by +that token.

    + +

    The CodeMirror.defineSimpleMode(name, states) method +takes a mode name and an object that describes the mode's states. The +editor below shows an example of such a mode (and is itself +highlighted by the mode shown in it).

    + +
    + +

    Each state is an array of rules. A rule may have the following properties:

    + +
    +
    regex
    +
    The regular expression that matches the token. May be a string + or a regex object. When a regex, the ignoreCase flag + will be taken into account when matching the token. This regex + should only capture groups when the token property is + an array.
    +
    token
    +
    An optional token style. Multiple styles can be specified by + separating them with dots or spaces. When the regex for + this rule captures groups, it must capture all of the + string (since JS provides no way to find out where a group matched), + and this property must hold an array of token styles that has one + style for each matched group.
    +
    next
    +
    When a next property is present, the mode will + transfer to another state when the token is encountered.
    +
    mode
    +
    Can be used to embed another mode inside a mode. When present, + must hold an object with a spec property that describes + the embedded mode, and an optional end end property + that specifies the regexp that will end the extent of the mode. When + a persistent property is set (and true), the nested + mode's state will be preserved between occurrences of the mode.
    +
    indent
    +
    When true, this token changes the indentation to be one unit + more than the current line's indentation.
    +
    dedent
    +
    When true, this token will pop one scope off the indentation + stack.
    +
    dedentIfLineStart
    +
    If a token has its dedent property set, it will, by + default, cause lines where it appears at the start to be dedented. + Set this property to false to prevent that behavior.
    +
    + +

    The meta property of the states object is special, and +will not be interpreted as a state. Instead, properties set on it will +be set on the mode, which is useful for properties +like lineComment, +which sets the comment style for a mode. The simple mode addon also +recognizes a few such properties:

    + +
    +
    dontIndentStates
    +
    An array of states in which the mode's auto-indentation should + not take effect. Usually used for multi-line comment and string + states.
    +
    + + + + + +
    diff --git a/doc/compress.html b/doc/compress.html index 19639903a3..940465259d 100644 --- a/doc/compress.html +++ b/doc/compress.html @@ -219,6 +219,7 @@

    Script compression helper

    + diff --git a/doc/manual.html b/doc/manual.html index fccf7d6416..f89cc4b3fd 100644 --- a/doc/manual.html +++ b/doc/manual.html @@ -2715,6 +2715,11 @@

    Writing CodeMirror Modes

    advances it past a token, and returns a style for that token. More advanced modes can also handle indentation for the language.

    +

    This section describes the low-level mode interface. Many modes + are written directly against this, since it offers a lot of + control, but for a quick mode definition, you might want to use + the simple mode addon.

    +

    The mode script should call CodeMirror.defineMode to register itself with CodeMirror. This function takes two From eee65eef5a258fef405d6880566213f5acf9924c Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 16 Oct 2014 17:53:19 +0200 Subject: [PATCH 1011/4131] [simple mode demo] Slight rewording --- demo/simplemode.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/demo/simplemode.html b/demo/simplemode.html index 4b8de8cded..9218b04247 100644 --- a/demo/simplemode.html +++ b/demo/simplemode.html @@ -32,7 +32,7 @@

    Simple Mode Demo

    The mode/simple -addon allows CodeMirror modes to be specified with a relatively simple +addon allows CodeMirror modes to be specified using a relatively simple declarative format. This format is not as powerful as writing code directly against the mode interface, but is a lot easier to get started with, and From a9acabd88b1930b2e5d4470cb3a6ce2a20ffa5db Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Fri, 17 Oct 2014 00:27:53 +0200 Subject: [PATCH 1012/4131] Switch to new logo --- demo/activeline.html | 2 +- demo/anywordhint.html | 2 +- demo/bidi.html | 2 +- demo/btree.html | 2 +- demo/buffers.html | 2 +- demo/changemode.html | 2 +- demo/closebrackets.html | 2 +- demo/closetag.html | 2 +- demo/complete.html | 2 +- demo/emacs.html | 2 +- demo/folding.html | 2 +- demo/fullscreen.html | 2 +- demo/hardwrap.html | 2 +- demo/html5complete.html | 2 +- demo/indentwrap.html | 2 +- demo/lint.html | 2 +- demo/loadmode.html | 2 +- demo/marker.html | 2 +- demo/markselection.html | 2 +- demo/matchhighlighter.html | 2 +- demo/matchtags.html | 2 +- demo/merge.html | 2 +- demo/multiplex.html | 2 +- demo/mustache.html | 2 +- demo/placeholder.html | 2 +- demo/preview.html | 2 +- demo/requirejs.html | 2 +- demo/resize.html | 2 +- demo/rulers.html | 2 +- demo/runmode.html | 2 +- demo/search.html | 2 +- demo/simplemode.html | 2 +- demo/spanaffectswrapping_shim.html | 2 +- demo/sublime.html | 2 +- demo/tern.html | 2 +- demo/theme.html | 2 +- demo/trailingspace.html | 2 +- demo/variableheight.html | 2 +- demo/vim.html | 2 +- demo/visibletabs.html | 2 +- demo/widget.html | 2 +- demo/xmlcomplete.html | 2 +- doc/compress.html | 2 +- doc/docs.css | 13 +- doc/internals.html | 2 +- doc/logo.png | Bin 12003 -> 9730 bytes doc/logo.svg | 279 ++++++++++++++++------------- doc/manual.html | 2 +- doc/realworld.html | 2 +- doc/releases.html | 2 +- doc/reporting.html | 2 +- doc/upgrade_v2.2.html | 2 +- doc/upgrade_v3.html | 2 +- doc/upgrade_v4.html | 2 +- index.html | 2 +- mode/apl/index.html | 2 +- mode/asterisk/index.html | 2 +- mode/clike/index.html | 2 +- mode/clike/scala.html | 2 +- mode/clojure/index.html | 2 +- mode/cobol/index.html | 2 +- mode/coffeescript/index.html | 2 +- mode/commonlisp/index.html | 2 +- mode/css/index.html | 2 +- mode/css/less.html | 2 +- mode/css/scss.html | 2 +- mode/cypher/index.html | 2 +- mode/d/index.html | 2 +- mode/diff/index.html | 2 +- mode/django/index.html | 2 +- mode/dtd/index.html | 2 +- mode/dylan/index.html | 2 +- mode/ecl/index.html | 2 +- mode/eiffel/index.html | 2 +- mode/erlang/index.html | 2 +- mode/fortran/index.html | 2 +- mode/gas/index.html | 2 +- mode/gfm/index.html | 2 +- mode/gherkin/index.html | 2 +- mode/go/index.html | 2 +- mode/groovy/index.html | 2 +- mode/haml/index.html | 2 +- mode/haskell/index.html | 2 +- mode/haxe/index.html | 2 +- mode/htmlembedded/index.html | 2 +- mode/htmlmixed/index.html | 2 +- mode/http/index.html | 2 +- mode/index.html | 2 +- mode/jade/index.html | 2 +- mode/javascript/index.html | 2 +- mode/javascript/json-ld.html | 2 +- mode/javascript/typescript.html | 2 +- mode/jinja2/index.html | 2 +- mode/julia/index.html | 2 +- mode/kotlin/index.html | 2 +- mode/livescript/index.html | 2 +- mode/lua/index.html | 2 +- mode/markdown/index.html | 2 +- mode/mirc/index.html | 2 +- mode/mllike/index.html | 2 +- mode/modelica/index.html | 2 +- mode/nginx/index.html | 2 +- mode/ntriples/index.html | 2 +- mode/octave/index.html | 2 +- mode/pascal/index.html | 2 +- mode/pegjs/index.html | 2 +- mode/perl/index.html | 2 +- mode/php/index.html | 2 +- mode/pig/index.html | 2 +- mode/properties/index.html | 2 +- mode/puppet/index.html | 2 +- mode/python/index.html | 2 +- mode/q/index.html | 2 +- mode/r/index.html | 2 +- mode/rpm/changes/index.html | 2 +- mode/rpm/index.html | 2 +- mode/rst/index.html | 2 +- mode/ruby/index.html | 2 +- mode/rust/index.html | 2 +- mode/sass/index.html | 2 +- mode/scheme/index.html | 2 +- mode/shell/index.html | 2 +- mode/sieve/index.html | 2 +- mode/slim/index.html | 2 +- mode/smalltalk/index.html | 2 +- mode/smarty/index.html | 2 +- mode/smartymixed/index.html | 2 +- mode/solr/index.html | 2 +- mode/sparql/index.html | 2 +- mode/sql/index.html | 2 +- mode/stex/index.html | 2 +- mode/tcl/index.html | 2 +- mode/textile/index.html | 2 +- mode/tiddlywiki/index.html | 2 +- mode/tiki/index.html | 2 +- mode/toml/index.html | 2 +- mode/tornado/index.html | 2 +- mode/turtle/index.html | 2 +- mode/vb/index.html | 2 +- mode/vbscript/index.html | 2 +- mode/velocity/index.html | 2 +- mode/verilog/index.html | 2 +- mode/xml/index.html | 2 +- mode/xquery/index.html | 2 +- mode/yaml/index.html | 2 +- mode/z80/index.html | 2 +- test/index.html | 2 +- 147 files changed, 311 insertions(+), 269 deletions(-) diff --git a/demo/activeline.html b/demo/activeline.html index c1391ef27e..741f6c45a4 100644 --- a/demo/activeline.html +++ b/demo/activeline.html @@ -12,7 +12,7 @@ .CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}