From ac4e68497d4dcf8f72369f912d2838684d83e65b Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Wed, 21 Aug 2013 17:14:46 +0200 Subject: [PATCH 01/82] Bump version number post-3.16 --- lib/codemirror.js | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/codemirror.js b/lib/codemirror.js index be262913b4..7224b624cb 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -5821,7 +5821,7 @@ window.CodeMirror = (function() { // THE END - CodeMirror.version = "3.16.0"; + CodeMirror.version = "3.16.1"; return CodeMirror; })(); diff --git a/package.json b/package.json index 3d436b0f78..e50ba6a808 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "codemirror", - "version":"3.16.0", + "version":"3.16.1", "main": "lib/codemirror.js", "description": "In-browser code editing made bearable", "licenses": [{"type": "MIT", From 4b2b7bf5a2d9a2823beb23779cdf877bbc7ec4f8 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Wed, 21 Aug 2013 17:15:42 +0200 Subject: [PATCH 02/82] Also update version number on project page I really should automate this. --- index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.html b/index.html index 96e2eecd24..0c66a37103 100644 --- a/index.html +++ b/index.html @@ -80,7 +80,7 @@
DOWNLOAD LATEST RELEASE -
version 3.15 (Release notes)
+
version 3.16 (Release notes)
or use the minification helper
DONATE WITH PAYPAL From 595468c39ccd0eab3f19d7cb1a01d4dfb54164e1 Mon Sep 17 00:00:00 2001 From: ciaranj Date: Wed, 21 Aug 2013 22:14:38 +0100 Subject: [PATCH 03/82] [merge addon] Add highlightDifferences option and method Provides new option (highlightDifferences) and method highlightDifferences(bool) to the MergeView plugin. If true (or undefined) the original behaviour is maintained, which is to show the differences (line highlighting and gutter graphics), if false then the changes will not be shown. Calling the method causes the visual change to occur 'immediately' Signed-off-by: ciaranj --- addon/merge/merge.js | 30 ++++++++++++++++++++++++++---- demo/merge.html | 13 +++++++++---- 2 files changed, 35 insertions(+), 8 deletions(-) diff --git a/addon/merge/merge.js b/addon/merge/merge.js index 16c3356c20..01bddbd18b 100644 --- a/addon/merge/merge.js +++ b/addon/merge/merge.js @@ -31,9 +31,20 @@ this.diff = getDiff(orig, options.value); this.diffOutOfDate = false; + this.showDifferences = options.highlightDifferences === undefined ? true: !!(options.highlightDifferences); this.forceUpdate = registerUpdate(this); setScrollLock(this, true, false); registerScroll(this); + }, + highlightDifferences: function(highlight) { + var originalHighlightDifferences = this.showDifferences; + + if( highlight === undefined ) this.showDifferences= true; + else this.showDifferences = !!(highlight); + + if( this.showDifferences != originalHighlightDifferences ) { + this.forceUpdate(); + } } }; @@ -46,8 +57,9 @@ dv.diff = getDiff(dv.orig.getValue(), dv.edit.getValue()); dv.diffOutOfDate = false; } - updateMarks(dv.edit, dv.diff, edit, DIFF_INSERT, dv.classes); - updateMarks(dv.orig, dv.diff, orig, DIFF_DELETE, dv.classes); + if( !dv.showDifferences) edit.from = edit.to = orig.from = orig.to = 0; + updateMarks(dv.edit, dv.diff, edit, DIFF_INSERT, dv.classes, dv.showDifferences); + updateMarks(dv.orig, dv.diff, orig, DIFF_DELETE, dv.classes, dv.showDifferences); drawConnectors(dv); } function set(slow) { @@ -143,7 +155,12 @@ } // FIXME maybe add a margin around viewport to prevent too many updates - function updateMarks(editor, diff, state, type, classes) { + function updateMarks(editor, diff, state, type, classes, showDifferences) { + if(! showDifferences ) { + clearMarks(editor, state.marked, classes); + return; + } + var vp = editor.getViewport(); editor.operation(function() { if (state.from == state.to || vp.from - state.to > 20 || state.from - vp.to > 20) { @@ -217,6 +234,7 @@ attrs(dv.svg, "width", w, "height", dv.gap.offsetHeight); } clear(dv.copyButtons); + if( !dv.showDifferences ) return; var flip = dv.type == "left"; var vpEdit = dv.edit.getViewport(), vpOrig = dv.orig.getViewport(); @@ -322,7 +340,11 @@ constuctor: MergeView, editor: function() { return this.edit; }, rightOriginal: function() { return this.right && this.right.orig; }, - leftOriginal: function() { return this.left && this.left.orig; } + leftOriginal: function() { return this.left && this.left.orig; }, + highlightDifferences: function(highlight) { + if( this.right ) this.right.highlightDifferences(highlight); + if( this.left ) this.left.highlightDifferences(highlight); + } }; // Operations on diffs diff --git a/demo/merge.html b/demo/merge.html index d3c8eb03cc..6422a83c75 100644 --- a/demo/merge.html +++ b/demo/merge.html @@ -45,15 +45,14 @@ either two-way or three-way. The left (or center) pane is editable, and the differences with the other -pane(s) are shown live as you edit it.

+pane(s) are optionally shown live as you edit it.

This addon depends on the google-diff-match-patch library to compute the diffs.

+ + + + @@ -82,6 +86,66 @@ ]

+

From be12635c1d5d7758f7422025836dc8b27eeb0746 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Tue, 27 Aug 2013 12:04:10 +0200 Subject: [PATCH 28/82] [css-lint addon] Don't add new deprecated code, fix trailing space Issue #1782 --- addon/lint/css-lint.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/addon/lint/css-lint.js b/addon/lint/css-lint.js index 97990eef0c..ba650f6a22 100644 --- a/addon/lint/css-lint.js +++ b/addon/lint/css-lint.js @@ -6,11 +6,12 @@ CodeMirror.registerHelper("lint", "css", function(text) { for ( var i = 0; i < messages.length; i++) { message = messages[i]; var startLine = message.line -1, endLine = message.line -1, startCol = message.col -1, endCol = message.col; - found.push({from: CodeMirror.Pos(startLine, startCol), + found.push({ + from: CodeMirror.Pos(startLine, startCol), to: CodeMirror.Pos(endLine, endCol), message: message.message, - severity : message.type}); + severity : message.type + }); } return found; }); -CodeMirror.cssValidator = CodeMirror.lint.css; // deprecated From dec86385beca96993e4a9b40d82ccbf47655285b Mon Sep 17 00:00:00 2001 From: Chris Granger Date: Mon, 29 Jul 2013 09:41:56 -0700 Subject: [PATCH 29/82] Vim: raise mode change events Signed-off-by: Chris Granger --- keymap/vim.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/keymap/vim.js b/keymap/vim.js index 9c9454d6c8..9ad17af31c 100644 --- a/keymap/vim.js +++ b/keymap/vim.js @@ -40,6 +40,10 @@ * TODO: Implement the remaining special marks. They have more complex * behavior. * + * Events: + * 'vim-mode-change' - raised on the editor anytime the current mode changes, + * Event object: {mode: "visual", subMode: "linewise"} + * * Code structure: * 1. Default keymap * 2. Variable declarations and short basic helpers @@ -318,6 +322,7 @@ CodeMirror.defineOption('vimMode', false, function(cm, val) { if (val) { cm.setOption('keyMap', 'vim'); + CodeMirror.signal(cm, "vim-mode-change", {mode: "normal"}); cm.on('beforeSelectionChange', beforeSelectionChange); maybeInitVimState(cm); } else if (cm.state.vim) { @@ -579,6 +584,7 @@ !cursorEqual(cm.getCursor('head'), cm.getCursor('anchor'))) { vim.visualMode = true; vim.visualLine = false; + CodeMirror.signal(cm, "vim-mode-change", {mode: "visual"}); cm.on('mousedown', exitVisualMode); } if (key != '0' || (key == '0' && vim.inputState.getRepeat() === 0)) { @@ -1651,8 +1657,10 @@ // Handle Replace-mode as a special case of insert mode. cm.toggleOverwrite(true); cm.setOption('keyMap', 'vim-replace'); + CodeMirror.signal(cm, "vim-mode-change", {mode: "replace"}); } else { cm.setOption('keyMap', 'vim-insert'); + CodeMirror.signal(cm, "vim-mode-change", {mode: "insert"}); } if (!vimGlobalState.macroModeState.inReplay) { // Only record if not replaying. @@ -1694,6 +1702,7 @@ } else { cm.setSelection(curStart, curEnd); } + CodeMirror.signal(cm, "vim-mode-change", {mode: "visual", subMode: vim.visualLine ? "linewise" : ""}); } else { curStart = cm.getCursor('anchor'); curEnd = cm.getCursor('head'); @@ -1706,10 +1715,12 @@ curEnd.ch = cursorIsBefore(curStart, curEnd) ? lineLength(cm, curEnd.line) : 0; cm.setSelection(curStart, curEnd); + CodeMirror.signal(cm, "vim-mode-change", {mode: "visual", subMode: "linewise"}); } else if (vim.visualLine && !actionArgs.linewise) { // v pressed in linewise visual mode. Switch to characterwise visual // mode instead of exiting visual mode. vim.visualLine = false; + CodeMirror.signal(cm, "vim-mode-change", {mode: "visual"}); } else { exitVisualMode(cm); } @@ -2022,6 +2033,7 @@ // it's not supposed to be. cm.setCursor(clipCursorToContent(cm, selectionEnd)); } + CodeMirror.signal(cm, "vim-mode-change", {mode: "normal"}); } // Remove any trailing newlines from the selection. For @@ -3444,6 +3456,7 @@ vim.insertMode = false; cm.setOption('keyMap', 'vim'); cm.toggleOverwrite(false); // exit replace mode if we were in it. + CodeMirror.signal(cm, "vim-mode-change", {mode: "normal"}); } CodeMirror.keyMap['vim-insert'] = { From f8ca1785618fc534fe8d6dc473412d4c5ddd1bf0 Mon Sep 17 00:00:00 2001 From: kubelsmieci Date: Tue, 27 Aug 2013 18:02:01 +0200 Subject: [PATCH 30/82] Update markselection.html Demo was incorrectly named as showing 'Highlighter', fixed to 'Selection' --- demo/markselection.html | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/demo/markselection.html b/demo/markselection.html index 2e52af930f..454933264f 100644 --- a/demo/markselection.html +++ b/demo/markselection.html @@ -1,6 +1,6 @@ -CodeMirror: Match Highlighter Demo +CodeMirror: Match Selection Demo @@ -22,12 +22,12 @@
  • Code
  • -

    Match Highlighter Demo

    +

    Match Selection Demo

    + +

    The TOML Mode

    +

    Created by Forbes Lindesay.

    +

    MIME type defined: text/x-toml.

    +
    diff --git a/mode/toml/toml.js b/mode/toml/toml.js new file mode 100644 index 0000000000..1d163f13bf --- /dev/null +++ b/mode/toml/toml.js @@ -0,0 +1,71 @@ +CodeMirror.defineMode("toml", function () { + return { + startState: function () { + return { + inString: false, + stringType: "", + lhs: true, + inArray: 0 + }; + }, + token: function (stream, state) { + //check for state changes + if (!state.inString && ((stream.peek() == '"') || (stream.peek() == "'"))) { + state.stringType = stream.peek(); + stream.next(); // Skip quote + state.inString = true; // Update state + } + if (stream.sol() && state.inArray === 0) { + state.lhs = true; + } + //return state + if (state.inString) { + while (state.inString && !stream.eol()) { + if (stream.peek() === state.stringType) { + stream.next(); // Skip quote + state.inString = false; // Clear flag + } else if (stream.peek() === '\\') { + stream.next(); + stream.next(); + } else { + stream.match(/^.[^\\\"\']*/); + } + } + return state.lhs ? "property string" : "string"; // Token style + } else if (state.inArray && stream.peek() === ']') { + stream.next(); + state.inArray--; + return 'bracket'; + } else if (state.lhs && stream.peek() === '[' && stream.skipTo(']')) { + stream.next();//skip closing ] + return "atom"; + } else if (stream.peek() === "#") { + stream.skipToEnd(); + return "comment"; + } else if (stream.eatSpace()) { + return null; + } else if (state.lhs && stream.eatWhile(function (c) { return c != '=' && c != ' '; })) { + return "property"; + } else if (state.lhs && stream.peek() === "=") { + stream.next(); + state.lhs = false; + return null; + } else if (!state.lhs && stream.match(/^\d\d\d\d[\d\-\:\.T]*Z/)) { + return 'atom'; //date + } else if (!state.lhs && (stream.match('true') || stream.match('false'))) { + return 'atom'; + } else if (!state.lhs && stream.peek() === '[') { + state.inArray++; + stream.next(); + return 'bracket'; + } else if (!state.lhs && stream.match(/^\-?\d+(?:\.\d+)?/)) { + return 'number'; + } else if (!stream.eatSpace()) { + stream.next(); + } + return null; + } + }; +}); + +CodeMirror.defineMIME('text/x-toml', 'toml'); From df7ce151b4baf26ffbd0acb0d67ab9ac28b0e2eb Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Tue, 3 Sep 2013 18:01:44 +0200 Subject: [PATCH 37/82] [tern addon] Fix fetching of parser state Issue #1799 --- addon/tern/tern.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/addon/tern/tern.js b/addon/tern/tern.js index 1be5ba7f5d..4348c8d8e8 100644 --- a/addon/tern/tern.js +++ b/addon/tern/tern.js @@ -233,7 +233,10 @@ closeArgHints(ts); if (cm.somethingSelected()) return; - var lex = cm.getTokenAt(cm.getCursor()).state.lexical; + var state = cm.getTokenAt(cm.getCursor()).state; + var inner = CodeMirror.innerMode(cm.getMode(), state); + if (inner.mode.name != "javascript") return; + var lex = inner.state.lexical; if (lex.info != "call") return; var ch = lex.column, pos = lex.pos || 0; From 4f081574b95c73bec7214f3707b03a76647d6060 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 5 Sep 2013 10:37:02 +0200 Subject: [PATCH 38/82] [sql mode] Add comment style properties --- mode/sql/sql.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/mode/sql/sql.js b/mode/sql/sql.js index 9016cc7aae..e9dcb7fd75 100644 --- a/mode/sql/sql.js +++ b/mode/sql/sql.js @@ -180,7 +180,11 @@ CodeMirror.defineMode("sql", function(config, parserConfig) { if (!cx) return CodeMirror.Pass; if (cx.align) return cx.col + (textAfter.charAt(0) == cx.type ? 0 : 1); else return cx.indent + config.indentUnit; - } + }, + + blockCommentStart: "/*", + blockCommentEnd: "*/", + lineComment: support.commentSlashSlash ? "//" : support.commentHash ? "#" : null }; }); From 36edc05b1d7386fa5d8cb6f67214896ed95123a1 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 5 Sep 2013 11:22:45 +0200 Subject: [PATCH 39/82] In refresh, recompute line heights when no known text height Issue #1793 --- lib/codemirror.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/codemirror.js b/lib/codemirror.js index fcb6bc03dd..c9a8b9d580 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -3188,9 +3188,11 @@ window.CodeMirror = (function() { operation: function(f){return runInOp(this, f);}, refresh: operation(null, function() { + var badHeight = this.display.cachedTextHeight == null; clearCaches(this); updateScrollPos(this, this.doc.scrollLeft, this.doc.scrollTop); regChange(this); + if (badHeight) estimateLineHeights(this); }), swapDoc: operation(null, function(doc) { From 22ea8d9dbc41c108d67675d7b3a8cbdde7e7133d Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 5 Sep 2013 11:32:33 +0200 Subject: [PATCH 40/82] [matchtags addon] Don't match tags when there is a selection Closes #1802 --- addon/edit/matchtags.js | 1 + 1 file changed, 1 insertion(+) diff --git a/addon/edit/matchtags.js b/addon/edit/matchtags.js index 52e8460245..f189c1f8ef 100644 --- a/addon/edit/matchtags.js +++ b/addon/edit/matchtags.js @@ -25,6 +25,7 @@ cm.state.failedTagMatch = false; cm.operation(function() { clear(cm); + if (cm.somethingSelected()) return; var cur = cm.getCursor(), range = cm.getViewport(); range.from = Math.min(range.from, cur.line); range.to = Math.max(cur.line + 1, range.to); var match = CodeMirror.findMatchingTag(cm, cur, range); From b8e09e976015c065d7911e472bc1902d7f299940 Mon Sep 17 00:00:00 2001 From: AndersMad Date: Sat, 31 Aug 2013 09:57:19 +0200 Subject: [PATCH 41/82] [css-hint addon] Add I have created this simple css autocomplete/hint that uses data from the css mode. Autocomplete works for both properties and values - but it does not filter the values by property. Better than nothing for now. --- addon/hint/css-hint.js | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 addon/hint/css-hint.js diff --git a/addon/hint/css-hint.js b/addon/hint/css-hint.js new file mode 100644 index 0000000000..d8fe3ebaf0 --- /dev/null +++ b/addon/hint/css-hint.js @@ -0,0 +1,50 @@ +(function () { + "use strict"; + + function getHints(cm) { + var cur = cm.getCursor(), token = cm.getTokenAt(cur); + var inner = CodeMirror.innerMode(cm.getMode(), token.state); + if (inner.mode.name != "css-base") 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"; + } + + 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); + } + + return { + list: result, + from: CodeMirror.Pos(cur.line, token.start), + to: CodeMirror.Pos(cur.line, token.end) + }; + } + + CodeMirror.registerHelper("hint", "css", getHints); +})(); From 90d036d610e4ba58649ec325967b3b7ef5efd15f Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 5 Sep 2013 12:34:43 +0200 Subject: [PATCH 42/82] [css-hint addon] Integrate --- addon/hint/css-hint.js | 2 +- doc/compress.html | 1 + doc/manual.html | 4 ++++ mode/css/css.js | 12 +++++------- 4 files changed, 11 insertions(+), 8 deletions(-) diff --git a/addon/hint/css-hint.js b/addon/hint/css-hint.js index d8fe3ebaf0..2b15300d0c 100644 --- a/addon/hint/css-hint.js +++ b/addon/hint/css-hint.js @@ -4,7 +4,7 @@ function getHints(cm) { var cur = cm.getCursor(), token = cm.getTokenAt(cur); var inner = CodeMirror.innerMode(cm.getMode(), token.state); - if (inner.mode.name != "css-base") return; + if (inner.mode.name != "css") return; // If it's not a 'word-style' token, ignore the token. if (!/^[\w$_-]*$/.test(token.string)) { diff --git a/doc/compress.html b/doc/compress.html index 92c0987ba9..5ee78bb4c5 100644 --- a/doc/compress.html +++ b/doc/compress.html @@ -157,6 +157,7 @@ + diff --git a/doc/manual.html b/doc/manual.html index 3f591492b6..9f516b7e05 100644 --- a/doc/manual.html +++ b/doc/manual.html @@ -2049,6 +2049,10 @@

    Static properties

    schema data. See the demo. +
    hint/css-hint.js
    +
    A minimal hinting function for CSS code. + Defines CodeMirror.hint.css.
    +
    hint/python-hint.js
    A very simple hinting function for Python code. Defines CodeMirror.hint.python.
    diff --git a/mode/css/css.js b/mode/css/css.js index 0caebe9fac..085b119de4 100644 --- a/mode/css/css.js +++ b/mode/css/css.js @@ -1,10 +1,8 @@ -CodeMirror.defineMode("css", function(config) { - return CodeMirror.getMode(config, "text/css"); -}); - -CodeMirror.defineMode("css-base", function(config, parserConfig) { +CodeMirror.defineMode("css", function(config, parserConfig) { "use strict"; + if (!parserConfig.propertyKeywords) parserConfig = CodeMirror.resolveMode("text/css"); + var indentUnit = config.indentUnit, hooks = parserConfig.hooks || {}, atMediaTypes = parserConfig.atMediaTypes || {}, @@ -580,7 +578,7 @@ CodeMirror.defineMode("css-base", function(config, parserConfig) { return false; } }, - name: "css-base" + name: "css" }); CodeMirror.defineMIME("text/x-scss", { @@ -624,6 +622,6 @@ CodeMirror.defineMode("css-base", function(config, parserConfig) { } } }, - name: "css-base" + name: "css" }); })(); From 47965d3bd07e347b18e1ee4ab40617c7f1e41b12 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 5 Sep 2013 12:47:49 +0200 Subject: [PATCH 43/82] [closetag addon] Restructure --- addon/edit/closetag.js | 55 +++++++++++++++++++++++++------------------------- 1 file changed, 28 insertions(+), 27 deletions(-) diff --git a/addon/edit/closetag.js b/addon/edit/closetag.js index 454dfea5e6..0bf8881d08 100644 --- a/addon/edit/closetag.js +++ b/addon/edit/closetag.js @@ -27,9 +27,9 @@ if (val && (old == CodeMirror.Init || !old)) { var map = {name: "autoCloseTags"}; if (typeof val != "object" || val.whenClosing) - map["'/'"] = function(cm) { return autoCloseTag(cm, '/'); }; + map["'/'"] = function(cm) { return autoCloseSlash(cm); }; if (typeof val != "object" || val.whenOpening) - map["'>'"] = function(cm) { return autoCloseTag(cm, '>'); }; + map["'>'"] = function(cm) { return autoCloseGT(cm); }; cm.addKeyMap(map); } else if (!val && (old != CodeMirror.Init && old)) { cm.removeKeyMap("autoCloseTags"); @@ -41,40 +41,41 @@ var htmlIndent = ["applet", "blockquote", "body", "button", "div", "dl", "fieldset", "form", "frameset", "h1", "h2", "h3", "h4", "h5", "h6", "head", "html", "iframe", "layer", "legend", "object", "ol", "p", "select", "table", "ul"]; - function autoCloseTag(cm, ch) { + 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") return CodeMirror.Pass; + 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); - if (ch == ">" && state.tagName) { - var tagName = state.tagName; - 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 == "tag" && state.type == "closeTag" || - tok.string.indexOf("/") == (tok.string.length - 1) || // match something like - dontCloseTags && indexOf(dontCloseTags, lowerTagName) > -1) - return CodeMirror.Pass; + var tagName = state.tagName; + 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 == "tag" && state.type == "closeTag" || + tok.string.indexOf("/") == (tok.string.length - 1) || // match something like + dontCloseTags && indexOf(dontCloseTags, lowerTagName) > -1) + return CodeMirror.Pass; - var doIndent = indentTags && indexOf(indentTags, lowerTagName) > -1; - var curPos = doIndent ? CodeMirror.Pos(pos.line + 1, 0) : CodeMirror.Pos(pos.line, pos.ch + 1); - cm.replaceSelection(">" + (doIndent ? "\n\n" : "") + "", - {head: curPos, anchor: curPos}); - if (doIndent) { - cm.indentLine(pos.line + 1); - cm.indentLine(pos.line + 2); - } - return; - } else if (ch == "/" && tok.string == "<") { - var tagName = state.context && state.context.tagName; - if (tagName) cm.replaceSelection("/" + tagName + ">", "end"); - return; + var doIndent = indentTags && indexOf(indentTags, lowerTagName) > -1; + var curPos = doIndent ? CodeMirror.Pos(pos.line + 1, 0) : CodeMirror.Pos(pos.line, pos.ch + 1); + cm.replaceSelection(">" + (doIndent ? "\n\n" : "") + "", + {head: curPos, anchor: curPos}); + if (doIndent) { + cm.indentLine(pos.line + 1); + cm.indentLine(pos.line + 2); } - return CodeMirror.Pass; + } + + function autoCloseSlash(cm) { + var pos = cm.getCursor(), tok = cm.getTokenAt(pos); + var inner = CodeMirror.innerMode(cm.getMode(), tok.state), state = inner.state; + if (tok.string != "<" || inner.mode.name != "xml") return CodeMirror.Pass; + + var tagName = state.context && state.context.tagName; + if (tagName) cm.replaceSelection("/" + tagName + ">", "end"); } function indexOf(collection, elt) { From a55b506103247d6664ee2fe72e21a85cb86e164b Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 5 Sep 2013 12:51:31 +0200 Subject: [PATCH 44/82] [closetag addon] Allow closing by typing / even when before a word Closes #1795 --- addon/edit/closetag.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addon/edit/closetag.js b/addon/edit/closetag.js index 0bf8881d08..0bc3e8be17 100644 --- a/addon/edit/closetag.js +++ b/addon/edit/closetag.js @@ -72,7 +72,7 @@ function autoCloseSlash(cm) { var pos = cm.getCursor(), tok = cm.getTokenAt(pos); var inner = CodeMirror.innerMode(cm.getMode(), tok.state), state = inner.state; - if (tok.string != "<" || inner.mode.name != "xml") return CodeMirror.Pass; + if (tok.string.charAt(0) != "<" || inner.mode.name != "xml") return CodeMirror.Pass; var tagName = state.context && state.context.tagName; if (tagName) cm.replaceSelection("/" + tagName + ">", "end"); From f5b9d3ca9030117806a8822f48853b7ff4b8bdaa Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 5 Sep 2013 14:52:48 +0200 Subject: [PATCH 45/82] [haskell mode] Allow keyword sets to be overridden --- mode/haskell/haskell.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/mode/haskell/haskell.js b/mode/haskell/haskell.js index b18d5ced1a..59ca7f0baa 100644 --- a/mode/haskell/haskell.js +++ b/mode/haskell/haskell.js @@ -1,4 +1,4 @@ -CodeMirror.defineMode("haskell", function() { +CodeMirror.defineMode("haskell", function(_config, modeConfig) { function switchState(source, setState, f) { setState(f); @@ -221,6 +221,10 @@ CodeMirror.defineMode("haskell", function() { "unwords", "unzip", "unzip3", "userError", "words", "writeFile", "zip", "zip3", "zipWith", "zipWith3"); + var override = modeConfig.overrideKeywords; + if (override) for (var word in override) if (override.hasOwnProperty(word)) + wkw[word] = override[word]; + return wkw; })(); From fab90b772626b054ba82a81f26b9caa35a356f93 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 5 Sep 2013 15:10:51 +0200 Subject: [PATCH 46/82] [continuecomment addon] Clean up, support line comment blocks --- addon/comment/continuecomment.js | 40 +++++++++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/addon/comment/continuecomment.js b/addon/comment/continuecomment.js index 9dba156189..94e5a3760f 100644 --- a/addon/comment/continuecomment.js +++ b/addon/comment/continuecomment.js @@ -1,35 +1,43 @@ (function() { var modes = ["clike", "css", "javascript"]; for (var i = 0; i < modes.length; ++i) - CodeMirror.extendMode(modes[i], {blockCommentStart: "/*", - blockCommentEnd: "*/", - blockCommentContinue: " * "}); + CodeMirror.extendMode(modes[i], {blockCommentContinue: " * "}); function continueComment(cm) { var pos = cm.getCursor(), token = cm.getTokenAt(pos); + if (token.type != "comment") return CodeMirror.Pass; var mode = CodeMirror.innerMode(cm.getMode(), token.state).mode; - var space; - if (token.type == "comment" && mode.blockCommentStart && mode.blockCommentContinue) { + var insert; + if (mode.blockCommentStart && mode.blockCommentContinue) { var end = token.string.indexOf(mode.blockCommentEnd); var full = cm.getRange(CodeMirror.Pos(pos.line, 0), CodeMirror.Pos(pos.line, token.end)), found; if (end != -1 && end == token.string.length - mode.blockCommentEnd.length) { // Comment ended, don't continue it } else if (token.string.indexOf(mode.blockCommentStart) == 0) { - space = full.slice(0, token.start); - if (!/^\s*$/.test(space)) { - space = ""; - for (var i = 0; i < token.start; ++i) space += " "; + insert = full.slice(0, token.start); + if (!/^\s*$/.test(insert)) { + insert = ""; + for (var i = 0; i < token.start; ++i) insert += " "; } } else if ((found = full.indexOf(mode.blockCommentContinue)) != -1 && found + mode.blockCommentContinue.length > token.start && /^\s*$/.test(full.slice(0, found))) { - space = full.slice(0, found); + insert = full.slice(0, found); + } + if (insert != null) insert += mode.blockCommentContinue; + } + if (insert == null && mode.lineComment) { + var line = cm.getLine(pos.line), found = line.indexOf(mode.lineComment); + if (found > -1) { + insert = line.slice(0, found); + if (/\S/.test(insert)) insert = null; + else insert += mode.lineComment + line.slice(found + mode.lineComment.length).match(/^\s*/)[0]; } } - if (space != null) - cm.replaceSelection("\n" + space + mode.blockCommentContinue, "end"); + if (insert != null) + cm.replaceSelection("\n" + insert, "end"); else return CodeMirror.Pass; } @@ -37,8 +45,10 @@ CodeMirror.defineOption("continueComments", null, function(cm, val, prev) { if (prev && prev != CodeMirror.Init) cm.removeKeyMap("continueComment"); - var map = {name: "continueComment"}; - map[typeof val == "string" ? val : "Enter"] = continueComment; - cm.addKeyMap(map); + if (val) { + var map = {name: "continueComment"}; + map[typeof val == "string" ? val : "Enter"] = continueComment; + cm.addKeyMap(map); + } }); })(); From f8282ccd7a17c2f9b81aa90452fe04c89cc256e7 Mon Sep 17 00:00:00 2001 From: Peter Kroon Date: Thu, 5 Sep 2013 14:20:04 +0200 Subject: [PATCH 47/82] [less mode] Fix indentation of nested rules Issue #1801 --- mode/less/less.js | 98 +++++++++++++++++++++++++++---------------------------- 1 file changed, 49 insertions(+), 49 deletions(-) diff --git a/mode/less/less.js b/mode/less/less.js index 09f510e032..d637f6db98 100644 --- a/mode/less/less.js +++ b/mode/less/less.js @@ -1,7 +1,8 @@ /* LESS mode - http://www.lesscss.org/ Ported to CodeMirror by Peter Kroon - Report bugs/issues here: https://github.com/marijnh/CodeMirror/issues GitHub: @peterkroon + Report bugs/issues here: https://github.com/marijnh/CodeMirror/issues + GitHub: @peterkroon */ CodeMirror.defineMode("less", function(config) { @@ -17,68 +18,60 @@ CodeMirror.defineMode("less", function(config) { else if (ch == "/" && stream.eat("*")) { state.tokenize = tokenCComment; return tokenCComment(stream, state); - } - else if (ch == "<" && stream.eat("!")) { + } else if (ch == "<" && stream.eat("!")) { state.tokenize = tokenSGMLComment; return tokenSGMLComment(stream, state); - } - else if (ch == "=") ret(null, "compare"); + } else if (ch == "=") ret(null, "compare"); else if (ch == "|" && stream.eat("=")) return ret(null, "compare"); else if (ch == "\"" || ch == "'") { state.tokenize = tokenString(ch); return state.tokenize(stream, state); - } - else if (ch == "/") { // e.g.: .png will not be parsed as a class + } else if (ch == "/") { // e.g.: .png will not be parsed as a class if(stream.eat("/")){ state.tokenize = tokenSComment; return tokenSComment(stream, state); - }else{ - if(type == "string" || type == "(")return ret("string", "string"); - if(state.stack[state.stack.length-1] != undefined)return ret(null, ch); + } else { + if(type == "string" || type == "(") return ret("string", "string"); + if(state.stack[state.stack.length-1] != undefined) return ret(null, ch); stream.eatWhile(/[\a-zA-Z0-9\-_.\s]/); if( /\/|\)|#/.test(stream.peek() || (stream.eatSpace() && stream.peek() == ")")) || stream.eol() )return ret("string", "string"); // let url(/images/logo.png) without quotes return as string } - } - else if (ch == "!") { + } else if (ch == "!") { stream.match(/^\s*\w*/); return ret("keyword", "important"); - } - else if (/\d/.test(ch)) { + } else if (/\d/.test(ch)) { stream.eatWhile(/[\w.%]/); return ret("number", "unit"); - } - else if (/[,+<>*\/]/.test(ch)) { + } else if (/[,+<>*\/]/.test(ch)) { if(stream.peek() == "=" || type == "a")return ret("string", "string"); + if(ch === ",")return ret(null, ch); return ret(null, "select-op"); - } - else if (/[;{}:\[\]()~\|]/.test(ch)) { + } else if (/[;{}:\[\]()~\|]/.test(ch)) { if(ch == ":"){ stream.eatWhile(/[a-z\\\-]/); if( selectors.test(stream.current()) ){ return ret("tag", "tag"); - }else if(stream.peek() == ":"){//::-webkit-search-decoration + } else if(stream.peek() == ":"){//::-webkit-search-decoration stream.next(); stream.eatWhile(/[a-z\\\-]/); if(stream.current().match(/\:\:\-(o|ms|moz|webkit)\-/))return ret("string", "string"); if( selectors.test(stream.current().substring(1)) )return ret("tag", "tag"); return ret(null, ch); - }else{ + } else { return ret(null, ch); } - }else if(ch == "~"){ + } else if(ch == "~"){ if(type == "r")return ret("string", "string"); - }else{ + } else { return ret(null, ch); } - } - else if (ch == ".") { + } else if (ch == ".") { if(type == "(" || type == "string")return ret("string", "string"); // allow url(../image.png) stream.eatWhile(/[\a-zA-Z0-9\-_]/); if(stream.peek() == " ")stream.eatSpace(); if(stream.peek() == ")")return ret("number", "unit");//rgba(0,0,0,.25); return ret("tag", "tag"); - } - else if (ch == "#") { + } else if (ch == "#") { //we don't eat white-space, we want the hex color and or id only stream.eatWhile(/[A-Za-z0-9]/); //check if there is a proper hex color length e.g. #eee || #eeeEEE @@ -93,43 +86,42 @@ CodeMirror.defineMode("less", function(config) { //#time { color: #aaa } else if(stream.peek() == "}" )return ret("number", "unit"); //we have a valid hex color value, parse as id whenever an element/class is defined after the hex(id) value e.g. #eee aaa || #eee .aaa - else if( /[a-zA-Z\\]/.test(stream.peek()) )return ret("atom", "tag"); + else if( /[a-zA-Z\\]/.test(stream.peek()) )return ret("atom", "tag"); //when a hex value is on the end of a line, parse as id - else if(stream.eol())return ret("atom", "tag"); + else if(stream.eol())return ret("atom", "tag"); //default - else return ret("number", "unit"); - }else{//when not a valid hexvalue in the current stream e.g. #footer + else return ret("number", "unit"); + } else {//when not a valid hexvalue in the current stream e.g. #footer stream.eatWhile(/[\w\\\-]/); return ret("atom", "tag"); } - }else{//when not a valid hexvalue length + } else {//when not a valid hexvalue length stream.eatWhile(/[\w\\\-]/); return ret("atom", "tag"); } - } - else if (ch == "&") { + } else if (ch == "&") { stream.eatWhile(/[\w\-]/); return ret(null, ch); - } - else { + } else { stream.eatWhile(/[\w\\\-_%.{]/); + //console.log(type); if(type == "string"){ return ret("string", "string"); - }else if(stream.current().match(/(^http$|^https$)/) != null){ + } else if(stream.current().match(/(^http$|^https$)/) != null){ stream.eatWhile(/[\w\\\-_%.{:\/]/); return ret("string", "string"); - }else if(stream.peek() == "<" || stream.peek() == ">"){ + } else if(stream.peek() == "<" || stream.peek() == ">" || stream.peek() == "+"){ return ret("tag", "tag"); - }else if( /\(/.test(stream.peek()) ){ + } else if( /\(/.test(stream.peek()) ){ return ret(null, ch); - }else if (stream.peek() == "/" && state.stack[state.stack.length-1] != undefined){ // url(dir/center/image.png) + } else if (stream.peek() == "/" && state.stack[state.stack.length-1] != undefined){ // url(dir/center/image.png) return ret("string", "string"); - }else if( stream.current().match(/\-\d|\-.\d/) ){ // match e.g.: -5px -0.4 etc... only colorize the minus sign + } else if( stream.current().match(/\-\d|\-.\d/) ){ // match e.g.: -5px -0.4 etc... only colorize the minus sign //commment out these 2 comment if you want the minus sign to be parsed as null -500px //stream.backUp(stream.current().length-1); - //return ret(null, ch); //console.log( stream.current() ); + //return ret(null, ch); return ret("number", "unit"); - }else if( /\/|[\s\)]/.test(stream.peek() || stream.eol() || (stream.eatSpace() && stream.peek() == "/")) && stream.current().indexOf(".") !== -1){ + } else if( /\/|[\s\)]/.test(stream.peek() || stream.eol() || (stream.eatSpace() && stream.peek() == "/")) && stream.current().indexOf(".") !== -1){ if(stream.current().substring(stream.current().length-1,stream.current().length) == "{"){ stream.backUp(1); return ret("tag", "tag"); @@ -137,14 +129,15 @@ CodeMirror.defineMode("less", function(config) { stream.eatSpace(); if( /[{<>.a-zA-Z\/]/.test(stream.peek()) || stream.eol() )return ret("tag", "tag"); // e.g. button.icon-plus return ret("string", "string"); // let url(/images/logo.png) without quotes return as string - }else if( stream.eol() || stream.peek() == "[" || stream.peek() == "#" || type == "tag" ){ + } else if( stream.eol() || stream.peek() == "[" || stream.peek() == "#" || type == "tag" ){ if(stream.current().substring(stream.current().length-1,stream.current().length) == "{")stream.backUp(1); return ret("tag", "tag"); - }else if(type == "compare" || type == "a" || type == "("){ + } else if(type == "compare" || type == "a" || type == "("){ return ret("string", "string"); - }else if(type == "|" || stream.current() == "-" || type == "["){ + } else if(type == "|" || stream.current() == "-" || type == "["){ + if(type == "|" )return ret("tag", "tag"); return ret(null, ch); - }else if(stream.peek() == ":") { + } else if(stream.peek() == ":") { stream.next(); var t_v = stream.peek() == ":" ? true : false; if(!t_v){ @@ -156,11 +149,14 @@ CodeMirror.defineMode("less", function(config) { stream.backUp(new_pos-(old_pos-1)); return ret("tag", "tag"); } else stream.backUp(new_pos-(old_pos-1)); - }else{ + } else { stream.backUp(1); } if(t_v)return ret("tag", "tag"); else return ret("variable", "variable"); - }else{ + } else if(state.stack[state.stack.length-1] === "font-family"){ + return ret(null, null); + } else { + if(state.stack[state.stack.length-1] === "{" || type === "select-op" || (state.stack[state.stack.length-1] === "rule" && type === ",") )return ret("tag", "tag"); return ret("variable", "variable"); } } @@ -238,12 +234,16 @@ CodeMirror.defineMode("less", function(config) { } else if (type == "}") state.stack.pop(); else if (type == "@media") state.stack.push("@media"); - else if (context == "{" && type != "comment") state.stack.push("rule"); + else if (stream.current() === "font-family") state.stack[state.stack.length-1] = "font-family"; + else if (context == "{" && type != "comment" && type !== "tag") state.stack.push("rule"); + else if (stream.peek() === ":" && stream.current().match(/@|#/) === null) style = type; return style; }, indent: function(state, textAfter) { var n = state.stack.length; + console.log(n); + if (/^\}/.test(textAfter)) n -= state.stack[state.stack.length-1] == "rule" ? 2 : 1; return state.baseIndent + n * indentUnit; From b3353e715e9ae03aa7810d5533bfcb613f81a5b3 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Fri, 6 Sep 2013 09:41:26 +0200 Subject: [PATCH 48/82] [less mode] Remove console.log --- mode/less/less.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/mode/less/less.js b/mode/less/less.js index d637f6db98..8384b3cd76 100644 --- a/mode/less/less.js +++ b/mode/less/less.js @@ -104,7 +104,6 @@ CodeMirror.defineMode("less", function(config) { return ret(null, ch); } else { stream.eatWhile(/[\w\\\-_%.{]/); - //console.log(type); if(type == "string"){ return ret("string", "string"); } else if(stream.current().match(/(^http$|^https$)/) != null){ @@ -242,7 +241,6 @@ CodeMirror.defineMode("less", function(config) { indent: function(state, textAfter) { var n = state.stack.length; - console.log(n); if (/^\}/.test(textAfter)) n -= state.stack[state.stack.length-1] == "rule" ? 2 : 1; From c55df0d8666b55e1d2c195c1d98770005aeb058d Mon Sep 17 00:00:00 2001 From: Matt Pass Date: Thu, 5 Sep 2013 18:23:48 +0100 Subject: [PATCH 49/82] Better lint icons and in fewer bytes Original error & warning icons had jagged edges due to being GIFs This made them look quite poor/low quality on dark BG'd themes So, new, better looking icons added which have been run thru TinyPNG for compression Result is fewer bytes than original and they look good on dark BG's too --- addon/lint/lint.css | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/addon/lint/lint.css b/addon/lint/lint.css index a57694e00e..e592b3672a 100644 --- a/addon/lint/lint.css +++ b/addon/lint/lint.css @@ -57,15 +57,15 @@ } .CodeMirror-lint-marker-error, .CodeMirror-lint-message-error { - background-image: url("data:image/gif;base64,R0lGODlhEAAQANUAAPVvcvWHiPVucvRuc+ttcfV6f91KVN5LU99PV/FZY/JhaM4oN84pONE4Rd1ATfJLWutVYPRgbdxpcsgWKMgZKs4lNfE/UvE/U+artcpdSc5uXveimslHPuBhW/eJhfV5efaCgO2CgP+/v+PExP///////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAACUALAAAAAAQABAAAAZ+wJJwSCwaScgkySgkjTQZTkYzWhadnE5oE+pwqkSshwQqkzxfa4kkQXxEpA9J9EFI1KQGQQBAigYCBA14ExEWF0gXihETeA0QD3AkD5QQg0NsDnAJmwkOd5gYFSQKpXAFDBhqaxgLBwQBBAapq00YEg0UDRKqTGtKSL7Cw8JBADs="); + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAHlBMVEW7AAC7AACxAAC7AAC7AAAAAAC4AAC5AAD///+7AAAUdclpAAAABnRSTlMXnORSiwCK0ZKSAAAATUlEQVR42mWPOQ7AQAgDuQLx/z8csYRmPRIFIwRGnosRrpamvkKi0FTIiMASR3hhKW+hAN6/tIWhu9PDWiTGNEkTtIOucA5Oyr9ckPgAWm0GPBog6v4AAAAASUVORK5CYII="); } .CodeMirror-lint-marker-warning, .CodeMirror-lint-message-warning { - background-image: url("data:image/gif;base64,R0lGODlhEAAQANUAAP7bc//egf/ij/7ijv/jl/7kl//mnv7lnv/uwf7CTP7DTf7DT/7IW//Na/7Na//NbP7QdP/dmbltAIJNAF03AMSAJMSCLKqASa2DS6uBSquCSrGHTq6ETbCHT7WKUrKIUcCVXL+UXMOYX8GWXsSZYMiib6+ETbOIUcOXX86uhd3Muf///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAACsALAAAAAAQABAAAAZowJVwSCwaj0ihikRSJYcoBEL0XKlGkcjImQQhJBREKFnyICoThKeE/AAW6AXgdPyUAgrLJBEo0YsbAQyDhAEdRRwDDw8OaA4NDQImRBgFEJdglxAEGEQZKQcHBqOkKRpFF6mqq1WtrUEAOw=="); + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAANlBMVEX/uwDvrwD/uwD/uwD/uwD/uwD/uwD/uwD/uwD6twD/uwAAAADurwD2tQD7uAD+ugAAAAD/uwDhmeTRAAAADHRSTlMJ8mN1EYcbmiixgACm7WbuAAAAVklEQVR42n3PUQqAIBBFUU1LLc3u/jdbOJoW1P08DA9Gba8+YWJ6gNJoNYIBzAA2chBth5kLmG9YUoG0NHAUwFXwO9LuBQL1giCQb8gC9Oro2vp5rncCIY8L8uEx5ZkAAAAASUVORK5CYII="); } .CodeMirror-lint-marker-multiple { - background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAcAAAAHCAYAAADEUlfTAAAAAXNSR0IArs4c6QAAAAZiS0dEAAAAAAAA+UO7fwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sJEAQvB2JVdrAAAAAdaVRYdENvbW1lbnQAAAAAAENyZWF0ZWQgd2l0aCBHSU1QZC5lBwAAAD1JREFUCNdtjkESADAEAzemf69f66HMqGlOIhYiFRFRtSQBWAY7mzx+EDTL6sSgb1jTk7Q87rxyqe37fXsAa78gLyZnRgEAAAAASUVORK5CYII="); + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAcAAAAHCAMAAADzjKfhAAAACVBMVEUAAAAAAAC/v7914kyHAAAAAXRSTlMAQObYZgAAACNJREFUeNo1ioEJAAAIwmz/H90iFFSGJgFMe3gaLZ0od+9/AQZ0ADosbYraAAAAAElFTkSuQmCC"); background-repeat: no-repeat; background-position: right bottom; width: 100%; height: 100%; From 30a9ee56fe988d54e3bdd435f7c37af68c5c4c21 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Fri, 6 Sep 2013 10:23:44 +0200 Subject: [PATCH 50/82] Don't mutate options.gutters in setGuttersForLineNumbers Closes #1807 Closes #1808 --- lib/codemirror.js | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/lib/codemirror.js b/lib/codemirror.js index c9a8b9d580..740389fc03 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -304,15 +304,13 @@ window.CodeMirror = (function() { // Make sure the gutters options contains the element // "CodeMirror-linenumbers" when the lineNumbers option is true. function setGuttersForLineNumbers(options) { - var found = false; - for (var i = 0; i < options.gutters.length; ++i) { - if (options.gutters[i] == "CodeMirror-linenumbers") { - if (options.lineNumbers) found = true; - else options.gutters.splice(i--, 1); - } + var found = indexOf(options.gutters, "CodeMirror-linenumbers"); + if (found == -1 && options.lineNumbers) { + options.gutters = options.gutters.concat(["CodeMirror-linenumbers"]); + } else if (found > -1 && !options.lineNumbers) { + options.gutters = options.gutters.slice(0); + options.gutters.splice(i, 1); } - if (!found && options.lineNumbers) - options.gutters.push("CodeMirror-linenumbers"); } // SCROLLBARS From c8c7fc18af5f025733a930fea202d98e54e12a5e Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Fri, 6 Sep 2013 11:56:51 +0200 Subject: [PATCH 51/82] Prevent corrupted measurements due to vanishing/appearing scrollbar Issue #1787 --- lib/codemirror.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/codemirror.js b/lib/codemirror.js index 740389fc03..b4b5549ee0 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -355,6 +355,7 @@ window.CodeMirror = (function() { if (mac_geLion && scrollbarWidth(d.measure) === 0) d.scrollbarV.style.minWidth = d.scrollbarH.style.minHeight = mac_geMountainLion ? "18px" : "12px"; + return needsV; } function visibleLines(display, doc, viewPort) { @@ -410,11 +411,13 @@ window.CodeMirror = (function() { var oldFrom = cm.display.showingFrom, oldTo = cm.display.showingTo, updated; var visible = visibleLines(cm.display, cm.doc, viewPort); for (;;) { + var hadVScroll = cm.display.scroller.scrollHeight > cm.display.scroller.clientHeight + 1; if (!updateDisplayInner(cm, changes, visible, forced)) break; - forced = false; updated = true; + changes = []; updateSelection(cm); - updateScrollbars(cm); + if (updateScrollbars(cm) != hadVScroll) continue; + forced = false; // Clip forced viewport to actual scrollable area if (viewPort) @@ -423,7 +426,6 @@ window.CodeMirror = (function() { visible = visibleLines(cm.display, cm.doc, viewPort); if (visible.from >= cm.display.showingFrom && visible.to <= cm.display.showingTo) break; - changes = []; } if (updated) { From 7ea6f43856685f6d7ae71d3344cb2a1bdb1ab037 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 9 Sep 2013 10:32:32 +0200 Subject: [PATCH 52/82] Amend c8c7fc18af5f to handle window resize-tiggered updated Issue #1787 --- lib/codemirror.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/lib/codemirror.js b/lib/codemirror.js index b4b5549ee0..8b6377dc50 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -355,7 +355,6 @@ window.CodeMirror = (function() { if (mac_geLion && scrollbarWidth(d.measure) === 0) d.scrollbarV.style.minWidth = d.scrollbarH.style.minHeight = mac_geMountainLion ? "18px" : "12px"; - return needsV; } function visibleLines(display, doc, viewPort) { @@ -411,12 +410,16 @@ window.CodeMirror = (function() { var oldFrom = cm.display.showingFrom, oldTo = cm.display.showingTo, updated; var visible = visibleLines(cm.display, cm.doc, viewPort); for (;;) { - var hadVScroll = cm.display.scroller.scrollHeight > cm.display.scroller.clientHeight + 1; + var oldWidth = cm.display.scroller.clientWidth; if (!updateDisplayInner(cm, changes, visible, forced)) break; updated = true; changes = []; updateSelection(cm); - if (updateScrollbars(cm) != hadVScroll) continue; + updateScrollbars(cm); + if (cm.options.lineWrapping && oldWidth != cm.display.scroller.clientWidth) { + forced = true; + continue; + } forced = false; // Clip forced viewport to actual scrollable area From 007434607dbd4faf5c7d4c99a836e989fe8b20f5 Mon Sep 17 00:00:00 2001 From: Peter Kroon Date: Mon, 9 Sep 2013 10:38:16 +0200 Subject: [PATCH 53/82] [dtd mode] Add --- doc/compress.html | 1 + mode/dtd/dtd.js | 127 ++++++++++++++++++++++++++++++++++++++++++++++++++++ mode/dtd/index.html | 89 ++++++++++++++++++++++++++++++++++++ mode/index.html | 1 + 4 files changed, 218 insertions(+) create mode 100644 mode/dtd/dtd.js create mode 100644 mode/dtd/index.html diff --git a/doc/compress.html b/doc/compress.html index 5ee78bb4c5..d49c193263 100644 --- a/doc/compress.html +++ b/doc/compress.html @@ -86,6 +86,7 @@ + diff --git a/mode/dtd/dtd.js b/mode/dtd/dtd.js new file mode 100644 index 0000000000..7033bf0f8b --- /dev/null +++ b/mode/dtd/dtd.js @@ -0,0 +1,127 @@ +/* + DTD mode + Ported to CodeMirror by Peter Kroon + Report bugs/issues here: https://github.com/marijnh/CodeMirror/issues + GitHub: @peterkroon +*/ + +CodeMirror.defineMode("dtd", function(config) { + var indentUnit = config.indentUnit, type; + function ret(style, tp) {type = tp; return style;} + + function tokenBase(stream, state) { + var ch = stream.next(); + + if (ch == "<" && stream.eat("!") ) { + if (stream.eatWhile(/[\-]/)) { + state.tokenize = tokenSGMLComment; + return tokenSGMLComment(stream, state); + } else if (stream.eatWhile(/[\w]/)) return ret("keyword", "doindent"); + } else if (ch == "<" && stream.eat("?")) { //xml declaration + state.tokenize = inBlock("meta", "?>"); + return ret("meta", ch); + } else if (ch == "#" && stream.eatWhile(/[\w]/)) return ret("atom", "tag"); + else if (ch == "|") return ret("keyword", "seperator"); + else if (ch.match(/[\(\)\[\]\-\.,\+\?>]/)) return ret(null, ch);//if(ch === ">") return ret(null, "endtag"); else + else if (ch.match(/[\[\]]/)) return ret("rule", ch); + else if (ch == "\"" || ch == "'") { + state.tokenize = tokenString(ch); + return state.tokenize(stream, state); + } else if (stream.eatWhile(/[a-zA-Z\?\+\d]/)) { + var sc = stream.current(); + if( sc.substr(sc.length-1,sc.length).match(/\?|\+/) !== null )stream.backUp(1); + return ret("tag", "tag"); + } else if (ch == "%" || ch == "*" ) return ret("number", "number"); + else { + stream.eatWhile(/[\w\\\-_%.{,]/); + return ret(null, null); + } + } + + function tokenSGMLComment(stream, state) { + var dashes = 0, ch; + while ((ch = stream.next()) != null) { + if (dashes >= 2 && ch == ">") { + state.tokenize = tokenBase; + break; + } + dashes = (ch == "-") ? dashes + 1 : 0; + } + return ret("comment", "comment"); + } + + function tokenString(quote) { + return function(stream, state) { + var escaped = false, ch; + while ((ch = stream.next()) != null) { + if (ch == quote && !escaped) { + state.tokenize = tokenBase; + break; + } + escaped = !escaped && ch == "\\"; + } + return ret("string", "tag"); + }; + } + + function inBlock(style, terminator) { + return function(stream, state) { + while (!stream.eol()) { + if (stream.match(terminator)) { + state.tokenize = tokenBase; + break; + } + stream.next(); + } + return style; + }; + } + + return { + startState: function(base) { + return {tokenize: tokenBase, + baseIndent: base || 0, + stack: []}; + }, + + token: function(stream, state) { + if (stream.eatSpace()) return null; + var style = state.tokenize(stream, state); + + var context = state.stack[state.stack.length-1]; + if (stream.current() == "[" || type === "doindent" || type == "[") state.stack.push("rule"); + else if (type === "endtag") state.stack[state.stack.length-1] = "endtag"; + else if (stream.current() == "]" || type == "]" || (type == ">" && context == "rule")) state.stack.pop(); + else if (type == "[") state.stack.push("["); + return style; + }, + + indent: function(state, textAfter) { + var n = state.stack.length; + + if( textAfter.match(/\]\s+|\]/) )n=n-1; + else if(textAfter.substr(textAfter.length-1, textAfter.length) === ">"){ + if(textAfter.substr(0,1) === "<")n; + else if( type == "doindent" && textAfter.length > 1 )n; + else if( type == "doindent")n--; + else if( type == ">" && textAfter.length > 1)n; + else if( type == "tag" && textAfter !== ">")n; + else if( type == "tag" && state.stack[state.stack.length-1] == "rule")n--; + else if( type == "tag")n++; + else if( textAfter === ">" && state.stack[state.stack.length-1] == "rule" && type === ">")n--; + else if( textAfter === ">" && state.stack[state.stack.length-1] == "rule")n; + else if( textAfter.substr(0,1) !== "<" && textAfter.substr(0,1) === ">" )n=n-1; + else if( textAfter === ">")n; + else n=n-1; + //over rule them all + if(type == null || type == "]")n--; + } + + return state.baseIndent + n * indentUnit; + }, + + electricChars: "]>" + }; +}); + +CodeMirror.defineMIME("application/xml-dtd", "dtd"); diff --git a/mode/dtd/index.html b/mode/dtd/index.html new file mode 100644 index 0000000000..076d827f7f --- /dev/null +++ b/mode/dtd/index.html @@ -0,0 +1,89 @@ + + +CodeMirror: DTD mode + + + + + + + + + +
    +

    DTD mode

    +
    + + +

    MIME types defined: application/xml-dtd.

    +
    diff --git a/mode/index.html b/mode/index.html index 5601a2c458..2b54d60689 100644 --- a/mode/index.html +++ b/mode/index.html @@ -41,6 +41,7 @@
  • Cython
  • D
  • diff
  • +
  • DTD
  • ECL
  • Erlang
  • Gas (AT&T-style assembly)
  • From 1564808cf8d9c3fc0a66c4e95a53962312f6e12c Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 9 Sep 2013 10:46:14 +0200 Subject: [PATCH 54/82] Fix drag/drop on Chrome by setting an image src Work around a Chrome regression where it aborts the drag if the setDragImage image is src-less. Closes #1810 --- lib/codemirror.js | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/codemirror.js b/lib/codemirror.js index 8b6377dc50..ce83709954 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -1912,6 +1912,7 @@ window.CodeMirror = (function() { // Recent Safari (~6.0.2) have a tendency to segfault when this happens, so we don't do it there. if (e.dataTransfer.setDragImage && !safari) { var img = elt("img", null, null, "position: fixed; left: 0; top: 0;"); + img.src = "data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="; if (opera) { img.width = img.height = 1; cm.display.wrapper.appendChild(img); From 687026e00a0809dd8a836095c3d760ddc4cc1a08 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 9 Sep 2013 11:16:55 +0200 Subject: [PATCH 55/82] [tern addon] Compensate for fact that call start pos is a column, not char offset Closes #1811 --- addon/tern/tern.js | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/addon/tern/tern.js b/addon/tern/tern.js index 4348c8d8e8..8d35f0630b 100644 --- a/addon/tern/tern.js +++ b/addon/tern/tern.js @@ -239,9 +239,18 @@ var lex = inner.state.lexical; if (lex.info != "call") return; - var ch = lex.column, pos = lex.pos || 0; - for (var line = cm.getCursor().line, e = Math.max(0, line - 9), found = false; line >= e; --line) - if (cm.getLine(line).charAt(ch) == "(") {found = true; break;} + var ch, pos = 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;;) { + var tab = str.indexOf("\t", pos); + if (tab == -1) break; + extra += tabSize - (tab + extra) % tabSize - 1; + pos = tab + 1; + } + ch = lex.column - extra; + if (str.charAt(ch) == "(") {found = true; break;} + } if (!found) return; var start = Pos(line, ch); From e0b0e32ed97bdd9b4dcb559f0d383bbb197961e4 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 9 Sep 2013 12:32:03 +0200 Subject: [PATCH 56/82] Allow styling of lines from mode tokenizers (experimental) --- lib/codemirror.js | 37 +++++++++++++++++++++++++------------ test/test.js | 19 +++++++++++++++++++ 2 files changed, 44 insertions(+), 12 deletions(-) diff --git a/lib/codemirror.js b/lib/codemirror.js index ce83709954..a14ce5358f 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -666,10 +666,11 @@ window.CodeMirror = (function() { } function buildLineElement(cm, line, lineNo, dims, reuse) { - var lineElement = lineContent(cm, line); + var built = buildLineContent(cm, line), lineElement = built.pre; var markers = line.gutterMarkers, display = cm.display, wrap; - if (!cm.options.lineNumbers && !markers && !line.bgClass && !line.wrapClass && !line.widgets) + var bgClass = built.bgClass ? built.bgClass + " " + (line.bgClass || "") : line.bgClass; + if (!cm.options.lineNumbers && !markers && !bgClass && !line.wrapClass && !line.widgets) return lineElement; // Lines with gutter elements, widgets or a background class need @@ -707,8 +708,8 @@ window.CodeMirror = (function() { wrap.appendChild(lineElement); } // Kludge to make sure the styled element lies behind the selection (by z-index) - if (line.bgClass) - wrap.insertBefore(elt("div", null, line.bgClass + " CodeMirror-linebackground"), wrap.firstChild); + if (bgClass) + wrap.insertBefore(elt("div", null, bgClass + " CodeMirror-linebackground"), wrap.firstChild); if (cm.options.lineNumbers || markers) { var gutterWrap = wrap.insertBefore(elt("div", null, null, "position: absolute; left: " + (cm.options.fixedGutter ? dims.fixedPos : -dims.gutterTotalWidth) + "px"), @@ -1031,7 +1032,7 @@ window.CodeMirror = (function() { return crudelyMeasureLine(cm, line); var display = cm.display, measure = emptyArray(line.text.length); - var pre = lineContent(cm, line, measure, true); + var pre = buildLineContent(cm, line, measure, true).pre; // IE does not cache element positions of inline elements between // calls to getBoundingClientRect. This makes the loop below, @@ -1135,7 +1136,7 @@ window.CodeMirror = (function() { if (cached || line.text.length >= cm.options.crudeMeasuringFrom) return measureChar(cm, line, line.text.length, cached && cached.measure, "right").right; - var pre = lineContent(cm, line, null, true); + var pre = buildLineContent(cm, line, null, true).pre; var end = pre.appendChild(zeroWidthElement(cm.display.measure)); removeChildrenAndAdd(cm.display.measure, pre); return getRect(end).right - getRect(cm.display.lineDiv).left; @@ -4314,13 +4315,23 @@ window.CodeMirror = (function() { } var styleToClassCache = {}; - function styleToClass(style) { + function interpretTokenStyle(style, builder) { if (!style) return null; + for (;;) { + var lineClass = style.match(/(?:^|\s)line-(background-)?(\S+)/); + if (!lineClass) break; + style = style.slice(0, lineClass.index) + style.slice(lineClass.index + lineClass[0].length); + var prop = lineClass[1] ? "bgClass" : "textClass"; + if (builder[prop] == null) + builder[prop] = lineClass[2]; + 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-")); } - function lineContent(cm, realLine, measure, copyWidgets) { + function buildLineContent(cm, realLine, measure, copyWidgets) { var merged, line = realLine, empty = true; while (merged = collapsedSpanAtStart(line)) line = getLine(cm.doc, merged.find().from.line); @@ -4328,7 +4339,6 @@ window.CodeMirror = (function() { var builder = {pre: elt("pre"), col: 0, pos: 0, measure: null, measuredSomething: false, cm: cm, copyWidgets: copyWidgets}; - if (line.textClass) builder.pre.className = line.textClass; do { if (line.text) empty = false; @@ -4365,8 +4375,11 @@ window.CodeMirror = (function() { } } + var textClass = builder.textClass ? builder.textClass + " " + (realLine.textClass || "") : realLine.textClass; + if (textClass) builder.pre.className = textClass; + signal(cm, "renderLine", cm, realLine, builder.pre); - return builder.pre; + return builder; } var tokenSpecialChars = /[\t\u0000-\u0019\u00ad\u200b\u2028\u2029\uFEFF]/g; @@ -4477,7 +4490,7 @@ window.CodeMirror = (function() { var spans = line.markedSpans, allText = line.text, at = 0; if (!spans) { for (var i = 1; i < styles.length; i+=2) - builder.addToken(builder, allText.slice(at, at = styles[i]), styleToClass(styles[i+1])); + builder.addToken(builder, allText.slice(at, at = styles[i]), interpretTokenStyle(styles[i+1], builder)); return; } @@ -4527,7 +4540,7 @@ window.CodeMirror = (function() { spanStartStyle = ""; } text = allText.slice(at, at = styles[i++]); - style = styleToClass(styles[i++]); + style = interpretTokenStyle(styles[i++], builder); } } } diff --git a/test/test.js b/test/test.js index 21e09cb12e..a05b8afb42 100644 --- a/test/test.js +++ b/test/test.js @@ -1539,3 +1539,22 @@ testCM("change_removedText", function(cm) { eq(removedText[0].join("\n"), "abc\nd"); eq(removedText[1].join("\n"), ""); }); + +testCM("lineStyleFromMode", function(cm) { + CodeMirror.defineMode("test_mode", function() { + return {token: function(stream) { + if (stream.match(/^\[[^\]]*\]/)) return "line-brackets"; + if (stream.match(/^\([^\]]*\)/)) return "line-background-parens"; + stream.match(/^\s+|^\S+/); + }}; + }); + cm.setOption("mode", "test_mode"); + var bracketElts = byClassName(cm.getWrapperElement(), "brackets"); + eq(bracketElts.length, 1); + eq(bracketElts[0].nodeName, "PRE"); + is(!/brackets.*brackets/.test(bracketElts[0].className)); + var parenElts = byClassName(cm.getWrapperElement(), "parens"); + eq(parenElts.length, 1); + eq(parenElts[0].nodeName, "DIV"); + is(!/parens.*parens/.test(parenElts[0].className)); +}, {value: "line1: [br] [br]\nline2: (par) (par)\nline3: nothing"}); From 45d3cda933484698bfc0a8074cca717ffd2bc8eb Mon Sep 17 00:00:00 2001 From: stoskov Date: Mon, 9 Sep 2013 17:52:00 +0300 Subject: [PATCH 57/82] Add a hook to server response --- addon/tern/tern.js | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/addon/tern/tern.js b/addon/tern/tern.js index 8d35f0630b..5084539993 100644 --- a/addon/tern/tern.js +++ b/addon/tern/tern.js @@ -24,6 +24,9 @@ // no tip should be shown. By default the docstring is shown. // * typeTip: Like completionTip, but for the tooltips shown for type // queries. +// * responseFilter: A function(doc, query, request, error, data) that +// will be applied to the Tern responses before treating them +// // // It is possible to run the Tern server in a web worker by specifying // these additional options: @@ -102,8 +105,16 @@ rename: function(cm) { rename(this, cm); }, - request: function(cm, query, c) { - this.server.request(buildRequest(this, findDoc(this, cm.getDoc()), query), c); + request: function (cm, query, c) { + var self = this; + var doc = findDoc(this, cm.getDoc()); + var request = buildRequest(this, doc, query); + + this.server.request(request, function (error, data) { + if (!error && self.options.responseFilter) + data = self.options.responseFilter(doc, query, request, error, data); + c(error, data); + }); } }; From 1b3f9d090503ddb6727356224c42db3a2664e088 Mon Sep 17 00:00:00 2001 From: Peter Kroon Date: Tue, 10 Sep 2013 18:58:06 +0200 Subject: [PATCH 58/82] [lint demo] Remove duplicate script tag --- demo/lint.html | 1 - 1 file changed, 1 deletion(-) diff --git a/demo/lint.html b/demo/lint.html index 05236150ef..8372c52c47 100644 --- a/demo/lint.html +++ b/demo/lint.html @@ -13,7 +13,6 @@ - From 6dc51c9ab3d0ba68ad794ed4971a7efc46aebc3d Mon Sep 17 00:00:00 2001 From: Brett Zamir Date: Wed, 11 Sep 2013 13:50:04 +0800 Subject: [PATCH 59/82] [lint demo] missing semicolon --- demo/complete.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/demo/complete.html b/demo/complete.html index 56999b9cc9..e256a908b4 100644 --- a/demo/complete.html +++ b/demo/complete.html @@ -71,7 +71,7 @@ + From 7579444498ba0db844f4921ee59a5dbaed9f93d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=ADn=20Gait=C3=A1n?= Date: Tue, 10 Sep 2013 16:20:42 -0300 Subject: [PATCH 64/82] [fortran mode] Add --- doc/compress.html | 1 + mode/fortran/fortran.js | 173 ++++++++++++++++++++++++++++++++++++++++++++++++ mode/fortran/index.html | 81 +++++++++++++++++++++++ mode/index.html | 1 + 4 files changed, 256 insertions(+) create mode 100644 mode/fortran/fortran.js create mode 100644 mode/fortran/index.html diff --git a/doc/compress.html b/doc/compress.html index d49c193263..8548991f90 100644 --- a/doc/compress.html +++ b/doc/compress.html @@ -89,6 +89,7 @@ + diff --git a/mode/fortran/fortran.js b/mode/fortran/fortran.js new file mode 100644 index 0000000000..83fd8fde85 --- /dev/null +++ b/mode/fortran/fortran.js @@ -0,0 +1,173 @@ +CodeMirror.defineMode("fortran", function() { + function words(array) { + var keys = {}; + for (var i = 0; i < array.length; ++i) { + keys[array[i]] = true; + } + return keys; + } + + var keywords = words([ + "abstract", "accept", "allocatable", "allocate", + "array", "assign", "asynchronous", "backspace", + "bind", "block", "byte", "call", "case", + "class", "close", "common", "contains", + "continue", "cycle", "data", "deallocate", + "decode", "deferred", "dimension", "do", + "elemental", "else", "encode", "end", + "endif", "entry", "enumerator", "equivalence", + "exit", "external", "extrinsic", "final", + "forall", "format", "function", "generic", + "go", "goto", "if", "implicit", "import", "include", + "inquire", "intent", "interface", "intrinsic", + "module", "namelist", "non_intrinsic", + "non_overridable", "none", "nopass", + "nullify", "open", "optional", "options", + "parameter", "pass", "pause", "pointer", + "print", "private", "program", "protected", + "public", "pure", "read", "recursive", "result", + "return", "rewind", "save", "select", "sequence", + "stop", "subroutine", "target", "then", "to", "type", + "use", "value", "volatile", "where", "while", + "write"]); + var builtins = words(["abort", "abs", "access", "achar", "acos", + "adjustl", "adjustr", "aimag", "aint", "alarm", + "all", "allocated", "alog", "amax", "amin", + "amod", "and", "anint", "any", "asin", + "associated", "atan", "besj", "besjn", "besy", + "besyn", "bit_size", "btest", "cabs", "ccos", + "ceiling", "cexp", "char", "chdir", "chmod", + "clog", "cmplx", "command_argument_count", + "complex", "conjg", "cos", "cosh", "count", + "cpu_time", "cshift", "csin", "csqrt", "ctime", + "c_funloc", "c_loc", "c_associated", "c_null_ptr", + "c_null_funptr", "c_f_pointer", "c_null_char", + "c_alert", "c_backspace", "c_form_feed", + "c_new_line", "c_carriage_return", + "c_horizontal_tab", "c_vertical_tab", "dabs", + "dacos", "dasin", "datan", "date_and_time", + "dbesj", "dbesj", "dbesjn", "dbesy", "dbesy", + "dbesyn", "dble", "dcos", "dcosh", "ddim", "derf", + "derfc", "dexp", "digits", "dim", "dint", "dlog", + "dlog", "dmax", "dmin", "dmod", "dnint", + "dot_product", "dprod", "dsign", "dsinh", + "dsin", "dsqrt", "dtanh", "dtan", "dtime", + "eoshift", "epsilon", "erf", "erfc", "etime", + "exit", "exp", "exponent", "extends_type_of", + "fdate", "fget", "fgetc", "float", "floor", + "flush", "fnum", "fputc", "fput", "fraction", + "fseek", "fstat", "ftell", "gerror", "getarg", + "get_command", "get_command_argument", + "get_environment_variable", "getcwd", + "getenv", "getgid", "getlog", "getpid", + "getuid", "gmtime", "hostnm", "huge", "iabs", + "iachar", "iand", "iargc", "ibclr", "ibits", + "ibset", "ichar", "idate", "idim", "idint", + "idnint", "ieor", "ierrno", "ifix", "imag", + "imagpart", "index", "int", "ior", "irand", + "isatty", "ishft", "ishftc", "isign", + "iso_c_binding", "is_iostat_end", "is_iostat_eor", + "itime", "kill", "kind", "lbound", "len", "len_trim", + "lge", "lgt", "link", "lle", "llt", "lnblnk", "loc", + "log", "logical", "long", "lshift", "lstat", "ltime", + "matmul", "max", "maxexponent", "maxloc", "maxval", + "mclock", "merge", "move_alloc", "min", "minexponent", + "minloc", "minval", "mod", "modulo", "mvbits", + "nearest", "new_line", "nint", "not", "or", "pack", + "perror", "precision", "present", "product", "radix", + "rand", "random_number", "random_seed", "range", + "real", "realpart", "rename", "repeat", "reshape", + "rrspacing", "rshift", "same_type_as", "scale", + "scan", "second", "selected_int_kind", + "selected_real_kind", "set_exponent", "shape", + "short", "sign", "signal", "sinh", "sin", "sleep", + "sngl", "spacing", "spread", "sqrt", "srand", "stat", + "sum", "symlnk", "system", "system_clock", "tan", + "tanh", "time", "tiny", "transfer", "transpose", + "trim", "ttynam", "ubound", "umask", "unlink", + "unpack", "verify", "xor", "zabs", "zcos", "zexp", + "zlog", "zsin", "zsqrt"]); + + var dataTypes = words(["c_bool", "c_char", "c_double", "c_double_complex", + "c_float", "c_float_complex", "c_funptr", "c_int", + "c_int16_t", "c_int32_t", "c_int64_t", "c_int8_t", + "c_int_fast16_t", "c_int_fast32_t", "c_int_fast64_t", + "c_int_fast8_t", "c_int_least16_t", "c_int_least32_t", + "c_int_least64_t", "c_int_least8_t", "c_intmax_t", + "c_intptr_t", "c_long", "c_long_double", + "c_long_double_complex", "c_long_long", "c_ptr", + "c_short", "c_signed_char", "c_size_t", "character", + "complex", "double", "integer", "logical", "real"]); + var isOperatorChar = /[+\-*&=<>\/\:]/; + var litOperator = new RegExp("(\.and\.|\.or\.|\.eq\.|\.lt\.|\.le\.|\.gt\.|\.ge\.|\.ne\.|\.not\.|\.eqv\.|\.neqv\.)", "i"); + + function tokenBase(stream, state) { + + if (stream.match(litOperator)){ + return 'operator'; + } + + var ch = stream.next(); + if (ch == "!") { + stream.skipToEnd(); + return "comment"; + } + if (ch == '"' || ch == "'") { + state.tokenize = tokenString(ch); + return state.tokenize(stream, state); + } + if (/[\[\]\(\),]/.test(ch)) { + return null; + } + if (/\d/.test(ch)) { + stream.eatWhile(/[\w\.]/); + return "number"; + } + if (isOperatorChar.test(ch)) { + stream.eatWhile(isOperatorChar); + return "operator"; + } + stream.eatWhile(/[\w\$_]/); + var word = stream.current().toLowerCase(); + + if (keywords.hasOwnProperty(word)){ + return 'keyword'; + } + if (builtins.hasOwnProperty(word) || dataTypes.hasOwnProperty(word)) { + return 'builtin'; + } + return "variable"; + } + + function tokenString(quote) { + return function(stream, state) { + var escaped = false, next, end = false; + while ((next = stream.next()) != null) { + if (next == quote && !escaped) { + end = true; + break; + } + escaped = !escaped && next == "\\"; + } + if (end || !escaped) state.tokenize = null; + return "string"; + }; + } + + // Interface + + return { + startState: function() { + return {tokenize: null}; + }, + + token: function(stream, state) { + if (stream.eatSpace()) return null; + var style = (state.tokenize || tokenBase)(stream, state); + if (style == "comment" || style == "meta") return style; + return style; + } + }; +}); + +CodeMirror.defineMIME("text/x-fortran", "fortran"); diff --git a/mode/fortran/index.html b/mode/fortran/index.html new file mode 100644 index 0000000000..efa55ec89a --- /dev/null +++ b/mode/fortran/index.html @@ -0,0 +1,81 @@ + + +CodeMirror: Fortran mode + + + + + + + + + +
    +

    Fortran mode

    + + +
    + + + +

    MIME types defined: text/x-Fortran.

    +
    diff --git a/mode/index.html b/mode/index.html index 2b54d60689..f2bba985c2 100644 --- a/mode/index.html +++ b/mode/index.html @@ -44,6 +44,7 @@
  • DTD
  • ECL
  • Erlang
  • +
  • Fortran
  • Gas (AT&T-style assembly)
  • Go
  • Groovy
  • From afd9b56612b6326706631e363874c731da9debd7 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 16 Sep 2013 14:56:23 +0200 Subject: [PATCH 65/82] Fix false positive in IE9/10 selection reset workaround hack Closes #1820 --- lib/codemirror.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/codemirror.js b/lib/codemirror.js index a14ce5358f..10545b9573 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -1605,7 +1605,10 @@ window.CodeMirror = (function() { if (signalDOMEvent(cm, e) || cm.options.onKeyEvent && cm.options.onKeyEvent(cm, addStop(e))) return; if (e.keyCode == 16) cm.doc.sel.shift = false; })); - on(d.input, "input", bind(fastPoll, cm)); + on(d.input, "input", function() { + if (ie && !ie_lt9 && cm.display.inputHasSelection) cm.display.inputHasSelection = null; + fastPoll(cm); + }); on(d.input, "keydown", operation(cm, onKeyDown)); on(d.input, "keypress", operation(cm, onKeyPress)); on(d.input, "focus", bind(onFocus, cm)); From e470d7f4ad2e3bc60ece03e43319d3d70e15337e Mon Sep 17 00:00:00 2001 From: Tomas-A Date: Thu, 12 Sep 2013 16:53:15 +0100 Subject: [PATCH 66/82] [searchcursor addon] Fix multiple-line search There must be an error in line 73 because if the phrase starts at the same character position then conditional if will always become true (same number is equal to same number) therefore it must be changed to strict less than. --- addon/search/searchcursor.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addon/search/searchcursor.js b/addon/search/searchcursor.js index 3da3f04e8f..c034d5865b 100644 --- a/addon/search/searchcursor.js +++ b/addon/search/searchcursor.js @@ -69,8 +69,8 @@ this.matches = function(reverse, pos) { var ln = pos.line, idx = (reverse ? target.length - 1 : 0), match = target[idx], line = fold(doc.getLine(ln)); var offsetA = (reverse ? line.indexOf(match) + match.length : line.lastIndexOf(match)); - if (reverse ? offsetA >= pos.ch || offsetA != match.length - : offsetA <= pos.ch || offsetA != line.length - match.length) + if (reverse ? offsetA > pos.ch || offsetA != match.length + : offsetA < pos.ch || offsetA != line.length - match.length) return; for (;;) { if (reverse ? !ln : ln == doc.lineCount() - 1) return; From 5cd7bdcaa1498c30e6dde4bd72674345ce8e3e12 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 16 Sep 2013 15:16:11 +0200 Subject: [PATCH 67/82] [sql mode] Merge functions and builtin list for plsql dialect Closes #1803 --- mode/sql/sql.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/mode/sql/sql.js b/mode/sql/sql.js index e9dcb7fd75..63ce3fa843 100644 --- a/mode/sql/sql.js +++ b/mode/sql/sql.js @@ -266,7 +266,7 @@ CodeMirror.defineMode("sql", function(config, parserConfig) { name: "sql", client: set("charset clear connect edit ego exit go help nopager notee nowarning pager print prompt quit rehash source status system tee"), keywords: set(sqlKeywords + "accessible action add after algorithm all analyze asensitive at authors auto_increment autocommit avg avg_row_length before binary binlog both btree cache call cascade cascaded case catalog_name chain change changed character check checkpoint checksum class_origin client_statistics close coalesce code collate collation collations column columns comment commit committed completion concurrent condition connection consistent constraint contains continue contributors convert cross current_date current_time current_timestamp current_user cursor data database databases day_hour day_microsecond day_minute day_second deallocate dec declare default delay_key_write delayed delimiter des_key_file describe deterministic dev_pop dev_samp deviance directory disable discard distinctrow div dual dumpfile each elseif enable enclosed end ends engine engines enum errors escape escaped even event events every execute exists exit explain extended fast fetch field fields first flush for force foreign found_rows full fulltext function general global grant grants group groupby_concat handler hash help high_priority hosts hour_microsecond hour_minute hour_second if ignore ignore_server_ids import index index_statistics infile inner innodb inout insensitive insert_method install interval invoker isolation iterate key keys kill language last leading leave left level limit linear lines list load local localtime localtimestamp lock logs low_priority master master_heartbeat_period master_ssl_verify_server_cert masters match max max_rows maxvalue message_text middleint migrate min min_rows minute_microsecond minute_second mod mode modifies modify mutex mysql_errno natural next no no_write_to_binlog offline offset one online open optimize option optionally out outer outfile pack_keys parser partition partitions password phase plugin plugins prepare preserve prev primary privileges procedure processlist profile profiles purge query quick range read read_write reads real rebuild recover references regexp relaylog release remove rename reorganize repair repeatable replace require resignal restrict resume return returns revoke right rlike rollback rollup row row_format rtree savepoint schedule schema schema_name schemas second_microsecond security sensitive separator serializable server session share show signal slave slow smallint snapshot soname spatial specific sql sql_big_result sql_buffer_result sql_cache sql_calc_found_rows sql_no_cache sql_small_result sqlexception sqlstate sqlwarning ssl start starting starts status std stddev stddev_pop stddev_samp storage straight_join subclass_origin sum suspend table_name table_statistics tables tablespace temporary terminated to trailing transaction trigger triggers truncate uncommitted undo uninstall unique unlock upgrade usage use use_frm user user_resources user_statistics using utc_date utc_time utc_timestamp value variables varying view views warnings when while with work write xa xor year_month zerofill begin do then else loop repeat"), - builtin: set("bool boolean bit blob decimal double enum float long longblob longtext medium mediumblob mediumint mediumtext time timestamp tinyblob tinyint tinytext text bigint int int1 int2 int3 int4 int8 integer float float4 float8 double char varbinary varchar varcharacter precision date datetime year unsigned signed numeric"), + builtin: set("bool boolean bit blob decimal double float long longblob longtext medium mediumblob mediumint mediumtext time timestamp tinyblob tinyint tinytext text bigint int int1 int2 int3 int4 int8 integer float float4 float8 double char varbinary varchar varcharacter precision date datetime year unsigned signed numeric"), atoms: set("false true null unknown"), operatorChars: /^[*+\-%<>!=&|^]/, dateSQL: set("date time timestamp"), @@ -282,7 +282,7 @@ CodeMirror.defineMode("sql", function(config, parserConfig) { name: "sql", client: set("charset clear connect edit ego exit go help nopager notee nowarning pager print prompt quit rehash source status system tee"), keywords: set(sqlKeywords + "accessible action add after algorithm all always analyze asensitive at authors auto_increment autocommit avg avg_row_length before binary binlog both btree cache call cascade cascaded case catalog_name chain change changed character check checkpoint checksum class_origin client_statistics close coalesce code collate collation collations column columns comment commit committed completion concurrent condition connection consistent constraint contains continue contributors convert cross current_date current_time current_timestamp current_user cursor data database databases day_hour day_microsecond day_minute day_second deallocate dec declare default delay_key_write delayed delimiter des_key_file describe deterministic dev_pop dev_samp deviance directory disable discard distinctrow div dual dumpfile each elseif enable enclosed end ends engine engines enum errors escape escaped even event events every execute exists exit explain extended fast fetch field fields first flush for force foreign found_rows full fulltext function general generated global grant grants group groupby_concat handler hard hash help high_priority hosts hour_microsecond hour_minute hour_second if ignore ignore_server_ids import index index_statistics infile inner innodb inout insensitive insert_method install interval invoker isolation iterate key keys kill language last leading leave left level limit linear lines list load local localtime localtimestamp lock logs low_priority master master_heartbeat_period master_ssl_verify_server_cert masters match max max_rows maxvalue message_text middleint migrate min min_rows minute_microsecond minute_second mod mode modifies modify mutex mysql_errno natural next no no_write_to_binlog offline offset one online open optimize option optionally out outer outfile pack_keys parser partition partitions password persistent phase plugin plugins prepare preserve prev primary privileges procedure processlist profile profiles purge query quick range read read_write reads real rebuild recover references regexp relaylog release remove rename reorganize repair repeatable replace require resignal restrict resume return returns revoke right rlike rollback rollup row row_format rtree savepoint schedule schema schema_name schemas second_microsecond security sensitive separator serializable server session share show signal slave slow smallint snapshot soft soname spatial specific sql sql_big_result sql_buffer_result sql_cache sql_calc_found_rows sql_no_cache sql_small_result sqlexception sqlstate sqlwarning ssl start starting starts status std stddev stddev_pop stddev_samp storage straight_join subclass_origin sum suspend table_name table_statistics tables tablespace temporary terminated to trailing transaction trigger triggers truncate uncommitted undo uninstall unique unlock upgrade usage use use_frm user user_resources user_statistics using utc_date utc_time utc_timestamp value variables varying view views virtual warnings when while with work write xa xor year_month zerofill begin do then else loop repeat"), - builtin: set("bool boolean bit blob decimal double enum float long longblob longtext medium mediumblob mediumint mediumtext time timestamp tinyblob tinyint tinytext text bigint int int1 int2 int3 int4 int8 integer float float4 float8 double char varbinary varchar varcharacter precision date datetime year unsigned signed numeric"), + builtin: set("bool boolean bit blob decimal double float long longblob longtext medium mediumblob mediumint mediumtext time timestamp tinyblob tinyint tinytext text bigint int int1 int2 int3 int4 int8 integer float float4 float8 double char varbinary varchar varcharacter precision date datetime year unsigned signed numeric"), atoms: set("false true null unknown"), operatorChars: /^[*+\-%<>!=&|^]/, dateSQL: set("date time timestamp"), @@ -313,8 +313,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"), - functions: set("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("bfile blob character clob dec float int integer mlslabel natural naturaln nchar nclob number numeric nvarchar2 real rowtype signtype smallint string varchar varchar2"), + 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"), operatorChars: /^[*+\-%<>!=~]/, dateSQL: set("date time timestamp"), support: set("doubleQuote nCharCast zerolessFloat binaryNumber hexNumber") From 1bdd4cb199082187c7f9251d10337eb413001ea8 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 16 Sep 2013 15:43:40 +0200 Subject: [PATCH 68/82] Don't make changes to bgClass invalidate line measurement caches --- lib/codemirror.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/codemirror.js b/lib/codemirror.js index 10545b9573..f4ee4b1c17 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -1001,7 +1001,7 @@ window.CodeMirror = (function() { var memo = cache[i]; if (memo.text == line.text && memo.markedSpans == line.markedSpans && cm.display.scroller.clientWidth == memo.width && - memo.classes == line.textClass + "|" + line.bgClass + "|" + line.wrapClass) + memo.classes == line.textClass + "|" + line.wrapClass) return memo; } } @@ -1021,7 +1021,7 @@ window.CodeMirror = (function() { var cache = cm.display.measureLineCache; var memo = {text: line.text, width: cm.display.scroller.clientWidth, markedSpans: line.markedSpans, measure: measure, - classes: line.textClass + "|" + line.bgClass + "|" + line.wrapClass}; + classes: line.textClass + "|" + line.wrapClass}; if (cache.length == 16) cache[++cm.display.measureLineCachePos % 16] = memo; else cache.push(memo); return measure; From a59d5767655792c8888f3e6a093f6f887908f8ae Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 16 Sep 2013 15:55:52 +0200 Subject: [PATCH 69/82] [merge addon] Signal updateDiff events --- addon/merge/merge.js | 1 + 1 file changed, 1 insertion(+) diff --git a/addon/merge/merge.js b/addon/merge/merge.js index 391eb885fb..ceb48032b1 100644 --- a/addon/merge/merge.js +++ b/addon/merge/merge.js @@ -60,6 +60,7 @@ if (dv.diffOutOfDate) { dv.diff = getDiff(dv.orig.getValue(), dv.edit.getValue()); dv.diffOutOfDate = false; + CodeMirror.signal(dv.edit, "updateDiff", dv.diff); } if (dv.showDifferences) { updateMarks(dv.edit, dv.diff, edit, DIFF_INSERT, dv.classes); From ecafd26e8c3cb6de5f36fde708368505f0e1ca08 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 16 Sep 2013 16:06:25 +0200 Subject: [PATCH 70/82] Fix spanAffectsWrapping regexp for Safari Issue #1825 --- demo/spanaffectswrapping_shim.html | 2 +- lib/codemirror.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/demo/spanaffectswrapping_shim.html b/demo/spanaffectswrapping_shim.html index 00de3bdc2b..e598221c0c 100644 --- a/demo/spanaffectswrapping_shim.html +++ b/demo/spanaffectswrapping_shim.html @@ -32,7 +32,7 @@ + + + + +
    +

    Octave mode

    + +
    + + +

    MIME types defined: text/x-octave.

    +
    diff --git a/mode/octave/octave.js b/mode/octave/octave.js new file mode 100644 index 0000000000..23cd2fe222 --- /dev/null +++ b/mode/octave/octave.js @@ -0,0 +1,118 @@ +CodeMirror.defineMode("octave", function() { + function wordRegexp(words) { + return new RegExp("^((" + words.join(")|(") + "))\\b"); + } + + var singleOperators = new RegExp("^[\\+\\-\\*/&|\\^~<>!@'\\\\]"); + var singleDelimiters = new RegExp('^[\\(\\[\\{\\},:=;]'); + var doubleOperators = new RegExp("^((==)|(~=)|(<=)|(>=)|(<<)|(>>)|(\\.[\\+\\-\\*/\\^\\\\]))"); + var doubleDelimiters = new RegExp("^((!=)|(\\+=)|(\\-=)|(\\*=)|(/=)|(&=)|(\\|=)|(\\^=))"); + var tripleDelimiters = new RegExp("^((>>=)|(<<=))"); + var expressionEnd = new RegExp("^[\\]\\)]"); + var identifiers = new RegExp("^[_A-Za-z][_A-Za-z0-9]*"); + + var builtins = wordRegexp([ + 'error', 'eval', 'function', 'abs', 'acos', 'atan', 'asin', 'cos', + 'cosh', 'exp', 'log', 'prod', 'log10', 'max', 'min', 'sign', 'sin', 'sinh', + 'sqrt', 'tan', 'reshape', 'break', 'zeros', 'default', 'margin', 'round', 'ones', + 'rand', 'syn', 'ceil', 'floor', 'size', 'clear', 'zeros', 'eye', 'mean', 'std', 'cov', + 'det', 'eig', 'inv', 'norm', 'rank', 'trace', 'expm', 'logm', 'sqrtm', 'linspace', 'plot', + 'title', 'xlabel', 'ylabel', 'legend', 'text', 'meshgrid', 'mesh', 'num2str' + ]); + + var keywords = wordRegexp([ + 'return', 'case', 'switch', 'else', 'elseif', 'end', 'endif', 'endfunction', + 'if', 'otherwise', 'do', 'for', 'while', 'try', 'catch', 'classdef', 'properties', 'events', + 'methods', 'global', 'persistent', 'endfor', 'endwhile', 'printf', 'disp', 'until', 'continue' + ]); + + + // tokenizers + function tokenTranspose(stream, state) { + if (!stream.sol() && stream.peek() === '\'') { + stream.next(); + state.tokenize = tokenBase; + return 'operator'; + } + state.tokenize = tokenBase; + return tokenBase(stream, state); + } + + + function tokenComment(stream, state) { + if (stream.match(/^.*%}/)) { + state.tokenize = tokenBase; + return 'comment'; + }; + stream.skipToEnd(); + return 'comment'; + } + + function tokenBase(stream, state) { + // whitespaces + if (stream.eatSpace()) return null; + + // Handle one line Comments + if (stream.match('%{')){ + state.tokenize = tokenComment; + stream.skipToEnd(); + return 'comment'; + } + + if (stream.match(/^(%)|(\.\.\.)/)){ + stream.skipToEnd(); + return 'comment'; + } + + // Handle Number Literals + if (stream.match(/^[0-9\.+-]/, false)) { + if (stream.match(/^[+-]?0x[0-9a-fA-F]+[ij]?/)) { + stream.tokenize = tokenBase; + return 'number'; }; + if (stream.match(/^[+-]?\d*\.\d+([EeDd][+-]?\d+)?[ij]?/)) { return 'number'; }; + if (stream.match(/^[+-]?\d+([EeDd][+-]?\d+)?[ij]?/)) { return 'number'; }; + } + if (stream.match(wordRegexp(['nan','NaN','inf','Inf']))) { return 'number'; }; + + // Handle Strings + if (stream.match(/^"([^"]|(""))*"/)) { return 'string'; } ; + if (stream.match(/^'([^']|(''))*'/)) { return 'string'; } ; + + // Handle words + if (stream.match(keywords)) { return 'keyword'; } ; + if (stream.match(builtins)) { return 'builtin'; } ; + if (stream.match(identifiers)) { return 'variable'; } ; + + if (stream.match(singleOperators) || stream.match(doubleOperators)) { return 'operator'; }; + if (stream.match(singleDelimiters) || stream.match(doubleDelimiters) || stream.match(tripleDelimiters)) { return null; }; + + if (stream.match(expressionEnd)) { + state.tokenize = tokenTranspose; + return null; + }; + + + // Handle non-detected items + stream.next(); + return 'error'; + }; + + + return { + startState: function() { + return { + tokenize: tokenBase + }; + }, + + token: function(stream, state) { + var style = state.tokenize(stream, state); + if (style === 'number' || style === 'variable'){ + state.tokenize = tokenTranspose; + } + return style; + } + }; +}); + +CodeMirror.defineMIME("text/x-octave", "octave"); From 51c8aee26fd4bb175f5640307dbc41295407697f Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Tue, 17 Sep 2013 17:03:29 +0200 Subject: [PATCH 74/82] [mode/meta.js] Add missing modes --- mode/meta.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/mode/meta.js b/mode/meta.js index 9c5d986f66..ce51c8ae19 100644 --- a/mode/meta.js +++ b/mode/meta.js @@ -13,12 +13,15 @@ CodeMirror.modeInfo = [ {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: 'ECL', mime: 'text/x-ecl', mode: 'ecl'}, {name: 'Erlang', mime: 'text/x-erlang', mode: 'erlang'}, + {name: 'Fortran', mime: 'text/x-fortran', mode: 'fortran'}, {name: 'Gas', mime: 'text/x-gas', mode: 'gas'}, {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'}, @@ -40,6 +43,7 @@ CodeMirror.modeInfo = [ {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: 'Octave', mime: 'text/x-octave', mode: 'octave'}, {name: 'Pascal', mime: 'text/x-pascal', mode: 'pascal'}, {name: 'Perl', mime: 'text/x-perl', mode: 'perl'}, {name: 'PHP', mime: 'text/x-php', mode: 'php'}, @@ -69,6 +73,8 @@ CodeMirror.modeInfo = [ {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'}, From e987409ef0c42435d8658c605f3ed2e517f475e8 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 19 Sep 2013 22:18:54 +0200 Subject: [PATCH 75/82] [d mode] Remove executable flag from mode files Closes #1830 --- mode/d/d.js | 0 mode/d/index.html | 0 2 files changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 mode/d/d.js mode change 100755 => 100644 mode/d/index.html diff --git a/mode/d/d.js b/mode/d/d.js old mode 100755 new mode 100644 diff --git a/mode/d/index.html b/mode/d/index.html old mode 100755 new mode 100644 From 344446ee7b1eb7747e52f6490bac1b407a0fb9a5 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 23 Sep 2013 08:41:48 +0200 Subject: [PATCH 76/82] [real-world uses] Add nodeMirror --- doc/realworld.html | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/realworld.html b/doc/realworld.html index 040da5910a..421250162c 100644 --- a/doc/realworld.html +++ b/doc/realworld.html @@ -85,6 +85,7 @@
  • Mongo MapReduce WebBrowser
  • My2ndGeneration (social coding)
  • Navigate CMS
  • +
  • nodeMirror (IDE project)
  • NoTex (rST authoring)
  • Oak (online outliner)
  • ORG (z80 assembly IDE)
  • From d662cafbce9893e1232ccafaa9714a24388456ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guillaume=20Mass=C3=A9?= Date: Thu, 19 Sep 2013 17:15:38 -0400 Subject: [PATCH 77/82] solarized selection should match gutter --- theme/solarized.css | 26 ++------------------------ 1 file changed, 2 insertions(+), 24 deletions(-) diff --git a/theme/solarized.css b/theme/solarized.css index f6b2a3f277..1a87d2d801 100644 --- a/theme/solarized.css +++ b/theme/solarized.css @@ -99,36 +99,14 @@ http://ethanschoonover.com/solarized/img/solarized-palette.png color: #586e75; } -.cm-s-solarized.cm-s-dark .CodeMirror-focused .CodeMirror-selected { - background: #386774; - color: inherit; -} - -.cm-s-solarized.cm-s-dark ::selection { - background: #386774; - color: inherit; -} - .cm-s-solarized.cm-s-dark .CodeMirror-selected { - background: #586e75; -} - -.cm-s-solarized.cm-s-light .CodeMirror-focused .CodeMirror-selected { - background: #eee8d5; - color: inherit; -} - -.cm-s-solarized.cm-s-light ::selection { - background: #eee8d5; - color: inherit; + background: #073642; } .cm-s-solarized.cm-s-light .CodeMirror-selected { - background: #93a1a1; + background: #eee8d5; } - - /* Editor styling */ From 9d67c932a266a9c5333f74bb61af5f587ae73cde Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 23 Sep 2013 12:07:31 +0200 Subject: [PATCH 78/82] [css mode] Recognize numbers with leading dot Closes #1833 Closes #1834 --- 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 085b119de4..4264bc606c 100644 --- a/mode/css/css.js +++ b/mode/css/css.js @@ -37,7 +37,7 @@ CodeMirror.defineMode("css", function(config, parserConfig) { stream.match(/^\s*\w*/); return ret("keyword", "important"); } - else if (/\d/.test(ch)) { + else if (/\d/.test(ch) || ch == "." && stream.eat(/\d/)) { stream.eatWhile(/[\w.%]/); return ret("number", "unit"); } From d2b2ed74c55dcfe03eeaf467180041265f879009 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 23 Sep 2013 12:14:56 +0200 Subject: [PATCH 79/82] Ensure scrollbar/width instability doesn't cause infinite loop Issue #1787 --- lib/codemirror.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/codemirror.js b/lib/codemirror.js index 88f992d8af..cdf7652e72 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -409,14 +409,14 @@ window.CodeMirror = (function() { function updateDisplay(cm, changes, viewPort, forced) { var oldFrom = cm.display.showingFrom, oldTo = cm.display.showingTo, updated; var visible = visibleLines(cm.display, cm.doc, viewPort); - for (;;) { + for (var first = true;; first = false) { var oldWidth = cm.display.scroller.clientWidth; if (!updateDisplayInner(cm, changes, visible, forced)) break; updated = true; changes = []; updateSelection(cm); updateScrollbars(cm); - if (cm.options.lineWrapping && oldWidth != cm.display.scroller.clientWidth) { + if (first && cm.options.lineWrapping && oldWidth != cm.display.scroller.clientWidth) { forced = true; continue; } From a3538de0decec580bc79fa0f9237973c83c8f5a9 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 23 Sep 2013 12:30:12 +0200 Subject: [PATCH 80/82] Don't add null changes to history Issue #1836 --- lib/codemirror.js | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/codemirror.js b/lib/codemirror.js index cdf7652e72..41b4d759ed 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -2329,6 +2329,7 @@ window.CodeMirror = (function() { } function makeChangeNoReadonly(doc, change, selUpdate) { + if (change.text.length == 1 && change.text[0] == "" && posEq(change.from, change.to)) return; var selAfter = computeSelAfterChange(doc, change, selUpdate); addToHistory(doc, change, selAfter, doc.cm ? doc.cm.curOp.id : NaN); From c2f2f34b6cedebf0a1ade910e17c438e2ae49623 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 23 Sep 2013 13:02:14 +0200 Subject: [PATCH 81/82] [test suite] Fix windows/IE incompatibilities Closes #1826 --- test/test.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/test/test.js b/test/test.js index a05b8afb42..e5d9afdedd 100644 --- a/test/test.js +++ b/test/test.js @@ -1,5 +1,7 @@ var Pos = CodeMirror.Pos; +CodeMirror.defaults.rtlMoveVisually = true; + function forEach(arr, f) { for (var i = 0, e = arr.length; i < e; ++i) f(arr[i]); } @@ -529,10 +531,10 @@ testCM("multiBookmarkCursor", function(cm) { } var base1 = cm.cursorCoords(Pos(0, 1)).left, base4 = cm.cursorCoords(Pos(0, 4)).left; add(true); - eq(base1, cm.cursorCoords(Pos(0, 1)).left); + is(Math.abs(base1 - cm.cursorCoords(Pos(0, 1)).left) < .1); while (m = ms.pop()) m.clear(); add(false); - eq(base4, cm.cursorCoords(Pos(0, 1)).left); + is(Math.abs(base4 - cm.cursorCoords(Pos(0, 1)).left) < .1); }, {value: "abcdefg"}); testCM("getAllMarks", function(cm) { @@ -1159,7 +1161,7 @@ testCM("rtlMovement", function(cm) { prevX = cursor.offsetLeft; } }); -}, {rtlMoveVisually: true}); +}); // Verify that updating a line clears its bidi ordering testCM("bidiUpdate", function(cm) { From 46bab8eab13594efcb8f6752e44013ddb1502661 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 23 Sep 2013 13:50:16 +0200 Subject: [PATCH 82/82] Mark release 3.17 --- AUTHORS | 11 +++++++++++ bower.json | 2 +- doc/compress.html | 1 + doc/releases.html | 9 +++++++++ index.html | 2 +- lib/codemirror.js | 2 +- package.json | 2 +- 7 files changed, 25 insertions(+), 4 deletions(-) diff --git a/AUTHORS b/AUTHORS index bb6f8c8c64..ad2ec99576 100644 --- a/AUTHORS +++ b/AUTHORS @@ -17,6 +17,7 @@ alexey-k Alex Piggott Amy Ananya Sen +AndersMad Andre von Houck Andrey Lushnikov Andy Kimball @@ -36,6 +37,7 @@ Ben Keen boomyjee borawjm Brandon Frohs +Brett Zamir Brian Sletten Bruce Mitchener Chandra Sekhar Pydi @@ -44,6 +46,7 @@ Chris Coyier Chris Granger Chris Morgan Christopher Brown +ciaranj CodeAnimal ComFreek dagsta @@ -76,6 +79,7 @@ Felipe Lalanne Felix Raab Filip Noetzel flack +ForbesLindesay Ford_Lawnmower Gabriel Nahmias galambalazs @@ -85,6 +89,7 @@ Golevka Gordon Smith greengiant Guillaume Massé +Guillaume Massé Hans Engel Hardest Hasan Karahan @@ -137,6 +142,7 @@ komakino Konstantin Lopuhin koops ks-ifware +kubelsmieci Lanny leaf corcoran Leonya Khachaturov @@ -151,6 +157,8 @@ Marco Aurélio Marijn Haverbeke Mario Pietsch Mark Lentczner +Martin Balek +Martín Gaitán Mason Malone Mateusz Paprocki mats cronqvist @@ -219,6 +227,7 @@ Stas Kobzar Stefan Borsje Steffen Beyer Steve O'Hara +stoskov Tarmil tfjgeorge Thaddee Tyl @@ -228,6 +237,8 @@ Thomas Schmid Tim Baumann Timothy Farrell Timothy Hatcher +TobiasBg +Tomas-A Tomas Varaneckas Tom Erik Støwer Tom MacWright diff --git a/bower.json b/bower.json index 451d654c0c..2aeffb8990 100644 --- a/bower.json +++ b/bower.json @@ -1,6 +1,6 @@ { "name": "CodeMirror", - "version": "3.16.0", + "version": "3.17.0", "main": ["lib/codemirror.js", "lib/codemirror.css"], "ignore": [ "**/.*", diff --git a/doc/compress.html b/doc/compress.html index d7f720fae1..30b148dd63 100644 --- a/doc/compress.html +++ b/doc/compress.html @@ -33,6 +33,7 @@

    Version: