diff --git a/AUTHORS b/AUTHORS index 9d62d48e63..a4f2b94b79 100644 --- a/AUTHORS +++ b/AUTHORS @@ -87,6 +87,7 @@ Christian Petrov Christopher Brown ciaranj CodeAnimal +coderaiser ComFreek Curtis Gagliardi dagsta @@ -230,6 +231,7 @@ jwallers@gmail.com kaniga Ken Newman Ken Rockot +Kevin Earls Kevin Sawicki Kevin Ushey Klaus Silveira @@ -351,6 +353,7 @@ Randall Mason Randy Burden Randy Edmunds Rasmus Erik Voel Jensen +ray ratchup Ray Ratchup Richard van der Meer Richard Z.H. Wang diff --git a/README.md b/README.md index bc6e7f5c71..38156a7427 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # CodeMirror [![Build Status](https://travis-ci.org/codemirror/CodeMirror.svg)](https://travis-ci.org/codemirror/CodeMirror) [![NPM version](https://img.shields.io/npm/v/codemirror.svg)](https://www.npmjs.org/package/codemirror) -[Funding status: ![maintainer happiness](https://marijnhaverbeke.nl/fund/status_s.png)](https://marijnhaverbeke.nl/fund/) +[Funding status: ![maintainer happiness](https://marijnhaverbeke.nl/fund/status_s.png?again)](https://marijnhaverbeke.nl/fund/) CodeMirror is a JavaScript component that provides a code editor in the browser. When a mode is available for the language you are coding diff --git a/addon/dialog/dialog.js b/addon/dialog/dialog.js index e0e8ad4eb7..323b20078e 100644 --- a/addon/dialog/dialog.js +++ b/addon/dialog/dialog.js @@ -58,7 +58,9 @@ if (inp) { if (options.value) { inp.value = options.value; - inp.select(); + if (options.selectValueOnOpen !== false) { + inp.select(); + } } if (options.onInput) diff --git a/addon/edit/closebrackets.js b/addon/edit/closebrackets.js index ff4bb3f733..2bbc6f2a38 100644 --- a/addon/edit/closebrackets.js +++ b/addon/edit/closebrackets.js @@ -9,29 +9,157 @@ else // Plain browser env mod(CodeMirror); })(function(CodeMirror) { - var DEFAULT_BRACKETS = "()[]{}''\"\""; - var DEFAULT_TRIPLES = "'\""; - var DEFAULT_EXPLODE_ON_ENTER = "[]{}"; - var SPACE_CHAR_REGEX = /\s/; + var defaults = { + pairs: "()[]{}''\"\"", + triples: "", + explode: "[]{}" + }; var Pos = CodeMirror.Pos; CodeMirror.defineOption("autoCloseBrackets", false, function(cm, val, old) { - if (old != CodeMirror.Init && old) - cm.removeKeyMap("autoCloseBrackets"); - if (!val) return; - var pairs = DEFAULT_BRACKETS, triples = DEFAULT_TRIPLES, explode = DEFAULT_EXPLODE_ON_ENTER; - if (typeof val == "string") pairs = val; - else if (typeof val == "object") { - if (val.pairs != null) pairs = val.pairs; - if (val.triples != null) triples = val.triples; - if (val.explode != null) explode = val.explode; + if (old && old != CodeMirror.Init) { + cm.removeKeyMap(keyMap); + cm.state.closeBrackets = null; + } + if (val) { + cm.state.closeBrackets = val; + cm.addKeyMap(keyMap); } - var map = buildKeymap(pairs, triples); - if (explode) map.Enter = buildExplodeHandler(explode); - cm.addKeyMap(map); }); + function getOption(conf, name) { + if (name == "pairs" && typeof conf == "string") return conf; + if (typeof conf == "object" && conf[name] != null) return conf[name]; + return defaults[name]; + } + + var bind = defaults.pairs + "`"; + var keyMap = {Backspace: handleBackspace, Enter: handleEnter}; + for (var i = 0; i < bind.length; i++) + keyMap["'" + bind.charAt(i) + "'"] = handler(bind.charAt(i)); + + function handler(ch) { + return function(cm) { return handleChar(cm, ch); }; + } + + function getConfig(cm) { + var deflt = cm.state.closeBrackets; + if (!deflt) return null; + var mode = cm.getModeAt(cm.getCursor()); + return mode.closeBrackets || deflt; + } + + function handleBackspace(cm) { + var conf = getConfig(cm); + if (!conf || cm.getOption("disableInput")) return CodeMirror.Pass; + + var pairs = getOption(conf, "pairs"); + var ranges = cm.listSelections(); + for (var i = 0; i < ranges.length; i++) { + if (!ranges[i].empty()) return CodeMirror.Pass; + var around = charsAround(cm, ranges[i].head); + if (!around || pairs.indexOf(around) % 2 != 0) return CodeMirror.Pass; + } + for (var i = ranges.length - 1; i >= 0; i--) { + var cur = ranges[i].head; + cm.replaceRange("", Pos(cur.line, cur.ch - 1), Pos(cur.line, cur.ch + 1)); + } + } + + function handleEnter(cm) { + var conf = getConfig(cm); + var explode = conf && getOption(conf, "explode"); + if (!explode || cm.getOption("disableInput")) return CodeMirror.Pass; + + var ranges = cm.listSelections(); + for (var i = 0; i < ranges.length; i++) { + if (!ranges[i].empty()) return CodeMirror.Pass; + var around = charsAround(cm, ranges[i].head); + if (!around || explode.indexOf(around) % 2 != 0) return CodeMirror.Pass; + } + cm.operation(function() { + cm.replaceSelection("\n\n", null); + cm.execCommand("goCharLeft"); + ranges = cm.listSelections(); + for (var i = 0; i < ranges.length; i++) { + var line = ranges[i].head.line; + cm.indentLine(line, null, true); + cm.indentLine(line + 1, null, true); + } + }); + } + + function handleChar(cm, ch) { + var conf = getConfig(cm); + if (!conf || cm.getOption("disableInput")) return CodeMirror.Pass; + + var pairs = getOption(conf, "pairs"); + var pos = pairs.indexOf(ch); + if (pos == -1) return CodeMirror.Pass; + var triples = getOption(conf, "triples"); + + var identical = pairs.charAt(pos + 1) == ch; + var ranges = cm.listSelections(); + var opening = pos % 2 == 0; + + var type, next; + for (var i = 0; i < ranges.length; i++) { + var range = ranges[i], cur = range.head, curType; + var next = cm.getRange(cur, Pos(cur.line, cur.ch + 1)); + if (opening && !range.empty()) { + curType = "surround"; + } else if ((identical || !opening) && next == ch) { + if (triples.indexOf(ch) >= 0 && cm.getRange(cur, Pos(cur.line, cur.ch + 3)) == ch + ch + ch) + curType = "skipThree"; + else + curType = "skip"; + } else if (identical && cur.ch > 1 && triples.indexOf(ch) >= 0 && + cm.getRange(Pos(cur.line, cur.ch - 2), cur) == ch + ch && + (cur.ch <= 2 || cm.getRange(Pos(cur.line, cur.ch - 3), Pos(cur.line, cur.ch - 2)) != ch)) { + curType = "addFour"; + } else if (identical) { + if (!CodeMirror.isWordChar(next) && enteringString(cm, cur, ch)) curType = "both"; + else return CodeMirror.Pass; + } else if (opening && (cm.getLine(cur.line).length == cur.ch || + isClosingBracket(next, pairs) || + /\s/.test(next))) { + curType = "both"; + } else { + return CodeMirror.Pass; + } + if (!type) type = curType; + else if (type != curType) return CodeMirror.Pass; + } + + var left = pos % 2 ? pairs.charAt(pos - 1) : ch; + var right = pos % 2 ? ch : pairs.charAt(pos + 1); + cm.operation(function() { + if (type == "skip") { + cm.execCommand("goCharRight"); + } else if (type == "skipThree") { + for (var i = 0; i < 3; i++) + cm.execCommand("goCharRight"); + } else if (type == "surround") { + var sels = cm.getSelections(); + for (var i = 0; i < sels.length; i++) + sels[i] = left + sels[i] + right; + cm.replaceSelections(sels, "around"); + } else if (type == "both") { + cm.replaceSelection(left + right, null); + cm.execCommand("goCharLeft"); + } else if (type == "addFour") { + cm.replaceSelection(left + left + left + left, "before"); + cm.execCommand("goCharRight"); + } + }); + } + + function isClosingBracket(ch, pairs) { + var pos = pairs.lastIndexOf(ch); + return pos > -1 && pos % 2 == 1; + } + function charsAround(cm, pos) { var str = cm.getRange(Pos(pos.line, pos.ch - 1), Pos(pos.line, pos.ch + 1)); @@ -53,109 +181,4 @@ stream.start = stream.pos; } } - - function buildKeymap(pairs, triples) { - var map = { - name : "autoCloseBrackets", - Backspace: function(cm) { - if (cm.getOption("disableInput")) return CodeMirror.Pass; - var ranges = cm.listSelections(); - for (var i = 0; i < ranges.length; i++) { - if (!ranges[i].empty()) return CodeMirror.Pass; - var around = charsAround(cm, ranges[i].head); - if (!around || pairs.indexOf(around) % 2 != 0) return CodeMirror.Pass; - } - for (var i = ranges.length - 1; i >= 0; i--) { - var cur = ranges[i].head; - cm.replaceRange("", Pos(cur.line, cur.ch - 1), Pos(cur.line, cur.ch + 1)); - } - } - }; - var closingBrackets = ""; - for (var i = 0; i < pairs.length; i += 2) (function(left, right) { - closingBrackets += right; - map["'" + left + "'"] = function(cm) { - if (cm.getOption("disableInput")) return CodeMirror.Pass; - var ranges = cm.listSelections(), type, next; - for (var i = 0; i < ranges.length; i++) { - var range = ranges[i], cur = range.head, curType; - var next = cm.getRange(cur, Pos(cur.line, cur.ch + 1)); - if (!range.empty()) { - curType = "surround"; - } else if (left == right && next == right) { - if (cm.getRange(cur, Pos(cur.line, cur.ch + 3)) == left + left + left) - curType = "skipThree"; - else - curType = "skip"; - } else if (left == right && cur.ch > 1 && triples.indexOf(left) >= 0 && - cm.getRange(Pos(cur.line, cur.ch - 2), cur) == left + left && - (cur.ch <= 2 || cm.getRange(Pos(cur.line, cur.ch - 3), Pos(cur.line, cur.ch - 2)) != left)) { - curType = "addFour"; - } else if (left == '"' || left == "'") { - if (!CodeMirror.isWordChar(next) && enteringString(cm, cur, left)) curType = "both"; - else return CodeMirror.Pass; - } else if (cm.getLine(cur.line).length == cur.ch || closingBrackets.indexOf(next) >= 0 || SPACE_CHAR_REGEX.test(next)) { - curType = "both"; - } else { - return CodeMirror.Pass; - } - if (!type) type = curType; - else if (type != curType) return CodeMirror.Pass; - } - - cm.operation(function() { - if (type == "skip") { - cm.execCommand("goCharRight"); - } else if (type == "skipThree") { - for (var i = 0; i < 3; i++) - cm.execCommand("goCharRight"); - } else if (type == "surround") { - var sels = cm.getSelections(); - for (var i = 0; i < sels.length; i++) - sels[i] = left + sels[i] + right; - cm.replaceSelections(sels, "around"); - } else if (type == "both") { - cm.replaceSelection(left + right, null); - cm.execCommand("goCharLeft"); - } else if (type == "addFour") { - cm.replaceSelection(left + left + left + left, "before"); - cm.execCommand("goCharRight"); - } - }); - }; - if (left != right) map["'" + right + "'"] = function(cm) { - var ranges = cm.listSelections(); - for (var i = 0; i < ranges.length; i++) { - var range = ranges[i]; - if (!range.empty() || - cm.getRange(range.head, Pos(range.head.line, range.head.ch + 1)) != right) - return CodeMirror.Pass; - } - cm.execCommand("goCharRight"); - }; - })(pairs.charAt(i), pairs.charAt(i + 1)); - return map; - } - - function buildExplodeHandler(pairs) { - return function(cm) { - if (cm.getOption("disableInput")) return CodeMirror.Pass; - var ranges = cm.listSelections(); - for (var i = 0; i < ranges.length; i++) { - if (!ranges[i].empty()) return CodeMirror.Pass; - var around = charsAround(cm, ranges[i].head); - if (!around || pairs.indexOf(around) % 2 != 0) return CodeMirror.Pass; - } - cm.operation(function() { - cm.replaceSelection("\n\n", null); - cm.execCommand("goCharLeft"); - ranges = cm.listSelections(); - for (var i = 0; i < ranges.length; i++) { - var line = ranges[i].head.line; - cm.indentLine(line, null, true); - cm.indentLine(line + 1, null, true); - } - }); - }; - } }); diff --git a/addon/fold/foldgutter.js b/addon/fold/foldgutter.js index 199120c726..ed7bd87d34 100644 --- a/addon/fold/foldgutter.js +++ b/addon/fold/foldgutter.js @@ -52,7 +52,7 @@ function isFolded(cm, line) { var marks = cm.findMarksAt(Pos(line)); for (var i = 0; i < marks.length; ++i) - if (marks[i].__isFold && marks[i].find().from.line == line) return true; + if (marks[i].__isFold && marks[i].find().from.line == line) return marks[i]; } function marker(spec) { @@ -98,7 +98,9 @@ if (!state) return; var opts = state.options; if (gutter != opts.gutter) return; - cm.foldCode(Pos(line, 0), opts.rangeFinder); + var folded = isFolded(cm, line); + if (folded) folded.clear(); + else cm.foldCode(Pos(line, 0), opts.rangeFinder); } function onChange(cm) { diff --git a/addon/hint/css-hint.js b/addon/hint/css-hint.js index 488da3449e..22642727cf 100644 --- a/addon/hint/css-hint.js +++ b/addon/hint/css-hint.js @@ -20,6 +20,10 @@ var inner = CodeMirror.innerMode(cm.getMode(), token.state); if (inner.mode.name != "css") return; + if (token.type == "keyword" && "!important".indexOf(token.string) == 0) + return {list: ["!important"], from: CodeMirror.Pos(cur.line, token.start), + to: CodeMirror.Pos(cur.line, token.end)}; + var start = token.start, end = cur.ch, word = token.string.slice(0, end - start); if (/[^\w$_-]/.test(word)) { word = ""; start = end = cur.ch; diff --git a/addon/hint/sql-hint.js b/addon/hint/sql-hint.js index 5b0cc7696f..cba27a0b2c 100644 --- a/addon/hint/sql-hint.js +++ b/addon/hint/sql-hint.js @@ -52,12 +52,9 @@ function addMatches(result, search, wordlist, formatter) { for (var word in wordlist) { if (!wordlist.hasOwnProperty(word)) continue; - if (Array.isArray(wordlist)) { - word = wordlist[word]; - } - if (match(search, word)) { - result.push(formatter(word)); - } + if (wordlist.slice) word = wordlist[word]; + + if (match(search, word)) result.push(formatter(word)); } } @@ -120,7 +117,7 @@ table = findTableByAlias(table, editor); var columns = getItem(tables, table); - if (columns && Array.isArray(tables) && columns.columns) + if (columns && columns.columns) columns = columns.columns; if (columns) { @@ -208,9 +205,17 @@ CodeMirror.registerHelper("hint", "sql", function(editor, options) { tables = (options && options.tables) || {}; var defaultTableName = options && options.defaultTable; - defaultTable = (defaultTableName && getItem(tables, defaultTableName)) || []; + defaultTable = defaultTableName && getItem(tables, defaultTableName); keywords = keywords || getKeywords(editor); + if (defaultTableName && !defaultTable) + defaultTable = findTableByAlias(defaultTableName, editor); + + defaultTable = defaultTable || []; + + if (defaultTable.columns) + defaultTable = defaultTable.columns; + var cur = editor.getCursor(); var result = []; var token = editor.getTokenAt(cur), start, end, search; diff --git a/addon/lint/lint.js b/addon/lint/lint.js index 18eb709016..c7e093960e 100644 --- a/addon/lint/lint.js +++ b/addon/lint/lint.js @@ -163,6 +163,7 @@ function onChange(cm) { var state = cm.state.lint; + if (!state) return; clearTimeout(state.timeout); state.timeout = setTimeout(function(){startLinting(cm);}, state.options.delay || 500); } @@ -188,6 +189,7 @@ clearMarks(cm); cm.off("change", onChange); CodeMirror.off(cm.getWrapperElement(), "mouseover", cm.state.lint.onMouseOver); + clearTimeout(cm.state.lint.timeout); delete cm.state.lint; } diff --git a/addon/merge/merge.js b/addon/merge/merge.js index f1f3aafc49..5b04b03292 100644 --- a/addon/merge/merge.js +++ b/addon/merge/merge.js @@ -37,7 +37,9 @@ constructor: DiffView, init: function(pane, orig, options) { this.edit = this.mv.edit; + (this.edit.state.diffViews || (this.edit.state.diffViews = [])).push(this); this.orig = CodeMirror(pane, copyObj({value: orig, readOnly: !this.mv.options.allowEditingOriginals}, copyObj(options))); + this.orig.state.diffViews = [this]; this.diff = getDiff(asString(orig), asString(options.value)); this.chunks = getChunks(this.diff); @@ -732,4 +734,42 @@ 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; } + + function findPrevDiff(chunks, start, isOrig) { + for (var i = chunks.length - 1; i >= 0; i--) { + var chunk = chunks[i]; + var to = (isOrig ? chunk.origTo : chunk.editTo) - 1; + if (to < start) return to; + } + } + + function findNextDiff(chunks, start, isOrig) { + for (var i = 0; i < chunks.length; i++) { + var chunk = chunks[i]; + var from = (isOrig ? chunk.origFrom : chunk.editFrom); + if (from > start) return from; + } + } + + function goNearbyDiff(cm, dir) { + var found = null, views = cm.state.diffViews, line = cm.getCursor().line; + if (views) for (var i = 0; i < views.length; i++) { + var dv = views[i], isOrig = cm == dv.orig; + ensureDiff(dv); + var pos = dir < 0 ? findPrevDiff(dv.chunks, line, isOrig) : findNextDiff(dv.chunks, line, isOrig); + if (pos != null && (found == null || (dir < 0 ? pos > found : pos < found))) + found = pos; + } + if (found != null) + cm.setCursor(found, 0); + else + return CodeMirror.Pass; + } + + CodeMirror.commands.goNextDiff = function(cm) { + return goNearbyDiff(cm, 1); + }; + CodeMirror.commands.goPrevDiff = function(cm) { + return goNearbyDiff(cm, -1); + }; }); diff --git a/addon/scroll/simplescrollbars.js b/addon/scroll/simplescrollbars.js index bb06adb86a..f78353a130 100644 --- a/addon/scroll/simplescrollbars.js +++ b/addon/scroll/simplescrollbars.js @@ -69,14 +69,20 @@ if (update !== false) this.scroll(pos, this.orientation); }; + var minButtonSize = 10; + Bar.prototype.update = function(scrollSize, clientSize, barSize) { this.screen = clientSize; this.total = scrollSize; this.size = barSize; - // FIXME clip to min size? + var buttonSize = this.screen * (this.size / this.total); + if (buttonSize < minButtonSize) { + this.size -= minButtonSize - buttonSize; + buttonSize = minButtonSize; + } this.inner.style[this.orientation == "horizontal" ? "width" : "height"] = - this.screen * (this.size / this.total) + "px"; + buttonSize + "px"; this.inner.style[this.orientation == "horizontal" ? "left" : "top"] = this.pos * (this.size / this.total) + "px"; }; diff --git a/addon/tern/tern.js b/addon/tern/tern.js index b049549d35..99b8a64682 100644 --- a/addon/tern/tern.js +++ b/addon/tern/tern.js @@ -443,7 +443,7 @@ function atInterestingExpression(cm) { var pos = cm.getCursor("end"), tok = cm.getTokenAt(pos); if (tok.start < pos.ch && (tok.type == "comment" || tok.type == "string")) return false; - return /\w/.test(cm.getLine(pos.line).slice(Math.max(pos.ch - 1, 0), pos.ch + 1)); + return /[\w)\]]/.test(cm.getLine(pos.line).slice(Math.max(pos.ch - 1, 0), pos.ch + 1)); } // Variable renaming diff --git a/bower.json b/bower.json index c59f2d9d27..334447e56d 100644 --- a/bower.json +++ b/bower.json @@ -1,6 +1,6 @@ { "name": "codemirror", - "version":"5.0.0", + "version":"5.1.0", "main": ["lib/codemirror.js", "lib/codemirror.css"], "ignore": [ "**/.*", diff --git a/doc/compress.html b/doc/compress.html index a376c86d2d..65df6483f5 100644 --- a/doc/compress.html +++ b/doc/compress.html @@ -36,6 +36,7 @@

Version: + + + +

MIME types +defined: application/pgp, application/pgp-keys, application/pgp-signature

+ + diff --git a/mode/clike/clike.js b/mode/clike/clike.js index e2223ccd15..f996f019dc 100644 --- a/mode/clike/clike.js +++ b/mode/clike/clike.js @@ -403,7 +403,8 @@ CodeMirror.defineMode("clike", function(config, parserConfig) { stream.eatWhile(/[\w\$_\xa1-\uffff]/); return "atom"; } - } + }, + modeProps: {closeBrackets: {triples: '"'}} }); def(["x-shader/x-vertex", "x-shader/x-fragment"], { diff --git a/mode/clojure/clojure.js b/mode/clojure/clojure.js index c334de7300..d531022a2e 100644 --- a/mode/clojure/clojure.js +++ b/mode/clojure/clojure.js @@ -234,6 +234,7 @@ CodeMirror.defineMode("clojure", function (options) { return state.indentStack.indent; }, + closeBrackets: {pairs: "()[]{}\"\""}, lineComment: ";;" }; }); diff --git a/mode/cmake/cmake.js b/mode/cmake/cmake.js new file mode 100644 index 0000000000..9f9eda5417 --- /dev/null +++ b/mode/cmake/cmake.js @@ -0,0 +1,97 @@ +// 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") + mod(require("../../lib/codemirror")); + else if (typeof define == "function" && define.amd) + define(["../../lib/codemirror"], mod); + else + mod(CodeMirror); +})(function(CodeMirror) { +"use strict"; + +CodeMirror.defineMode("cmake", function () { + var variable_regex = /({)?[a-zA-Z0-9_]+(})?/; + + function tokenString(stream, state) { + var current, prev, found_var = false; + while (!stream.eol() && (current = stream.next()) != state.pending) { + if (current === '$' && prev != '\\' && state.pending == '"') { + found_var = true; + break; + } + prev = current; + } + if (found_var) { + stream.backUp(1); + } + if (current == state.pending) { + state.continueString = false; + } else { + state.continueString = true; + } + return "string"; + } + + function tokenize(stream, state) { + var ch = stream.next(); + + // Have we found a variable? + if (ch === '$') { + if (stream.match(variable_regex)) { + return 'variable-2'; + } + return 'variable'; + } + // Should we still be looking for the end of a string? + if (state.continueString) { + // If so, go through the loop again + stream.backUp(1); + return tokenString(stream, state); + } + // Do we just have a function on our hands? + // In 'cmake_minimum_required (VERSION 2.8.8)', 'cmake_minimum_required' is matched + if (stream.match(/(\s+)?\w+\(/) || stream.match(/(\s+)?\w+\ \(/)) { + stream.backUp(1); + return 'def'; + } + if (ch == "#") { + stream.skipToEnd(); + return "comment"; + } + // Have we found a string? + if (ch == "'" || ch == '"') { + // Store the type (single or double) + state.pending = ch; + // Perform the looping function to find the end + return tokenString(stream, state); + } + if (ch == '(' || ch == ')') { + return 'bracket'; + } + if (ch.match(/[0-9]/)) { + return 'number'; + } + stream.eatWhile(/[\w-]/); + return null; + } + return { + startState: function () { + var state = {}; + state.inDefinition = false; + state.inInclude = false; + state.continueString = false; + state.pending = false; + return state; + }, + token: function (stream, state) { + if (stream.eatSpace()) return null; + return tokenize(stream, state); + } + }; +}); + +CodeMirror.defineMIME("text/x-cmake", "cmake"); + +}); diff --git a/mode/cmake/index.html b/mode/cmake/index.html new file mode 100644 index 0000000000..ed114fece5 --- /dev/null +++ b/mode/cmake/index.html @@ -0,0 +1,129 @@ + + +CodeMirror: CMake mode + + + + + + + + + + +
+

CMake mode

+
+ + +

MIME types defined: text/x-cmake.

+ +
diff --git a/mode/commonlisp/commonlisp.js b/mode/commonlisp/commonlisp.js index 5f50b352de..fb1f99c631 100644 --- a/mode/commonlisp/commonlisp.js +++ b/mode/commonlisp/commonlisp.js @@ -111,6 +111,7 @@ CodeMirror.defineMode("commonlisp", function (config) { return typeof i == "number" ? i : state.ctx.start + 1; }, + closeBrackets: {pairs: "()[]{}\"\""}, lineComment: ";;", blockCommentStart: "#|", blockCommentEnd: "|#" diff --git a/mode/css/css.js b/mode/css/css.js index 34355aaa99..bed1517e8c 100644 --- a/mode/css/css.js +++ b/mode/css/css.js @@ -239,6 +239,7 @@ CodeMirror.defineMode("css", function(config, parserConfig) { if (type == "{" || type == "}") return popAndPass(type, stream, state); if (type == ")") return popContext(state); if (type == "(") return pushContext(state, stream, "parens"); + if (type == "interpolation") return pushContext(state, stream, "interpolation"); if (type == "word") wordAsValue(stream); return "parens"; }; diff --git a/mode/css/less.html b/mode/css/less.html index 6ccb721e63..adf7427d30 100644 --- a/mode/css/less.html +++ b/mode/css/less.html @@ -146,7 +146,7 @@ }); -

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

+

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/scss.html b/mode/css/scss.html index 21f20e0d16..f8e4d37368 100644 --- a/mode/css/scss.html +++ b/mode/css/scss.html @@ -150,7 +150,7 @@ }); -

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

+

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

Parsing/Highlighting Tests: normal, verbose.

diff --git a/mode/groovy/groovy.js b/mode/groovy/groovy.js index 89b8224cf5..e3a1db869b 100644 --- a/mode/groovy/groovy.js +++ b/mode/groovy/groovy.js @@ -217,6 +217,7 @@ CodeMirror.defineMode("groovy", function(config) { }, electricChars: "{}", + closeBrackets: {triples: "'\""}, fold: "brace" }; }); diff --git a/mode/htmlembedded/htmlembedded.js b/mode/htmlembedded/htmlembedded.js index e8f7ba803f..464dc57f83 100644 --- a/mode/htmlembedded/htmlembedded.js +++ b/mode/htmlembedded/htmlembedded.js @@ -3,84 +3,26 @@ (function(mod) { if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror"), require("../htmlmixed/htmlmixed")); + mod(require("../../lib/codemirror"), require("../htmlmixed/htmlmixed"), + require("../../addon/mode/multiplex")); else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror", "../htmlmixed/htmlmixed"], mod); + define(["../../lib/codemirror", "../htmlmixed/htmlmixed", + "../../addon/mode/multiplex"], mod); else // Plain browser env mod(CodeMirror); })(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("htmlembedded", function(config, parserConfig) { - - //config settings - var scriptStartRegex = parserConfig.scriptStartRegex || /^<%/i, - scriptEndRegex = parserConfig.scriptEndRegex || /^%>/i; - - //inner modes - var scriptingMode, htmlMixedMode; - - //tokenizer when in html mode - function htmlDispatch(stream, state) { - if (stream.match(scriptStartRegex, false)) { - state.token=scriptingDispatch; - return scriptingMode.token(stream, state.scriptState); - } - else - return htmlMixedMode.token(stream, state.htmlState); - } - - //tokenizer when in scripting mode - function scriptingDispatch(stream, state) { - if (stream.match(scriptEndRegex, false)) { - state.token=htmlDispatch; - return htmlMixedMode.token(stream, state.htmlState); - } - else - return scriptingMode.token(stream, state.scriptState); - } - - - return { - startState: function() { - scriptingMode = scriptingMode || CodeMirror.getMode(config, parserConfig.scriptingModeSpec); - htmlMixedMode = htmlMixedMode || CodeMirror.getMode(config, "htmlmixed"); - return { - token : parserConfig.startOpen ? scriptingDispatch : htmlDispatch, - htmlState : CodeMirror.startState(htmlMixedMode), - scriptState : CodeMirror.startState(scriptingMode) - }; - }, - - token: function(stream, state) { - return state.token(stream, state); - }, - - indent: function(state, textAfter) { - if (state.token == htmlDispatch) - return htmlMixedMode.indent(state.htmlState, textAfter); - else if (scriptingMode.indent) - return scriptingMode.indent(state.scriptState, textAfter); - }, - - copyState: function(state) { - return { - token : state.token, - htmlState : CodeMirror.copyState(htmlMixedMode, state.htmlState), - scriptState : CodeMirror.copyState(scriptingMode, state.scriptState) - }; - }, - - innerMode: function(state) { - if (state.token == scriptingDispatch) return {state: state.scriptState, mode: scriptingMode}; - else return {state: state.htmlState, mode: htmlMixedMode}; - } - }; -}, "htmlmixed"); - -CodeMirror.defineMIME("application/x-ejs", { name: "htmlembedded", scriptingModeSpec:"javascript"}); -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"}); - + "use strict"; + + CodeMirror.defineMode("htmlembedded", function(config, parserConfig) { + return CodeMirror.multiplexingMode(CodeMirror.getMode(config, "htmlmixed"), { + open: parserConfig.open || parserConfig.scriptStartRegex || "<%", + close: parserConfig.close || parserConfig.scriptEndRegex || "%>", + mode: CodeMirror.getMode(config, parserConfig.scriptingModeSpec) + }); + }, "htmlmixed"); + + CodeMirror.defineMIME("application/x-ejs", {name: "htmlembedded", scriptingModeSpec:"javascript"}); + 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/htmlembedded/index.html b/mode/htmlembedded/index.html index 93d01c4512..365ef8f366 100644 --- a/mode/htmlembedded/index.html +++ b/mode/htmlembedded/index.html @@ -10,6 +10,7 @@ +