Upgrade to CodeMirror 4.8
This commit is contained in:
parent
b5b859d569
commit
bea92c98f8
|
@ -38,7 +38,7 @@ const (
|
|||
|
||||
const (
|
||||
WideVersion = "1.0.1" // wide version
|
||||
CodeMirrorVer = "4.7" // editor version
|
||||
CodeMirrorVer = "4.8" // editor version
|
||||
)
|
||||
|
||||
// The latest session content.
|
||||
|
|
|
@ -1,262 +0,0 @@
|
|||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
||||
|
||||
/*
|
||||
* Author: Constantin Jucovschi (c.jucovschi@jacobs-university.de)
|
||||
* Licence: MIT
|
||||
*/
|
||||
|
||||
(function(mod) {
|
||||
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
||||
mod(require("../../lib/codemirror"));
|
||||
else if (typeof define == "function" && define.amd) // AMD
|
||||
define(["../../lib/codemirror"], mod);
|
||||
else // Plain browser env
|
||||
mod(CodeMirror);
|
||||
})(function(CodeMirror) {
|
||||
"use strict";
|
||||
|
||||
CodeMirror.defineMode("stex", function() {
|
||||
"use strict";
|
||||
|
||||
function pushCommand(state, command) {
|
||||
state.cmdState.push(command);
|
||||
}
|
||||
|
||||
function peekCommand(state) {
|
||||
if (state.cmdState.length > 0) {
|
||||
return state.cmdState[state.cmdState.length - 1];
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function popCommand(state) {
|
||||
var plug = state.cmdState.pop();
|
||||
if (plug) {
|
||||
plug.closeBracket();
|
||||
}
|
||||
}
|
||||
|
||||
// returns the non-default plugin closest to the end of the list
|
||||
function getMostPowerful(state) {
|
||||
var context = state.cmdState;
|
||||
for (var i = context.length - 1; i >= 0; i--) {
|
||||
var plug = context[i];
|
||||
if (plug.name == "DEFAULT") {
|
||||
continue;
|
||||
}
|
||||
return plug;
|
||||
}
|
||||
return { styleIdentifier: function() { return null; } };
|
||||
}
|
||||
|
||||
function addPluginPattern(pluginName, cmdStyle, styles) {
|
||||
return function () {
|
||||
this.name = pluginName;
|
||||
this.bracketNo = 0;
|
||||
this.style = cmdStyle;
|
||||
this.styles = styles;
|
||||
this.argument = null; // \begin and \end have arguments that follow. These are stored in the plugin
|
||||
|
||||
this.styleIdentifier = function() {
|
||||
return this.styles[this.bracketNo - 1] || null;
|
||||
};
|
||||
this.openBracket = function() {
|
||||
this.bracketNo++;
|
||||
return "bracket";
|
||||
};
|
||||
this.closeBracket = function() {};
|
||||
};
|
||||
}
|
||||
|
||||
var plugins = {};
|
||||
|
||||
plugins["importmodule"] = addPluginPattern("importmodule", "tag", ["string", "builtin"]);
|
||||
plugins["documentclass"] = addPluginPattern("documentclass", "tag", ["", "atom"]);
|
||||
plugins["usepackage"] = addPluginPattern("usepackage", "tag", ["atom"]);
|
||||
plugins["begin"] = addPluginPattern("begin", "tag", ["atom"]);
|
||||
plugins["end"] = addPluginPattern("end", "tag", ["atom"]);
|
||||
|
||||
plugins["DEFAULT"] = function () {
|
||||
this.name = "DEFAULT";
|
||||
this.style = "tag";
|
||||
|
||||
this.styleIdentifier = this.openBracket = this.closeBracket = function() {};
|
||||
};
|
||||
|
||||
function setState(state, f) {
|
||||
state.f = f;
|
||||
}
|
||||
|
||||
// called when in a normal (no environment) context
|
||||
function normal(source, state) {
|
||||
var plug;
|
||||
// Do we look like '\command' ? If so, attempt to apply the plugin 'command'
|
||||
if (source.match(/^\\[a-zA-Z@]+/)) {
|
||||
var cmdName = source.current().slice(1);
|
||||
plug = plugins[cmdName] || plugins["DEFAULT"];
|
||||
plug = new plug();
|
||||
pushCommand(state, plug);
|
||||
setState(state, beginParams);
|
||||
return plug.style;
|
||||
}
|
||||
|
||||
// escape characters
|
||||
if (source.match(/^\\[$&%#{}_]/)) {
|
||||
return "tag";
|
||||
}
|
||||
|
||||
// white space control characters
|
||||
if (source.match(/^\\[,;!\/\\]/)) {
|
||||
return "tag";
|
||||
}
|
||||
|
||||
// find if we're starting various math modes
|
||||
if (source.match("\\[")) {
|
||||
setState(state, function(source, state){ return inMathMode(source, state, "\\]"); });
|
||||
return "keyword";
|
||||
}
|
||||
if (source.match("$$")) {
|
||||
setState(state, function(source, state){ return inMathMode(source, state, "$$"); });
|
||||
return "keyword";
|
||||
}
|
||||
if (source.match("$")) {
|
||||
setState(state, function(source, state){ return inMathMode(source, state, "$"); });
|
||||
return "keyword";
|
||||
}
|
||||
|
||||
var ch = source.next();
|
||||
if (ch == "%") {
|
||||
// special case: % at end of its own line; stay in same state
|
||||
if (!source.eol()) {
|
||||
setState(state, inCComment);
|
||||
}
|
||||
return "comment";
|
||||
}
|
||||
else if (ch == '}' || ch == ']') {
|
||||
plug = peekCommand(state);
|
||||
if (plug) {
|
||||
plug.closeBracket(ch);
|
||||
setState(state, beginParams);
|
||||
} else {
|
||||
return "error";
|
||||
}
|
||||
return "bracket";
|
||||
} else if (ch == '{' || ch == '[') {
|
||||
plug = plugins["DEFAULT"];
|
||||
plug = new plug();
|
||||
pushCommand(state, plug);
|
||||
return "bracket";
|
||||
}
|
||||
else if (/\d/.test(ch)) {
|
||||
source.eatWhile(/[\w.%]/);
|
||||
return "atom";
|
||||
}
|
||||
else {
|
||||
source.eatWhile(/[\w\-_]/);
|
||||
plug = getMostPowerful(state);
|
||||
if (plug.name == 'begin') {
|
||||
plug.argument = source.current();
|
||||
}
|
||||
return plug.styleIdentifier();
|
||||
}
|
||||
}
|
||||
|
||||
function inCComment(source, state) {
|
||||
source.skipToEnd();
|
||||
setState(state, normal);
|
||||
return "comment";
|
||||
}
|
||||
|
||||
function inMathMode(source, state, endModeSeq) {
|
||||
if (source.eatSpace()) {
|
||||
return null;
|
||||
}
|
||||
if (source.match(endModeSeq)) {
|
||||
setState(state, normal);
|
||||
return "keyword";
|
||||
}
|
||||
if (source.match(/^\\[a-zA-Z@]+/)) {
|
||||
return "tag";
|
||||
}
|
||||
if (source.match(/^[a-zA-Z]+/)) {
|
||||
return "variable-2";
|
||||
}
|
||||
// escape characters
|
||||
if (source.match(/^\\[$&%#{}_]/)) {
|
||||
return "tag";
|
||||
}
|
||||
// white space control characters
|
||||
if (source.match(/^\\[,;!\/]/)) {
|
||||
return "tag";
|
||||
}
|
||||
// special math-mode characters
|
||||
if (source.match(/^[\^_&]/)) {
|
||||
return "tag";
|
||||
}
|
||||
// non-special characters
|
||||
if (source.match(/^[+\-<>|=,\/@!*:;'"`~#?]/)) {
|
||||
return null;
|
||||
}
|
||||
if (source.match(/^(\d+\.\d*|\d*\.\d+|\d+)/)) {
|
||||
return "number";
|
||||
}
|
||||
var ch = source.next();
|
||||
if (ch == "{" || ch == "}" || ch == "[" || ch == "]" || ch == "(" || ch == ")") {
|
||||
return "bracket";
|
||||
}
|
||||
|
||||
// eat comments here, because inCComment returns us to normal state!
|
||||
if (ch == "%") {
|
||||
if (!source.eol()) {
|
||||
source.skipToEnd();
|
||||
}
|
||||
return "comment";
|
||||
}
|
||||
return "error";
|
||||
}
|
||||
|
||||
function beginParams(source, state) {
|
||||
var ch = source.peek(), lastPlug;
|
||||
if (ch == '{' || ch == '[') {
|
||||
lastPlug = peekCommand(state);
|
||||
lastPlug.openBracket(ch);
|
||||
source.eat(ch);
|
||||
setState(state, normal);
|
||||
return "bracket";
|
||||
}
|
||||
if (/[ \t\r]/.test(ch)) {
|
||||
source.eat(ch);
|
||||
return null;
|
||||
}
|
||||
setState(state, normal);
|
||||
popCommand(state);
|
||||
|
||||
return normal(source, state);
|
||||
}
|
||||
|
||||
return {
|
||||
startState: function() {
|
||||
return {
|
||||
cmdState: [],
|
||||
f: normal
|
||||
};
|
||||
},
|
||||
copyState: function(s) {
|
||||
return {
|
||||
cmdState: s.cmdState.slice(),
|
||||
f: s.f
|
||||
};
|
||||
},
|
||||
token: function(stream, state) {
|
||||
return state.f(stream, state);
|
||||
},
|
||||
lineComment: "%"
|
||||
};
|
||||
});
|
||||
|
||||
CodeMirror.defineMIME("text/x-stex", "stex");
|
||||
CodeMirror.defineMIME("text/x-latex", "stex");
|
||||
|
||||
});
|
|
@ -71,7 +71,7 @@
|
|||
};
|
||||
var closingBrackets = "";
|
||||
for (var i = 0; i < pairs.length; i += 2) (function(left, right) {
|
||||
if (left != right) closingBrackets += right;
|
||||
closingBrackets += right;
|
||||
map["'" + left + "'"] = function(cm) {
|
||||
if (cm.getOption("disableInput")) return CodeMirror.Pass;
|
||||
var ranges = cm.listSelections(), type, next;
|
|
@ -93,7 +93,7 @@
|
|||
"if in instanceof isnt new no not null of off on or return switch then throw true try typeof until void while with yes").split(" ");
|
||||
|
||||
function getCompletions(token, context, keywords, options) {
|
||||
var found = [], start = token.string;
|
||||
var found = [], start = token.string, global = options && options.globalScope || window;
|
||||
function maybeAdd(str) {
|
||||
if (str.lastIndexOf(start, 0) == 0 && !arrayContains(found, str)) found.push(str);
|
||||
}
|
||||
|
@ -112,28 +112,28 @@
|
|||
if (options && options.additionalContext)
|
||||
base = options.additionalContext[obj.string];
|
||||
if (!options || options.useGlobalScope !== false)
|
||||
base = base || window[obj.string];
|
||||
base = base || global[obj.string];
|
||||
} else if (obj.type == "string") {
|
||||
base = "";
|
||||
} else if (obj.type == "atom") {
|
||||
base = 1;
|
||||
} else if (obj.type == "function") {
|
||||
if (window.jQuery != null && (obj.string == '$' || obj.string == 'jQuery') &&
|
||||
(typeof window.jQuery == 'function'))
|
||||
base = window.jQuery();
|
||||
else if (window._ != null && (obj.string == '_') && (typeof window._ == 'function'))
|
||||
base = window._();
|
||||
if (global.jQuery != null && (obj.string == '$' || obj.string == 'jQuery') &&
|
||||
(typeof global.jQuery == 'function'))
|
||||
base = global.jQuery();
|
||||
else if (global._ != null && (obj.string == '_') && (typeof global._ == 'function'))
|
||||
base = global._();
|
||||
}
|
||||
while (base != null && context.length)
|
||||
base = base[context.pop().string];
|
||||
if (base != null) gatherCompletions(base);
|
||||
} else {
|
||||
// If not, just look in the window object and any local scope
|
||||
// If not, just look in the global object and any local scope
|
||||
// (reading into JS mode internals to get at the local and global variables)
|
||||
for (var v = token.state.localVars; v; v = v.next) maybeAdd(v.name);
|
||||
for (var v = token.state.globalVars; v; v = v.next) maybeAdd(v.name);
|
||||
if (!options || options.useGlobalScope !== false)
|
||||
gatherCompletions(window);
|
||||
gatherCompletions(global);
|
||||
forEach(keywords, maybeAdd);
|
||||
}
|
||||
return found;
|
|
@ -18,10 +18,17 @@
|
|||
var quote = (options && options.quoteChar) || '"';
|
||||
if (!tags) return;
|
||||
var cur = cm.getCursor(), token = cm.getTokenAt(cur);
|
||||
if (/^<\/?$/.test(token.string) && token.end == cur.ch) {
|
||||
var nextToken = cm.getTokenAt(Pos(cur.line, cur.ch + 1));
|
||||
if (nextToken.start == cur.ch && /\btag\b/.test(nextToken.type))
|
||||
token = nextToken;
|
||||
}
|
||||
var inner = CodeMirror.innerMode(cm.getMode(), token.state);
|
||||
if (inner.mode.name != "xml") return;
|
||||
var result = [], replaceToken = false, prefix;
|
||||
var tag = /\btag\b/.test(token.type), tagName = tag && /^\w/.test(token.string), tagStart;
|
||||
var tag = /\btag\b/.test(token.type) && !/>$/.test(token.string);
|
||||
var tagName = tag && /^\w/.test(token.string), tagStart;
|
||||
|
||||
if (tagName) {
|
||||
var before = cm.getLine(cur.line).slice(Math.max(0, token.start - 2), token.start);
|
||||
var tagType = /<\/$/.test(before) ? "close" : /<$/.test(before) ? "open" : null;
|
||||
|
@ -31,6 +38,7 @@
|
|||
} else if (tag && token.string == "</") {
|
||||
tagType = "close";
|
||||
}
|
||||
|
||||
if (!tag && !inner.state.tagName || tagType) {
|
||||
if (tagName)
|
||||
prefix = token.string;
|
|
@ -3,12 +3,12 @@
|
|||
|
||||
(function(mod) {
|
||||
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
||||
mod(require("../../lib/codemirror"));
|
||||
mod(require("../../lib/codemirror"), "cjs");
|
||||
else if (typeof define == "function" && define.amd) // AMD
|
||||
define(["../../lib/codemirror"], mod);
|
||||
define(["../../lib/codemirror"], function(CM) { mod(CM, "amd"); });
|
||||
else // Plain browser env
|
||||
mod(CodeMirror);
|
||||
})(function(CodeMirror) {
|
||||
mod(CodeMirror, "plain");
|
||||
})(function(CodeMirror, env) {
|
||||
if (!CodeMirror.modeURL) CodeMirror.modeURL = "../mode/%N/%N.js";
|
||||
|
||||
var loading = {};
|
||||
|
@ -35,21 +35,24 @@
|
|||
if (CodeMirror.modes.hasOwnProperty(mode)) return ensureDeps(mode, cont);
|
||||
if (loading.hasOwnProperty(mode)) return loading[mode].push(cont);
|
||||
|
||||
var script = document.createElement("script");
|
||||
script.src = CodeMirror.modeURL.replace(/%N/g, mode);
|
||||
var others = document.getElementsByTagName("script")[0];
|
||||
others.parentNode.insertBefore(script, others);
|
||||
var list = loading[mode] = [cont];
|
||||
var count = 0, poll = setInterval(function() {
|
||||
if (++count > 100) return clearInterval(poll);
|
||||
if (CodeMirror.modes.hasOwnProperty(mode)) {
|
||||
clearInterval(poll);
|
||||
loading[mode] = null;
|
||||
var file = CodeMirror.modeURL.replace(/%N/g, mode);
|
||||
if (env == "plain") {
|
||||
var script = document.createElement("script");
|
||||
script.src = file;
|
||||
var others = document.getElementsByTagName("script")[0];
|
||||
var list = loading[mode] = [cont];
|
||||
CodeMirror.on(script, "load", function() {
|
||||
ensureDeps(mode, function() {
|
||||
for (var i = 0; i < list.length; ++i) list[i]();
|
||||
});
|
||||
}
|
||||
}, 200);
|
||||
});
|
||||
others.parentNode.insertBefore(script, others);
|
||||
} else if (env == "cjs") {
|
||||
require(file);
|
||||
cont();
|
||||
} else if (env == "amd") {
|
||||
requirejs([file], cont);
|
||||
}
|
||||
};
|
||||
|
||||
CodeMirror.autoLoadMode = function(instance, mode) {
|
|
@ -28,7 +28,7 @@ CodeMirror.overlayMode = function(base, overlay, combine) {
|
|||
overlay: CodeMirror.startState(overlay),
|
||||
basePos: 0, baseCur: null,
|
||||
overlayPos: 0, overlayCur: null,
|
||||
lineSeen: null
|
||||
streamSeen: null
|
||||
};
|
||||
},
|
||||
copyState: function(state) {
|
||||
|
@ -41,9 +41,9 @@ CodeMirror.overlayMode = function(base, overlay, combine) {
|
|||
},
|
||||
|
||||
token: function(stream, state) {
|
||||
if (stream.sol() || stream.string != state.lineSeen ||
|
||||
if (stream != state.streamSeen ||
|
||||
Math.min(state.basePos, state.overlayPos) < stream.start) {
|
||||
state.lineSeen = stream.string;
|
||||
state.streamSeen = stream;
|
||||
state.basePos = state.overlayPos = stream.start;
|
||||
}
|
||||
|
|
@ -52,12 +52,12 @@
|
|||
.CodeMirror div.CodeMirror-secondarycursor {
|
||||
border-left: 1px solid silver;
|
||||
}
|
||||
.CodeMirror.cm-keymap-fat-cursor div.CodeMirror-cursor {
|
||||
.CodeMirror.cm-fat-cursor div.CodeMirror-cursor {
|
||||
width: auto;
|
||||
border: 0;
|
||||
background: #7e7;
|
||||
}
|
||||
.CodeMirror.cm-keymap-fat-cursor div.CodeMirror-cursors {
|
||||
.CodeMirror.cm-fat-cursor div.CodeMirror-cursors {
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
|
@ -125,6 +125,7 @@ div.CodeMirror-overwrite div.CodeMirror-cursor {}
|
|||
.cm-header, .cm-strong {font-weight: bold;}
|
||||
.cm-em {font-style: italic;}
|
||||
.cm-link {text-decoration: underline;}
|
||||
.cm-strikethrough {text-decoration: line-through;}
|
||||
|
||||
.cm-s-default .cm-error {color: #f00;}
|
||||
.cm-invalidchar {color: #f00;}
|
||||
|
@ -209,6 +210,11 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
|
|||
*zoom:1;
|
||||
*display:inline;
|
||||
}
|
||||
.CodeMirror-gutter-wrapper {
|
||||
position: absolute;
|
||||
z-index: 4;
|
||||
height: 100%;
|
||||
}
|
||||
.CodeMirror-gutter-elt {
|
||||
position: absolute;
|
||||
cursor: default;
|
||||
|
@ -305,5 +311,8 @@ div.CodeMirror-cursors {
|
|||
}
|
||||
}
|
||||
|
||||
/* See issue #2901 */
|
||||
.cm-tab-wrap-hack:after { content: ''; }
|
||||
|
||||
/* Help users use markselection to safely style text background */
|
||||
span.CodeMirror-selectedtext { background: none; }
|
|
@ -86,7 +86,8 @@
|
|||
suppressEdits: false, // used to disable editing during key handlers when in readOnly mode
|
||||
pasteIncoming: false, cutIncoming: false, // help recognize paste/cut edits in readInput
|
||||
draggingText: false,
|
||||
highlight: new Delayed() // stores highlight worker timeout
|
||||
highlight: new Delayed(), // stores highlight worker timeout
|
||||
keySeq: null // Unfinished key sequence
|
||||
};
|
||||
|
||||
// Override magic textarea content restore that IE sometimes does
|
||||
|
@ -184,8 +185,10 @@
|
|||
// Need to set a minimum width to see the scrollbar on IE7 (but must not set it on IE8).
|
||||
if (ie && ie_version < 8) d.scrollbarH.style.minHeight = d.scrollbarV.style.minWidth = "18px";
|
||||
|
||||
if (place.appendChild) place.appendChild(d.wrapper);
|
||||
else place(d.wrapper);
|
||||
if (place) {
|
||||
if (place.appendChild) place.appendChild(d.wrapper);
|
||||
else place(d.wrapper);
|
||||
}
|
||||
|
||||
// Current rendered range (may be bigger than the view window).
|
||||
d.viewFrom = d.viewTo = doc.first;
|
||||
|
@ -196,7 +199,7 @@
|
|||
d.externalMeasured = null;
|
||||
// Empty space (in pixels) above the view
|
||||
d.viewOffset = 0;
|
||||
d.lastSizeC = 0;
|
||||
d.lastWrapHeight = d.lastWrapWidth = 0;
|
||||
d.updateLineNumbers = null;
|
||||
|
||||
// Used to only resize the line number gutter when necessary (when
|
||||
|
@ -301,12 +304,6 @@
|
|||
});
|
||||
}
|
||||
|
||||
function keyMapChanged(cm) {
|
||||
var map = keyMap[cm.options.keyMap], style = map.style;
|
||||
cm.display.wrapper.className = cm.display.wrapper.className.replace(/\s*cm-keymap-\S+/g, "") +
|
||||
(style ? " cm-keymap-" + style : "");
|
||||
}
|
||||
|
||||
function themeChanged(cm) {
|
||||
cm.display.wrapper.className = cm.display.wrapper.className.replace(/\s*cm-s-\S+/g, "") +
|
||||
cm.options.theme.replace(/(^|\s)\s*/g, " cm-s-");
|
||||
|
@ -551,6 +548,7 @@
|
|||
this.visible = visibleLines(display, cm.doc, viewport);
|
||||
this.editorIsHidden = !display.wrapper.offsetWidth;
|
||||
this.wrapperHeight = display.wrapper.clientHeight;
|
||||
this.wrapperWidth = display.wrapper.clientWidth;
|
||||
this.oldViewFrom = display.viewFrom; this.oldViewTo = display.viewTo;
|
||||
this.oldScrollerWidth = display.scroller.clientWidth;
|
||||
this.force = force;
|
||||
|
@ -591,7 +589,7 @@
|
|||
}
|
||||
|
||||
var different = from != display.viewFrom || to != display.viewTo ||
|
||||
display.lastSizeC != update.wrapperHeight;
|
||||
display.lastWrapHeight != update.wrapperHeight || display.lastWrapWidth != update.wrapperWidth;
|
||||
adjustView(cm, from, to);
|
||||
|
||||
display.viewOffset = heightAtLine(getLine(cm.doc, display.viewFrom));
|
||||
|
@ -619,7 +617,8 @@
|
|||
removeChildren(display.selectionDiv);
|
||||
|
||||
if (different) {
|
||||
display.lastSizeC = update.wrapperHeight;
|
||||
display.lastWrapHeight = update.wrapperHeight;
|
||||
display.lastWrapWidth = update.wrapperWidth;
|
||||
startWorker(cm, 400);
|
||||
}
|
||||
|
||||
|
@ -868,9 +867,12 @@
|
|||
if (cm.options.lineNumbers || markers) {
|
||||
var wrap = ensureLineWrapped(lineView);
|
||||
var gutterWrap = lineView.gutter =
|
||||
wrap.insertBefore(elt("div", null, "CodeMirror-gutter-wrapper", "position: absolute; left: " +
|
||||
(cm.options.fixedGutter ? dims.fixedPos : -dims.gutterTotalWidth) + "px"),
|
||||
wrap.insertBefore(elt("div", null, "CodeMirror-gutter-wrapper", "left: " +
|
||||
(cm.options.fixedGutter ? dims.fixedPos : -dims.gutterTotalWidth) +
|
||||
"px; width: " + dims.gutterTotalWidth + "px"),
|
||||
lineView.text);
|
||||
if (lineView.line.gutterClass)
|
||||
gutterWrap.className += " " + lineView.line.gutterClass;
|
||||
if (cm.options.lineNumbers && (!markers || !markers["CodeMirror-linenumbers"]))
|
||||
lineView.lineNumber = gutterWrap.appendChild(
|
||||
elt("div", lineNumberFor(cm.options, lineN),
|
||||
|
@ -2397,7 +2399,7 @@
|
|||
// possible when it is clear that nothing happened. hasSelection
|
||||
// will be the case when there is a lot of text in the textarea,
|
||||
// in which case reading its value would be expensive.
|
||||
if (!cm.state.focused || (hasSelection(input) && !prevInput) || isReadOnly(cm) || cm.options.disableInput)
|
||||
if (!cm.state.focused || (hasSelection(input) && !prevInput) || isReadOnly(cm) || cm.options.disableInput || cm.state.keySeq)
|
||||
return false;
|
||||
// See paste handler for more on the fakedLastChar kludge
|
||||
if (cm.state.pasteIncoming && cm.state.fakedLastChar) {
|
||||
|
@ -2652,8 +2654,10 @@
|
|||
|
||||
// Called when the window resizes
|
||||
function onResize(cm) {
|
||||
// Might be a text scaling operation, clear size caches.
|
||||
var d = cm.display;
|
||||
if (d.lastWrapHeight == d.wrapper.clientHeight && d.lastWrapWidth == d.wrapper.clientWidth)
|
||||
return;
|
||||
// Might be a text scaling operation, clear size caches.
|
||||
d.cachedCharWidth = d.cachedTextHeight = d.cachedPaddingH = null;
|
||||
cm.setSize();
|
||||
}
|
||||
|
@ -3167,62 +3171,70 @@
|
|||
return done;
|
||||
}
|
||||
|
||||
// Collect the currently active keymaps.
|
||||
function allKeyMaps(cm) {
|
||||
var maps = cm.state.keyMaps.slice(0);
|
||||
if (cm.options.extraKeys) maps.push(cm.options.extraKeys);
|
||||
maps.push(cm.options.keyMap);
|
||||
return maps;
|
||||
function lookupKeyForEditor(cm, name, handle) {
|
||||
for (var i = 0; i < cm.state.keyMaps.length; i++) {
|
||||
var result = lookupKey(name, cm.state.keyMaps[i], handle);
|
||||
if (result) return result;
|
||||
}
|
||||
return (cm.options.extraKeys && lookupKey(name, cm.options.extraKeys, handle))
|
||||
|| lookupKey(name, cm.options.keyMap, handle);
|
||||
}
|
||||
|
||||
var stopSeq = new Delayed;
|
||||
function dispatchKey(cm, name, e, handle) {
|
||||
var seq = cm.state.keySeq;
|
||||
if (seq) {
|
||||
if (isModifierKey(name)) return "handled";
|
||||
stopSeq.set(50, function() {
|
||||
if (cm.state.keySeq == seq) {
|
||||
cm.state.keySeq = null;
|
||||
resetInput(cm);
|
||||
}
|
||||
});
|
||||
name = seq + " " + name;
|
||||
}
|
||||
var result = lookupKeyForEditor(cm, name, handle);
|
||||
|
||||
if (result == "multi")
|
||||
cm.state.keySeq = name;
|
||||
if (result == "handled")
|
||||
signalLater(cm, "keyHandled", cm, name, e);
|
||||
|
||||
if (result == "handled" || result == "multi") {
|
||||
e_preventDefault(e);
|
||||
restartBlink(cm);
|
||||
}
|
||||
|
||||
if (seq && !result && /\'$/.test(name)) {
|
||||
e_preventDefault(e);
|
||||
return true;
|
||||
}
|
||||
return !!result;
|
||||
}
|
||||
|
||||
var maybeTransition;
|
||||
// Handle a key from the keydown event.
|
||||
function handleKeyBinding(cm, e) {
|
||||
// Handle automatic keymap transitions
|
||||
var startMap = getKeyMap(cm.options.keyMap), next = startMap.auto;
|
||||
clearTimeout(maybeTransition);
|
||||
if (next && !isModifierKey(e)) maybeTransition = setTimeout(function() {
|
||||
if (getKeyMap(cm.options.keyMap) == startMap) {
|
||||
cm.options.keyMap = (next.call ? next.call(null, cm) : next);
|
||||
keyMapChanged(cm);
|
||||
}
|
||||
}, 50);
|
||||
|
||||
var name = keyName(e, true), handled = false;
|
||||
var name = keyName(e, true);
|
||||
if (!name) return false;
|
||||
var keymaps = allKeyMaps(cm);
|
||||
|
||||
if (e.shiftKey) {
|
||||
if (e.shiftKey && !cm.state.keySeq) {
|
||||
// First try to resolve full name (including 'Shift-'). Failing
|
||||
// that, see if there is a cursor-motion command (starting with
|
||||
// 'go') bound to the keyname without 'Shift-'.
|
||||
handled = lookupKey("Shift-" + name, keymaps, function(b) {return doHandleBinding(cm, b, true);})
|
||||
|| lookupKey(name, keymaps, function(b) {
|
||||
if (typeof b == "string" ? /^go[A-Z]/.test(b) : b.motion)
|
||||
return doHandleBinding(cm, b);
|
||||
});
|
||||
return dispatchKey(cm, "Shift-" + name, e, function(b) {return doHandleBinding(cm, b, true);})
|
||||
|| dispatchKey(cm, name, e, function(b) {
|
||||
if (typeof b == "string" ? /^go[A-Z]/.test(b) : b.motion)
|
||||
return doHandleBinding(cm, b);
|
||||
});
|
||||
} else {
|
||||
handled = lookupKey(name, keymaps, function(b) { return doHandleBinding(cm, b); });
|
||||
return dispatchKey(cm, name, e, function(b) { return doHandleBinding(cm, b); });
|
||||
}
|
||||
|
||||
if (handled) {
|
||||
e_preventDefault(e);
|
||||
restartBlink(cm);
|
||||
signalLater(cm, "keyHandled", cm, name, e);
|
||||
}
|
||||
return handled;
|
||||
}
|
||||
|
||||
// Handle a key from the keypress event
|
||||
function handleCharBinding(cm, e, ch) {
|
||||
var handled = lookupKey("'" + ch + "'", allKeyMaps(cm),
|
||||
function(b) { return doHandleBinding(cm, b, true); });
|
||||
if (handled) {
|
||||
e_preventDefault(e);
|
||||
restartBlink(cm);
|
||||
signalLater(cm, "keyHandled", cm, "'" + ch + "'", e);
|
||||
}
|
||||
return handled;
|
||||
return dispatchKey(cm, "'" + ch + "'", e,
|
||||
function(b) { return doHandleBinding(cm, b, true); });
|
||||
}
|
||||
|
||||
var lastStoppedKey = null;
|
||||
|
@ -3701,6 +3713,8 @@
|
|||
// If an editor sits on the top or bottom of the window, partially
|
||||
// scrolled out of view, this ensures that the cursor is visible.
|
||||
function maybeScrollWindow(cm, coords) {
|
||||
if (signalDOMEvent(cm, "scrollCursorIntoView")) return;
|
||||
|
||||
var display = cm.display, box = display.sizer.getBoundingClientRect(), doScroll = null;
|
||||
if (coords.top + box.top < 0) doScroll = true;
|
||||
else if (coords.bottom + box.top > (window.innerHeight || document.documentElement.clientHeight)) doScroll = false;
|
||||
|
@ -4024,12 +4038,12 @@
|
|||
getDoc: function() {return this.doc;},
|
||||
|
||||
addKeyMap: function(map, bottom) {
|
||||
this.state.keyMaps[bottom ? "push" : "unshift"](map);
|
||||
this.state.keyMaps[bottom ? "push" : "unshift"](getKeyMap(map));
|
||||
},
|
||||
removeKeyMap: function(map) {
|
||||
var maps = this.state.keyMaps;
|
||||
for (var i = 0; i < maps.length; ++i)
|
||||
if (maps[i] == map || (typeof maps[i] != "string" && maps[i].name == map)) {
|
||||
if (maps[i] == map || maps[i].name == map) {
|
||||
maps.splice(i, 1);
|
||||
return true;
|
||||
}
|
||||
|
@ -4086,20 +4100,11 @@
|
|||
// Fetch the parser token for a given character. Useful for hacks
|
||||
// that want to inspect the mode state (say, for completion).
|
||||
getTokenAt: function(pos, precise) {
|
||||
var doc = this.doc;
|
||||
pos = clipPos(doc, pos);
|
||||
var state = getStateBefore(this, pos.line, precise), mode = this.doc.mode;
|
||||
var line = getLine(doc, pos.line);
|
||||
var stream = new StringStream(line.text, this.options.tabSize);
|
||||
while (stream.pos < pos.ch && !stream.eol()) {
|
||||
stream.start = stream.pos;
|
||||
var style = readToken(mode, stream, state);
|
||||
}
|
||||
return {start: stream.start,
|
||||
end: stream.pos,
|
||||
string: stream.current(),
|
||||
type: style || null,
|
||||
state: state};
|
||||
return takeToken(this, pos, precise);
|
||||
},
|
||||
|
||||
getLineTokens: function(line, precise) {
|
||||
return takeToken(this, Pos(line), precise, true);
|
||||
},
|
||||
|
||||
getTokenTypeAt: function(pos) {
|
||||
|
@ -4502,7 +4507,12 @@
|
|||
themeChanged(cm);
|
||||
guttersChanged(cm);
|
||||
}, true);
|
||||
option("keyMap", "default", keyMapChanged);
|
||||
option("keyMap", "default", function(cm, val, old) {
|
||||
var next = getKeyMap(val);
|
||||
var prev = old != CodeMirror.Init && getKeyMap(old);
|
||||
if (prev && prev.detach) prev.detach(cm, next);
|
||||
if (next.attach) next.attach(cm, prev || null);
|
||||
});
|
||||
option("extraKeys", null);
|
||||
|
||||
option("lineWrapping", false, wrappingChanged, true);
|
||||
|
@ -4847,9 +4857,11 @@
|
|||
toggleOverwrite: function(cm) {cm.toggleOverwrite();}
|
||||
};
|
||||
|
||||
|
||||
// STANDARD KEYMAPS
|
||||
|
||||
var keyMap = CodeMirror.keyMap = {};
|
||||
|
||||
keyMap.basic = {
|
||||
"Left": "goCharLeft", "Right": "goCharRight", "Up": "goLineUp", "Down": "goLineDown",
|
||||
"End": "goLineEnd", "Home": "goLineStartSmart", "PageUp": "goPageUp", "PageDown": "goPageDown",
|
||||
|
@ -4871,6 +4883,13 @@
|
|||
"Ctrl-U": "undoSelection", "Shift-Ctrl-U": "redoSelection", "Alt-U": "redoSelection",
|
||||
fallthrough: "basic"
|
||||
};
|
||||
// Very basic readline/emacs-style bindings, which are standard on Mac.
|
||||
keyMap.emacsy = {
|
||||
"Ctrl-F": "goCharRight", "Ctrl-B": "goCharLeft", "Ctrl-P": "goLineUp", "Ctrl-N": "goLineDown",
|
||||
"Alt-F": "goWordRight", "Alt-B": "goWordLeft", "Ctrl-A": "goLineStart", "Ctrl-E": "goLineEnd",
|
||||
"Ctrl-V": "goPageDown", "Shift-Ctrl-V": "goPageUp", "Ctrl-D": "delCharAfter", "Ctrl-H": "delCharBefore",
|
||||
"Alt-D": "delWordAfter", "Alt-Backspace": "delWordBefore", "Ctrl-K": "killLine", "Ctrl-T": "transposeChars"
|
||||
};
|
||||
keyMap.macDefault = {
|
||||
"Cmd-A": "selectAll", "Cmd-D": "deleteLine", "Cmd-Z": "undo", "Shift-Cmd-Z": "redo", "Cmd-Y": "redo",
|
||||
"Cmd-Home": "goDocStart", "Cmd-Up": "goDocStart", "Cmd-End": "goDocEnd", "Cmd-Down": "goDocEnd", "Alt-Left": "goGroupLeft",
|
||||
|
@ -4881,70 +4900,100 @@
|
|||
"Cmd-U": "undoSelection", "Shift-Cmd-U": "redoSelection", "Ctrl-Up": "goDocStart", "Ctrl-Down": "goDocEnd",
|
||||
fallthrough: ["basic", "emacsy"]
|
||||
};
|
||||
// Very basic readline/emacs-style bindings, which are standard on Mac.
|
||||
keyMap.emacsy = {
|
||||
"Ctrl-F": "goCharRight", "Ctrl-B": "goCharLeft", "Ctrl-P": "goLineUp", "Ctrl-N": "goLineDown",
|
||||
"Alt-F": "goWordRight", "Alt-B": "goWordLeft", "Ctrl-A": "goLineStart", "Ctrl-E": "goLineEnd",
|
||||
"Ctrl-V": "goPageDown", "Shift-Ctrl-V": "goPageUp", "Ctrl-D": "delCharAfter", "Ctrl-H": "delCharBefore",
|
||||
"Alt-D": "delWordAfter", "Alt-Backspace": "delWordBefore", "Ctrl-K": "killLine", "Ctrl-T": "transposeChars"
|
||||
};
|
||||
keyMap["default"] = mac ? keyMap.macDefault : keyMap.pcDefault;
|
||||
|
||||
// KEYMAP DISPATCH
|
||||
|
||||
function getKeyMap(val) {
|
||||
if (typeof val == "string") return keyMap[val];
|
||||
else return val;
|
||||
function normalizeKeyName(name) {
|
||||
var parts = name.split(/-(?!$)/), name = parts[parts.length - 1];
|
||||
var alt, ctrl, shift, cmd;
|
||||
for (var i = 0; i < parts.length - 1; i++) {
|
||||
var mod = parts[i];
|
||||
if (/^(cmd|meta|m)$/i.test(mod)) cmd = true;
|
||||
else if (/^a(lt)?$/i.test(mod)) alt = true;
|
||||
else if (/^(c|ctrl|control)$/i.test(mod)) ctrl = true;
|
||||
else if (/^s(hift)$/i.test(mod)) shift = true;
|
||||
else throw new Error("Unrecognized modifier name: " + mod);
|
||||
}
|
||||
if (alt) name = "Alt-" + name;
|
||||
if (ctrl) name = "Ctrl-" + name;
|
||||
if (cmd) name = "Cmd-" + name;
|
||||
if (shift) name = "Shift-" + name;
|
||||
return name;
|
||||
}
|
||||
|
||||
// Given an array of keymaps and a key name, call handle on any
|
||||
// bindings found, until that returns a truthy value, at which point
|
||||
// we consider the key handled. Implements things like binding a key
|
||||
// to false stopping further handling and keymap fallthrough.
|
||||
var lookupKey = CodeMirror.lookupKey = function(name, maps, handle) {
|
||||
function lookup(map) {
|
||||
map = getKeyMap(map);
|
||||
var found = map[name];
|
||||
if (found === false) return "stop";
|
||||
if (found != null && handle(found)) return true;
|
||||
if (map.nofallthrough) return "stop";
|
||||
// This is a kludge to keep keymaps mostly working as raw objects
|
||||
// (backwards compatibility) while at the same time support features
|
||||
// like normalization and multi-stroke key bindings. It compiles a
|
||||
// new normalized keymap, and then updates the old object to reflect
|
||||
// this.
|
||||
CodeMirror.normalizeKeyMap = function(keymap) {
|
||||
var copy = {};
|
||||
for (var keyname in keymap) if (keymap.hasOwnProperty(keyname)) {
|
||||
var value = keymap[keyname];
|
||||
if (/^(name|fallthrough|(de|at)tach)$/.test(keyname)) continue;
|
||||
if (value == "...") { delete keymap[keyname]; continue; }
|
||||
|
||||
var fallthrough = map.fallthrough;
|
||||
if (fallthrough == null) return false;
|
||||
if (Object.prototype.toString.call(fallthrough) != "[object Array]")
|
||||
return lookup(fallthrough);
|
||||
for (var i = 0; i < fallthrough.length; ++i) {
|
||||
var done = lookup(fallthrough[i]);
|
||||
if (done) return done;
|
||||
var keys = map(keyname.split(" "), normalizeKeyName);
|
||||
for (var i = 0; i < keys.length; i++) {
|
||||
var val, name;
|
||||
if (i == keys.length - 1) {
|
||||
name = keyname;
|
||||
val = value;
|
||||
} else {
|
||||
name = keys.slice(0, i + 1).join(" ");
|
||||
val = "...";
|
||||
}
|
||||
var prev = copy[name];
|
||||
if (!prev) copy[name] = val;
|
||||
else if (prev != val) throw new Error("Inconsistent bindings for " + name);
|
||||
}
|
||||
return false;
|
||||
delete keymap[keyname];
|
||||
}
|
||||
for (var prop in copy) keymap[prop] = copy[prop];
|
||||
return keymap;
|
||||
};
|
||||
|
||||
for (var i = 0; i < maps.length; ++i) {
|
||||
var done = lookup(maps[i]);
|
||||
if (done) return done != "stop";
|
||||
var lookupKey = CodeMirror.lookupKey = function(key, map, handle) {
|
||||
map = getKeyMap(map);
|
||||
var found = map.call ? map.call(key) : map[key];
|
||||
if (found === false) return "nothing";
|
||||
if (found === "...") return "multi";
|
||||
if (found != null && handle(found)) return "handled";
|
||||
|
||||
if (map.fallthrough) {
|
||||
if (Object.prototype.toString.call(map.fallthrough) != "[object Array]")
|
||||
return lookupKey(key, map.fallthrough, handle);
|
||||
for (var i = 0; i < map.fallthrough.length; i++) {
|
||||
var result = lookupKey(key, map.fallthrough[i], handle);
|
||||
if (result) return result;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Modifier key presses don't count as 'real' key presses for the
|
||||
// purpose of keymap fallthrough.
|
||||
var isModifierKey = CodeMirror.isModifierKey = function(event) {
|
||||
var name = keyNames[event.keyCode];
|
||||
var isModifierKey = CodeMirror.isModifierKey = function(value) {
|
||||
var name = typeof value == "string" ? value : keyNames[value.keyCode];
|
||||
return name == "Ctrl" || name == "Alt" || name == "Shift" || name == "Mod";
|
||||
};
|
||||
|
||||
// Look up the name of a key as indicated by an event object.
|
||||
var keyName = CodeMirror.keyName = function(event, noShift) {
|
||||
if (presto && event.keyCode == 34 && event["char"]) return false;
|
||||
var name = keyNames[event.keyCode];
|
||||
var base = keyNames[event.keyCode], name = base;
|
||||
if (name == null || event.altGraphKey) return false;
|
||||
if (event.altKey) name = "Alt-" + name;
|
||||
if (flipCtrlCmd ? event.metaKey : event.ctrlKey) name = "Ctrl-" + name;
|
||||
if (flipCtrlCmd ? event.ctrlKey : event.metaKey) name = "Cmd-" + name;
|
||||
if (!noShift && event.shiftKey) name = "Shift-" + name;
|
||||
if (event.altKey && base != "Alt") name = "Alt-" + name;
|
||||
if ((flipCtrlCmd ? event.metaKey : event.ctrlKey) && base != "Ctrl") name = "Ctrl-" + name;
|
||||
if ((flipCtrlCmd ? event.ctrlKey : event.metaKey) && base != "Cmd") name = "Cmd-" + name;
|
||||
if (!noShift && event.shiftKey && base != "Shift") name = "Shift-" + name;
|
||||
return name;
|
||||
};
|
||||
|
||||
function getKeyMap(val) {
|
||||
return typeof val == "string" ? keyMap[val] : val;
|
||||
}
|
||||
|
||||
// FROMTEXTAREA
|
||||
|
||||
CodeMirror.fromTextArea = function(textarea, options) {
|
||||
|
@ -5794,20 +5843,44 @@
|
|||
if (inner.mode.blankLine) return inner.mode.blankLine(inner.state);
|
||||
}
|
||||
|
||||
function readToken(mode, stream, state) {
|
||||
function readToken(mode, stream, state, inner) {
|
||||
for (var i = 0; i < 10; i++) {
|
||||
if (inner) inner[0] = CodeMirror.innerMode(mode, state).mode;
|
||||
var style = mode.token(stream, state);
|
||||
if (stream.pos > stream.start) return style;
|
||||
}
|
||||
throw new Error("Mode " + mode.name + " failed to advance stream.");
|
||||
}
|
||||
|
||||
// Utility for getTokenAt and getLineTokens
|
||||
function takeToken(cm, pos, precise, asArray) {
|
||||
function getObj(copy) {
|
||||
return {start: stream.start, end: stream.pos,
|
||||
string: stream.current(),
|
||||
type: style || null,
|
||||
state: copy ? copyState(doc.mode, state) : state};
|
||||
}
|
||||
|
||||
var doc = cm.doc, mode = doc.mode, style;
|
||||
pos = clipPos(doc, pos);
|
||||
var line = getLine(doc, pos.line), state = getStateBefore(cm, pos.line, precise);
|
||||
var stream = new StringStream(line.text, cm.options.tabSize), tokens;
|
||||
if (asArray) tokens = [];
|
||||
while ((asArray || stream.pos < pos.ch) && !stream.eol()) {
|
||||
stream.start = stream.pos;
|
||||
style = readToken(mode, stream, state);
|
||||
if (asArray) tokens.push(getObj(true));
|
||||
}
|
||||
return asArray ? tokens : getObj();
|
||||
}
|
||||
|
||||
// Run the given mode's parser over a line, calling f for each token.
|
||||
function runMode(cm, text, mode, state, f, lineClasses, forceToEnd) {
|
||||
var flattenSpans = mode.flattenSpans;
|
||||
if (flattenSpans == null) flattenSpans = cm.options.flattenSpans;
|
||||
var curStart = 0, curStyle = null;
|
||||
var stream = new StringStream(text, cm.options.tabSize), style;
|
||||
var inner = cm.options.addModeClass && [null];
|
||||
if (text == "") extractLineClasses(callBlankLine(mode, state), lineClasses);
|
||||
while (!stream.eol()) {
|
||||
if (stream.pos > cm.options.maxHighlightLength) {
|
||||
|
@ -5816,10 +5889,10 @@
|
|||
stream.pos = text.length;
|
||||
style = null;
|
||||
} else {
|
||||
style = extractLineClasses(readToken(mode, stream, state), lineClasses);
|
||||
style = extractLineClasses(readToken(mode, stream, state, inner), lineClasses);
|
||||
}
|
||||
if (cm.options.addModeClass) {
|
||||
var mName = CodeMirror.innerMode(mode, state).mode.name;
|
||||
if (inner) {
|
||||
var mName = inner[0].name;
|
||||
if (mName) style = "m-" + (style ? mName + " " + style : mName);
|
||||
}
|
||||
if (!flattenSpans || curStyle != style) {
|
||||
|
@ -5878,12 +5951,13 @@
|
|||
return {styles: st, classes: lineClasses.bgClass || lineClasses.textClass ? lineClasses : null};
|
||||
}
|
||||
|
||||
function getLineStyles(cm, line) {
|
||||
function getLineStyles(cm, line, updateFrontier) {
|
||||
if (!line.styles || line.styles[0] != cm.state.modeGen) {
|
||||
var result = highlightLine(cm, line, line.stateAfter = getStateBefore(cm, lineNo(line)));
|
||||
line.styles = result.styles;
|
||||
if (result.classes) line.styleClasses = result.classes;
|
||||
else if (line.styleClasses) line.styleClasses = null;
|
||||
if (updateFrontier === cm.doc.frontier) cm.doc.frontier++;
|
||||
}
|
||||
return line.styles;
|
||||
}
|
||||
|
@ -5938,7 +6012,8 @@
|
|||
if (hasBadBidiRects(cm.display.measure) && (order = getOrder(line)))
|
||||
builder.addToken = buildTokenBadBidi(builder.addToken, order);
|
||||
builder.map = [];
|
||||
insertLineContent(line, builder, getLineStyles(cm, line));
|
||||
var allowFrontierUpdate = lineView != cm.display.externalMeasured && lineNo(line);
|
||||
insertLineContent(line, builder, getLineStyles(cm, line, allowFrontierUpdate));
|
||||
if (line.styleClasses) {
|
||||
if (line.styleClasses.bgClass)
|
||||
builder.bgClass = joinClasses(line.styleClasses.bgClass, builder.bgClass || "");
|
||||
|
@ -5960,9 +6035,14 @@
|
|||
}
|
||||
}
|
||||
|
||||
// See issue #2901
|
||||
if (webkit && /\bcm-tab\b/.test(builder.content.lastChild.className))
|
||||
builder.content.className = "cm-tab-wrap-hack";
|
||||
|
||||
signal(cm, "renderLine", cm, lineView.line, builder.pre);
|
||||
if (builder.pre.className)
|
||||
builder.textClass = joinClasses(builder.pre.className, builder.textClass || "");
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
|
@ -6531,22 +6611,26 @@
|
|||
},
|
||||
|
||||
addLineClass: docMethodOp(function(handle, where, cls) {
|
||||
return changeLine(this, handle, "class", function(line) {
|
||||
var prop = where == "text" ? "textClass" : where == "background" ? "bgClass" : "wrapClass";
|
||||
return changeLine(this, handle, where == "gutter" ? "gutter" : "class", function(line) {
|
||||
var prop = where == "text" ? "textClass"
|
||||
: where == "background" ? "bgClass"
|
||||
: where == "gutter" ? "gutterClass" : "wrapClass";
|
||||
if (!line[prop]) line[prop] = cls;
|
||||
else if (new RegExp("(?:^|\\s)" + cls + "(?:$|\\s)").test(line[prop])) return false;
|
||||
else if (classTest(cls).test(line[prop])) return false;
|
||||
else line[prop] += " " + cls;
|
||||
return true;
|
||||
});
|
||||
}),
|
||||
removeLineClass: docMethodOp(function(handle, where, cls) {
|
||||
return changeLine(this, handle, "class", function(line) {
|
||||
var prop = where == "text" ? "textClass" : where == "background" ? "bgClass" : "wrapClass";
|
||||
var prop = where == "text" ? "textClass"
|
||||
: where == "background" ? "bgClass"
|
||||
: where == "gutter" ? "gutterClass" : "wrapClass";
|
||||
var cur = line[prop];
|
||||
if (!cur) return false;
|
||||
else if (cls == null) line[prop] = null;
|
||||
else {
|
||||
var found = cur.match(new RegExp("(?:^|\\s+)" + cls + "(?:$|\\s+)"));
|
||||
var found = cur.match(classTest(cls));
|
||||
if (!found) return false;
|
||||
var end = found.index + found[0].length;
|
||||
line[prop] = cur.slice(0, found.index) + (!found.index || end == cur.length ? "" : " ") + cur.slice(end) || null;
|
||||
|
@ -7165,6 +7249,8 @@
|
|||
// registering a (non-DOM) handler on the editor for the event name,
|
||||
// and preventDefault-ing the event in that handler.
|
||||
function signalDOMEvent(cm, e, override) {
|
||||
if (typeof e == "string")
|
||||
e = {type: e, preventDefault: function() { this.defaultPrevented = true; }};
|
||||
signal(cm, override || e.type, cm, e);
|
||||
return e_defaultPrevented(e) || e.codemirrorIgnore;
|
||||
}
|
||||
|
@ -7338,7 +7424,8 @@
|
|||
};
|
||||
else range = function(node, start, end) {
|
||||
var r = document.body.createTextRange();
|
||||
r.moveToElementText(node.parentNode);
|
||||
try { r.moveToElementText(node.parentNode); }
|
||||
catch(e) { return r; }
|
||||
r.collapse(true);
|
||||
r.moveEnd("character", end);
|
||||
r.moveStart("character", start);
|
||||
|
@ -7370,14 +7457,19 @@
|
|||
catch(e) { return document.body; }
|
||||
};
|
||||
|
||||
function classTest(cls) { return new RegExp("\\b" + cls + "\\b\\s*"); }
|
||||
function rmClass(node, cls) {
|
||||
var test = classTest(cls);
|
||||
if (test.test(node.className)) node.className = node.className.replace(test, "");
|
||||
}
|
||||
function addClass(node, cls) {
|
||||
if (!classTest(cls).test(node.className)) node.className += " " + cls;
|
||||
}
|
||||
function classTest(cls) { return new RegExp("(^|\\s)" + cls + "(?:$|\\s)\\s*"); }
|
||||
var rmClass = CodeMirror.rmClass = function(node, cls) {
|
||||
var current = node.className;
|
||||
var match = classTest(cls).exec(current);
|
||||
if (match) {
|
||||
var after = current.slice(match.index + match[0].length);
|
||||
node.className = current.slice(0, match.index) + (after ? match[1] + after : "");
|
||||
}
|
||||
};
|
||||
var addClass = CodeMirror.addClass = function(node, cls) {
|
||||
var current = node.className;
|
||||
if (!classTest(cls).test(current)) node.className += (current ? " " : "") + cls;
|
||||
};
|
||||
function joinClasses(a, b) {
|
||||
var as = a.split(" ");
|
||||
for (var i = 0; i < as.length; i++)
|
||||
|
@ -7824,7 +7916,7 @@
|
|||
|
||||
// THE END
|
||||
|
||||
CodeMirror.version = "4.7.0";
|
||||
CodeMirror.version = "4.8.0";
|
||||
|
||||
return CodeMirror;
|
||||
});
|
|
@ -256,7 +256,7 @@
|
|||
|
||||
// Actual keymap
|
||||
|
||||
var keyMap = CodeMirror.keyMap.emacs = {
|
||||
var keyMap = CodeMirror.keyMap.emacs = CodeMirror.normalizeKeyMap({
|
||||
"Ctrl-W": function(cm) {kill(cm, cm.getCursor("start"), cm.getCursor("end"));},
|
||||
"Ctrl-K": repeated(function(cm) {
|
||||
var start = cm.getCursor(), end = cm.clipPos(Pos(start.line));
|
||||
|
@ -353,27 +353,7 @@
|
|||
"Alt-/": "autocomplete",
|
||||
"Ctrl-J": "newlineAndIndent", "Enter": false, "Tab": "indentAuto",
|
||||
|
||||
"Alt-G": function(cm) {cm.setOption("keyMap", "emacs-Alt-G");},
|
||||
"Ctrl-X": function(cm) {cm.setOption("keyMap", "emacs-Ctrl-X");},
|
||||
"Ctrl-Q": function(cm) {cm.setOption("keyMap", "emacs-Ctrl-Q");},
|
||||
"Ctrl-U": addPrefixMap
|
||||
};
|
||||
|
||||
CodeMirror.keyMap["emacs-Ctrl-X"] = {
|
||||
"Tab": function(cm) {
|
||||
cm.indentSelection(getPrefix(cm, true) || cm.getOption("indentUnit"));
|
||||
},
|
||||
"Ctrl-X": function(cm) {
|
||||
cm.setSelection(cm.getCursor("head"), cm.getCursor("anchor"));
|
||||
},
|
||||
|
||||
"Ctrl-S": "save", "Ctrl-W": "save", "S": "saveAll", "F": "open", "U": repeated("undo"), "K": "close",
|
||||
"Delete": function(cm) { kill(cm, cm.getCursor(), bySentence(cm, cm.getCursor(), 1), true); },
|
||||
auto: "emacs", nofallthrough: true, disableInput: true
|
||||
};
|
||||
|
||||
CodeMirror.keyMap["emacs-Alt-G"] = {
|
||||
"G": function(cm) {
|
||||
"Alt-G G": function(cm) {
|
||||
var prefix = getPrefix(cm, true);
|
||||
if (prefix != null && prefix > 0) return cm.setCursor(prefix - 1);
|
||||
|
||||
|
@ -383,13 +363,24 @@
|
|||
cm.setCursor(num - 1);
|
||||
});
|
||||
},
|
||||
auto: "emacs", nofallthrough: true, disableInput: true
|
||||
};
|
||||
|
||||
CodeMirror.keyMap["emacs-Ctrl-Q"] = {
|
||||
"Tab": repeated("insertTab"),
|
||||
auto: "emacs", nofallthrough: true
|
||||
};
|
||||
"Ctrl-X Tab": function(cm) {
|
||||
cm.indentSelection(getPrefix(cm, true) || cm.getOption("indentUnit"));
|
||||
},
|
||||
"Ctrl-X Ctrl-X": function(cm) {
|
||||
cm.setSelection(cm.getCursor("head"), cm.getCursor("anchor"));
|
||||
},
|
||||
"Ctrl-X Ctrl-S": "save",
|
||||
"Ctrl-X Ctrl-W": "save",
|
||||
"Ctrl-X S": "saveAll",
|
||||
"Ctrl-X F": "open",
|
||||
"Ctrl-X U": repeated("undo"),
|
||||
"Ctrl-X K": "close",
|
||||
"Ctrl-X Delete": function(cm) { kill(cm, cm.getCursor(), bySentence(cm, cm.getCursor(), 1), true); },
|
||||
|
||||
"Ctrl-Q Tab": repeated("insertTab"),
|
||||
"Ctrl-U": addPrefixMap
|
||||
});
|
||||
|
||||
var prefixMap = {"Ctrl-G": clearPrefix};
|
||||
function regPrefix(d) {
|
|
@ -386,9 +386,7 @@
|
|||
|
||||
map["Alt-Q"] = "wrapLines";
|
||||
|
||||
var mapK = CodeMirror.keyMap["sublime-Ctrl-K"] = {auto: "sublime", nofallthrough: true};
|
||||
|
||||
map[ctrl + "K"] = function(cm) {cm.setOption("keyMap", "sublime-Ctrl-K");};
|
||||
var cK = ctrl + "K ";
|
||||
|
||||
function modifyWordOrSelection(cm, mod) {
|
||||
cm.operation(function() {
|
||||
|
@ -409,9 +407,9 @@
|
|||
});
|
||||
}
|
||||
|
||||
mapK[ctrl + "Backspace"] = "delLineLeft";
|
||||
map[cK + ctrl + "Backspace"] = "delLineLeft";
|
||||
|
||||
cmds[mapK[ctrl + "K"] = "delLineRight"] = function(cm) {
|
||||
cmds[map[cK + ctrl + "K"] = "delLineRight"] = function(cm) {
|
||||
cm.operation(function() {
|
||||
var ranges = cm.listSelections();
|
||||
for (var i = ranges.length - 1; i >= 0; i--)
|
||||
|
@ -420,22 +418,22 @@
|
|||
});
|
||||
};
|
||||
|
||||
cmds[mapK[ctrl + "U"] = "upcaseAtCursor"] = function(cm) {
|
||||
cmds[map[cK + ctrl + "U"] = "upcaseAtCursor"] = function(cm) {
|
||||
modifyWordOrSelection(cm, function(str) { return str.toUpperCase(); });
|
||||
};
|
||||
cmds[mapK[ctrl + "L"] = "downcaseAtCursor"] = function(cm) {
|
||||
cmds[map[cK + ctrl + "L"] = "downcaseAtCursor"] = function(cm) {
|
||||
modifyWordOrSelection(cm, function(str) { return str.toLowerCase(); });
|
||||
};
|
||||
|
||||
cmds[mapK[ctrl + "Space"] = "setSublimeMark"] = function(cm) {
|
||||
cmds[map[cK + ctrl + "Space"] = "setSublimeMark"] = function(cm) {
|
||||
if (cm.state.sublimeMark) cm.state.sublimeMark.clear();
|
||||
cm.state.sublimeMark = cm.setBookmark(cm.getCursor());
|
||||
};
|
||||
cmds[mapK[ctrl + "A"] = "selectToSublimeMark"] = function(cm) {
|
||||
cmds[map[cK + ctrl + "A"] = "selectToSublimeMark"] = function(cm) {
|
||||
var found = cm.state.sublimeMark && cm.state.sublimeMark.find();
|
||||
if (found) cm.setSelection(cm.getCursor(), found);
|
||||
};
|
||||
cmds[mapK[ctrl + "W"] = "deleteToSublimeMark"] = function(cm) {
|
||||
cmds[map[cK + ctrl + "W"] = "deleteToSublimeMark"] = function(cm) {
|
||||
var found = cm.state.sublimeMark && cm.state.sublimeMark.find();
|
||||
if (found) {
|
||||
var from = cm.getCursor(), to = found;
|
||||
|
@ -444,7 +442,7 @@
|
|||
cm.replaceRange("", from, to);
|
||||
}
|
||||
};
|
||||
cmds[mapK[ctrl + "X"] = "swapWithSublimeMark"] = function(cm) {
|
||||
cmds[map[cK + ctrl + "X"] = "swapWithSublimeMark"] = function(cm) {
|
||||
var found = cm.state.sublimeMark && cm.state.sublimeMark.find();
|
||||
if (found) {
|
||||
cm.state.sublimeMark.clear();
|
||||
|
@ -452,13 +450,13 @@
|
|||
cm.setCursor(found);
|
||||
}
|
||||
};
|
||||
cmds[mapK[ctrl + "Y"] = "sublimeYank"] = function(cm) {
|
||||
cmds[map[cK + ctrl + "Y"] = "sublimeYank"] = function(cm) {
|
||||
if (cm.state.sublimeKilled != null)
|
||||
cm.replaceSelection(cm.state.sublimeKilled, null, "paste");
|
||||
};
|
||||
|
||||
mapK[ctrl + "G"] = "clearBookmarks";
|
||||
cmds[mapK[ctrl + "C"] = "showInCenter"] = function(cm) {
|
||||
map[cK + ctrl + "G"] = "clearBookmarks";
|
||||
cmds[map[cK + ctrl + "C"] = "showInCenter"] = function(cm) {
|
||||
var pos = cm.cursorCoords(null, "local");
|
||||
cm.scrollTo(null, (pos.top + pos.bottom) / 2 - cm.getScrollInfo().clientHeight / 2);
|
||||
};
|
||||
|
@ -530,7 +528,7 @@
|
|||
|
||||
map["Shift-" + ctrl + "["] = "fold";
|
||||
map["Shift-" + ctrl + "]"] = "unfold";
|
||||
mapK[ctrl + "0"] = mapK[ctrl + "j"] = "unfoldAll";
|
||||
map[cK + ctrl + "0"] = map[cK + ctrl + "j"] = "unfoldAll";
|
||||
|
||||
map[ctrl + "I"] = "findIncremental";
|
||||
map["Shift-" + ctrl + "I"] = "findIncrementalReverse";
|
||||
|
@ -538,4 +536,5 @@
|
|||
map["F3"] = "findNext";
|
||||
map["Shift-F3"] = "findPrev";
|
||||
|
||||
CodeMirror.normalizeKeyMap(map);
|
||||
});
|
File diff suppressed because it is too large
Load Diff
|
@ -471,4 +471,19 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
|
|||
modeProps: {fold: ["brace", "include"]}
|
||||
});
|
||||
|
||||
def("text/x-objectivec", {
|
||||
name: "clike",
|
||||
keywords: words(cKeywords + "inline restrict _Bool _Complex _Imaginery BOOL Class bycopy byref id IMP in " +
|
||||
"inout nil oneway out Protocol SEL self super atomic nonatomic retain copy readwrite readonly"),
|
||||
atoms: words("YES NO NULL NILL ON OFF"),
|
||||
hooks: {
|
||||
"@": function(stream) {
|
||||
stream.eatWhile(/[\w\$]/);
|
||||
return "keyword";
|
||||
},
|
||||
"#": cppHook
|
||||
},
|
||||
modeProps: {fold: "brace"}
|
||||
});
|
||||
|
||||
});
|
|
@ -139,6 +139,26 @@ void Class::Method2(MyType<T, V>* value) {
|
|||
}
|
||||
</textarea></div>
|
||||
|
||||
<h2>Objective-C example</h2>
|
||||
|
||||
<div><textarea id="objectivec-code">
|
||||
/*
|
||||
This is a longer comment
|
||||
That spans two lines
|
||||
*/
|
||||
|
||||
#import <Test/Test.h>
|
||||
@implementation YourAppDelegate
|
||||
|
||||
// This is a one-line comment
|
||||
|
||||
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
|
||||
char myString[] = "This is a C character array";
|
||||
int test = 5;
|
||||
return YES;
|
||||
}
|
||||
</textarea></div>
|
||||
|
||||
<h2>Java example</h2>
|
||||
|
||||
<div><textarea id="java-code">
|
||||
|
@ -202,6 +222,11 @@ object FilterTest extends App {
|
|||
matchBrackets: true,
|
||||
mode: "text/x-java"
|
||||
});
|
||||
var objectivecEditor = CodeMirror.fromTextArea(document.getElementById("objectivec-code"), {
|
||||
lineNumbers: true,
|
||||
matchBrackets: true,
|
||||
mode: "text/x-objectivec"
|
||||
});
|
||||
var scalaEditor = CodeMirror.fromTextArea(document.getElementById("scala-code"), {
|
||||
lineNumbers: true,
|
||||
matchBrackets: true,
|
||||
|
@ -220,6 +245,7 @@ object FilterTest extends App {
|
|||
<p><strong>MIME types defined:</strong> <code>text/x-csrc</code>
|
||||
(C), <code>text/x-c++src</code> (C++), <code>text/x-java</code>
|
||||
(Java), <code>text/x-csharp</code> (C#),
|
||||
<code>text/x-objectivec</code> (Objective-C),
|
||||
<code>text/x-scala</code> (Scala), <code>text/x-vertex</code>
|
||||
and <code>x-shader/x-fragment</code> (shader programs).</p>
|
||||
</article>
|
|
@ -182,7 +182,7 @@ CodeMirror.defineMode("css", function(config, parserConfig) {
|
|||
override = "string-2";
|
||||
return "maybeprop";
|
||||
} else if (allowNested) {
|
||||
override = stream.match(/^\s*:/, false) ? "property" : "tag";
|
||||
override = stream.match(/^\s*:(?:\s|$)/, false) ? "property" : "tag";
|
||||
return "block";
|
||||
} else {
|
||||
override += " error";
|
|
@ -0,0 +1,80 @@
|
|||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
||||
|
||||
(function(mod) {
|
||||
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
||||
mod(require("../../lib/codemirror"), require("../../addon/mode/simple"));
|
||||
else if (typeof define == "function" && define.amd) // AMD
|
||||
define(["../../lib/codemirror", "../../addon/mode/simple"], mod);
|
||||
else // Plain browser env
|
||||
mod(CodeMirror);
|
||||
})(function(CodeMirror) {
|
||||
"use strict";
|
||||
|
||||
// Collect all Dockerfile directives
|
||||
var instructions = ["from", "maintainer", "run", "cmd", "expose", "env",
|
||||
"add", "copy", "entrypoint", "volume", "user",
|
||||
"workdir", "onbuild"],
|
||||
instructionRegex = "(" + instructions.join('|') + ")",
|
||||
instructionOnlyLine = new RegExp(instructionRegex + "\\s*$", "i"),
|
||||
instructionWithArguments = new RegExp(instructionRegex + "(\\s+)", "i");
|
||||
|
||||
CodeMirror.defineSimpleMode("dockerfile", {
|
||||
start: [
|
||||
// Block comment: This is a line starting with a comment
|
||||
{
|
||||
regex: /#.*$/,
|
||||
token: "comment",
|
||||
next: "start"
|
||||
},
|
||||
// Highlight an instruction without any arguments (for convenience)
|
||||
{
|
||||
regex: instructionOnlyLine,
|
||||
token: "variable-2",
|
||||
next: "start"
|
||||
},
|
||||
// Highlight an instruction followed by arguments
|
||||
{
|
||||
regex: instructionWithArguments,
|
||||
token: ["variable-2", null],
|
||||
next: "arguments"
|
||||
},
|
||||
// Fail-safe return to start
|
||||
{
|
||||
token: null,
|
||||
next: "start"
|
||||
}
|
||||
],
|
||||
arguments: [
|
||||
{
|
||||
// Line comment without instruction arguments is an error
|
||||
regex: /#.*$/,
|
||||
token: "error",
|
||||
next: "start"
|
||||
},
|
||||
{
|
||||
regex: /[^#]+\\$/,
|
||||
token: null,
|
||||
next: "arguments"
|
||||
},
|
||||
{
|
||||
// Match everything except for the inline comment
|
||||
regex: /[^#]+/,
|
||||
token: null,
|
||||
next: "start"
|
||||
},
|
||||
{
|
||||
regex: /$/,
|
||||
token: null,
|
||||
next: "start"
|
||||
},
|
||||
// Fail safe return to start
|
||||
{
|
||||
token: null,
|
||||
next: "start"
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
CodeMirror.defineMIME("text/x-dockerfile", "dockerfile");
|
||||
});
|
|
@ -0,0 +1,72 @@
|
|||
<!doctype html>
|
||||
|
||||
<title>CodeMirror: Dockerfile mode</title>
|
||||
<meta charset="utf-8"/>
|
||||
<link rel=stylesheet href="../../doc/docs.css">
|
||||
|
||||
<link rel="stylesheet" href="../../lib/codemirror.css">
|
||||
<script src="../../lib/codemirror.js"></script>
|
||||
<script src="../../addon/mode/simple.js"></script>
|
||||
<script src="dockerfile.js"></script>
|
||||
<style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
|
||||
<div id=nav>
|
||||
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
|
||||
|
||||
<ul>
|
||||
<li><a href="../../index.html">Home</a>
|
||||
<li><a href="../../doc/manual.html">Manual</a>
|
||||
<li><a href="https://github.com/codemirror/codemirror">Code</a>
|
||||
</ul>
|
||||
<ul>
|
||||
<li><a href="../index.html">Language modes</a>
|
||||
<li><a class=active href="#">Dockerfile</a>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<article>
|
||||
<h2>Dockerfile mode</h2>
|
||||
<form><textarea id="code" name="code"># Install Ghost blogging platform and run development environment
|
||||
#
|
||||
# VERSION 1.0.0
|
||||
|
||||
FROM ubuntu:12.10
|
||||
MAINTAINER Amer Grgic "amer@livebyt.es"
|
||||
WORKDIR /data/ghost
|
||||
|
||||
# Install dependencies for nginx installation
|
||||
RUN apt-get update
|
||||
RUN apt-get install -y python g++ make software-properties-common --force-yes
|
||||
RUN add-apt-repository ppa:chris-lea/node.js
|
||||
RUN apt-get update
|
||||
# Install unzip
|
||||
RUN apt-get install -y unzip
|
||||
# Install curl
|
||||
RUN apt-get install -y curl
|
||||
# Install nodejs & npm
|
||||
RUN apt-get install -y rlwrap
|
||||
RUN apt-get install -y nodejs
|
||||
# Download Ghost v0.4.1
|
||||
RUN curl -L https://ghost.org/zip/ghost-latest.zip -o /tmp/ghost.zip
|
||||
# Unzip Ghost zip to /data/ghost
|
||||
RUN unzip -uo /tmp/ghost.zip -d /data/ghost
|
||||
# Add custom config js to /data/ghost
|
||||
ADD ./config.example.js /data/ghost/config.js
|
||||
# Install Ghost with NPM
|
||||
RUN cd /data/ghost/ && npm install --production
|
||||
# Expose port 2368
|
||||
EXPOSE 2368
|
||||
# Run Ghost
|
||||
CMD ["npm","start"]
|
||||
</textarea></form>
|
||||
|
||||
<script>
|
||||
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
|
||||
lineNumbers: true,
|
||||
mode: "dockerfile"
|
||||
});
|
||||
</script>
|
||||
|
||||
<p>Dockerfile syntac highlighting for CodeMirror.</p>
|
||||
|
||||
<p><strong>MIME types defined:</strong> <code>text/x-dockerfile</code></p>
|
||||
</article>
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue