多项UI组件升级到最新版本

pull/8/MERGE
xuxueli 6 years ago
parent 25f5ac3eee
commit 5048011fa7

@ -1343,7 +1343,7 @@ Tips: 历史版本(V1.3.x)目前已经Release至稳定版本, 进入维护阶段
- 10、命令行任务原生提供通用命令行任务HandlerBean任务"CommandJobHandler");业务方只需要提供命令行即可; - 10、命令行任务原生提供通用命令行任务HandlerBean任务"CommandJobHandler");业务方只需要提供命令行即可;
- 11、项目依赖升级 groovy 至较新稳定版本pom清理 - 11、项目依赖升级 groovy 至较新稳定版本pom清理
- 12、子任务失败重试重试逻辑优化子任务失败时将会按照其预设的失败重试次数主动进行重试 - 12、子任务失败重试重试逻辑优化子任务失败时将会按照其预设的失败重试次数主动进行重试
- 13、多项UI组件升级到最新版本layer/pace/jquery.validate - 13、多项UI组件升级到最新版本layer/pace/jquery.validate/echarts/CodeMirror
- 14、[迭代中]docker镜像并且推送docker镜像到中央仓库更进一步实现产品开箱即用 - 14、[迭代中]docker镜像并且推送docker镜像到中央仓库更进一步实现产品开箱即用
@ -1366,7 +1366,7 @@ Tips: 历史版本(V1.3.x)目前已经Release至稳定版本, 进入维护阶段
- 16、Cron TimeZone 自定义; - 16、Cron TimeZone 自定义;
- 17、忙碌转移优化全部机器忙碌时不再直接失败 - 17、忙碌转移优化全部机器忙碌时不再直接失败
- 18、流程任务等透传动态参数 - 18、流程任务等透传动态参数
- 19、任务支持切换执行器 - 19、任务支持切换执行器quartz job group固定
- 20、任务自动注册待考虑因为任务自动注册将会导致任务难以管理控制 - 20、任务自动注册待考虑因为任务自动注册将会导致任务难以管理控制
- 21、批量触发支持添加参数 "org.quartz.scheduler.batchTriggerAcquisitionMaxCount: 50" - 21、批量触发支持添加参数 "org.quartz.scheduler.batchTriggerAcquisitionMaxCount: 50"
- 22、失败重试间隔 - 22、失败重试间隔

@ -1,5 +1,5 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others // CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE // Distributed under an MIT license: https://codemirror.net/LICENSE
(function(mod) { (function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS if (typeof exports == "object" && typeof module == "object") // CommonJS

@ -25,8 +25,6 @@
margin: 0; margin: 0;
padding: 0 4px; padding: 0 4px;
border-radius: 2px; border-radius: 2px;
max-width: 19em;
overflow: hidden;
white-space: pre; white-space: pre;
color: black; color: black;
cursor: pointer; cursor: pointer;

@ -1,5 +1,5 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others // CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE // Distributed under an MIT license: https://codemirror.net/LICENSE
(function(mod) { (function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS if (typeof exports == "object" && typeof module == "object") // CommonJS
@ -98,7 +98,7 @@
var pos = this.cm.getCursor(), line = this.cm.getLine(pos.line); var pos = this.cm.getCursor(), line = this.cm.getLine(pos.line);
if (pos.line != this.startPos.line || line.length - pos.ch != this.startLen - this.startPos.ch || if (pos.line != this.startPos.line || line.length - pos.ch != this.startLen - this.startPos.ch ||
pos.ch < this.startPos.ch || this.cm.somethingSelected() || pos.ch < this.startPos.ch || this.cm.somethingSelected() ||
(pos.ch && this.options.closeCharacters.test(line.charAt(pos.ch - 1)))) { (!pos.ch || this.options.closeCharacters.test(line.charAt(pos.ch - 1)))) {
this.close(); this.close();
} else { } else {
var self = this; var self = this;
@ -108,15 +108,11 @@
}, },
update: function(first) { update: function(first) {
if (this.tick == null) return; if (this.tick == null) return
if (!this.options.hint.async) { var self = this, myTick = ++this.tick
this.finishUpdate(this.options.hint(this.cm, this.options), first); fetchHints(this.options.hint, this.cm, this.options, function(data) {
} else { if (self.tick == myTick) self.finishUpdate(data, first)
var myTick = ++this.tick, self = this; })
this.options.hint(this.cm, function(data) {
if (self.tick == myTick) self.finishUpdate(data, first);
}, this.options);
}
}, },
finishUpdate: function(data, first) { finishUpdate: function(data, first) {
@ -125,7 +121,6 @@
var picked = (this.widget && this.widget.picked) || (first && this.options.completeSingle); var picked = (this.widget && this.widget.picked) || (first && this.options.completeSingle);
if (this.widget) this.widget.close(); if (this.widget) this.widget.close();
if (data && this.data && isNewCompletion(this.data, data)) return;
this.data = data; this.data = data;
if (data && data.list.length) { if (data && data.list.length) {
@ -139,11 +134,6 @@
} }
}; };
function isNewCompletion(old, nw) {
var moved = CodeMirror.cmpPos(nw.from, old.from)
return moved > 0 && old.to.ch - old.from.ch != nw.to.ch - nw.from.ch
}
function parseOptions(cm, pos, options) { function parseOptions(cm, pos, options) {
var editor = cm.options.hintOptions; var editor = cm.options.hintOptions;
var out = {}; var out = {};
@ -210,7 +200,8 @@
var widget = this, cm = completion.cm; var widget = this, cm = completion.cm;
var hints = this.hints = document.createElement("ul"); var hints = this.hints = document.createElement("ul");
hints.className = "CodeMirror-hints"; var theme = completion.cm.options.theme;
hints.className = "CodeMirror-hints " + theme;
this.selectedHint = data.selectedHint || 0; this.selectedHint = data.selectedHint || 0;
var completions = data.list; var completions = data.list;
@ -233,6 +224,9 @@
var winH = window.innerHeight || Math.max(document.body.offsetHeight, document.documentElement.offsetHeight); var winH = window.innerHeight || Math.max(document.body.offsetHeight, document.documentElement.offsetHeight);
(completion.options.container || document.body).appendChild(hints); (completion.options.container || document.body).appendChild(hints);
var box = hints.getBoundingClientRect(), overlapY = box.bottom - winH; var box = hints.getBoundingClientRect(), overlapY = box.bottom - winH;
var scrolls = hints.scrollHeight > hints.clientHeight + 1
var startScroll = cm.getScrollInfo();
if (overlapY > 0) { if (overlapY > 0) {
var height = box.bottom - box.top, curTop = pos.top - (pos.bottom - box.top); var height = box.bottom - box.top, curTop = pos.top - (pos.bottom - box.top);
if (curTop - height > 0) { // Fits above cursor if (curTop - height > 0) { // Fits above cursor
@ -257,6 +251,8 @@
} }
hints.style.left = (left = pos.left - overlapX) + "px"; hints.style.left = (left = pos.left - overlapX) + "px";
} }
if (scrolls) for (var node = hints.firstChild; node; node = node.nextSibling)
node.style.paddingRight = cm.display.nativeBarWidth + "px"
cm.addKeyMap(this.keyMap = buildKeyMap(completion, { cm.addKeyMap(this.keyMap = buildKeyMap(completion, {
moveFocus: function(n, avoidWrap) { widget.changeActive(widget.selectedHint + n, avoidWrap); }, moveFocus: function(n, avoidWrap) { widget.changeActive(widget.selectedHint + n, avoidWrap); },
@ -274,7 +270,6 @@
cm.on("focus", this.onFocus = function() { clearTimeout(closingOnBlur); }); cm.on("focus", this.onFocus = function() { clearTimeout(closingOnBlur); });
} }
var startScroll = cm.getScrollInfo();
cm.on("scroll", this.onScroll = function() { cm.on("scroll", this.onScroll = function() {
var curScroll = cm.getScrollInfo(), editor = cm.getWrapperElement().getBoundingClientRect(); var curScroll = cm.getScrollInfo(), editor = cm.getWrapperElement().getBoundingClientRect();
var newTop = top + startScroll.top - curScroll.top; var newTop = top + startScroll.top - curScroll.top;
@ -302,7 +297,7 @@
setTimeout(function(){cm.focus();}, 20); setTimeout(function(){cm.focus();}, 20);
}); });
CodeMirror.signal(data, "select", completions[0], hints.firstChild); CodeMirror.signal(data, "select", completions[this.selectedHint], hints.childNodes[this.selectedHint]);
return true; return true;
} }
@ -339,7 +334,7 @@
i = avoidWrap ? 0 : this.data.list.length - 1; i = avoidWrap ? 0 : this.data.list.length - 1;
if (this.selectedHint == i) return; if (this.selectedHint == i) return;
var node = this.hints.childNodes[this.selectedHint]; var node = this.hints.childNodes[this.selectedHint];
node.className = node.className.replace(" " + ACTIVE_HINT_ELEMENT_CLASS, ""); if (node) node.className = node.className.replace(" " + ACTIVE_HINT_ELEMENT_CLASS, "");
node = this.hints.childNodes[this.selectedHint = i]; node = this.hints.childNodes[this.selectedHint = i];
node.className += " " + ACTIVE_HINT_ELEMENT_CLASS; node.className += " " + ACTIVE_HINT_ELEMENT_CLASS;
if (node.offsetTop < this.hints.scrollTop) if (node.offsetTop < this.hints.scrollTop)
@ -362,40 +357,31 @@
return result return result
} }
function fetchHints(hint, cm, options, callback) {
if (hint.async) {
hint(cm, callback, options)
} else {
var result = hint(cm, options)
if (result && result.then) result.then(callback)
else callback(result)
}
}
function resolveAutoHints(cm, pos) { function resolveAutoHints(cm, pos) {
var helpers = cm.getHelpers(pos, "hint"), words var helpers = cm.getHelpers(pos, "hint"), words
if (helpers.length) { if (helpers.length) {
var async = false, resolved var resolved = function(cm, callback, options) {
for (var i = 0; i < helpers.length; i++) if (helpers[i].async) async = true var app = applicableHelpers(cm, helpers);
if (async) { function run(i) {
resolved = function(cm, callback, options) { if (i == app.length) return callback(null)
var app = applicableHelpers(cm, helpers) fetchHints(app[i], cm, options, function(result) {
function run(i, result) { if (result && result.list.length > 0) callback(result)
if (i == app.length) return callback(null) else run(i + 1)
var helper = app[i] })
if (helper.async) {
helper(cm, function(result) {
if (result) callback(result)
else run(i + 1)
}, options)
} else {
var result = helper(cm, options)
if (result) callback(result)
else run(i + 1)
}
}
run(0)
}
resolved.async = true
} else {
resolved = function(cm, options) {
var app = applicableHelpers(cm, helpers)
for (var i = 0; i < app.length; i++) {
var cur = app[i](cm, options)
if (cur && cur.list.length) return cur
}
} }
run(0)
} }
resolved.async = true
resolved.supportsSelection = true resolved.supportsSelection = true
return resolved return resolved
} else if (words = cm.getHelper(cm.getCursor(), "hintWords")) { } else if (words = cm.getHelper(cm.getCursor(), "hintWords")) {
@ -412,12 +398,13 @@
}); });
CodeMirror.registerHelper("hint", "fromList", function(cm, options) { CodeMirror.registerHelper("hint", "fromList", function(cm, options) {
var cur = cm.getCursor(), token = cm.getTokenAt(cur); var cur = cm.getCursor(), token = cm.getTokenAt(cur)
var to = CodeMirror.Pos(cur.line, token.end); var term, from = CodeMirror.Pos(cur.line, token.start), to = cur
if (token.string && /\w/.test(token.string[token.string.length - 1])) { if (token.start < cur.ch && /\w/.test(token.string.charAt(cur.ch - token.start - 1))) {
var term = token.string, from = CodeMirror.Pos(cur.line, token.start); term = token.string.substr(0, cur.ch - token.start)
} else { } else {
var term = "", from = to; term = ""
from = cur
} }
var found = []; var found = [];
for (var i = 0; i < options.words.length; i++) { for (var i = 0; i < options.words.length; i++) {

@ -5,6 +5,7 @@
font-family: monospace; font-family: monospace;
height: 300px; height: 300px;
color: black; color: black;
direction: ltr;
} }
/* PADDING */ /* PADDING */
@ -52,13 +53,18 @@
} }
.cm-fat-cursor .CodeMirror-cursor { .cm-fat-cursor .CodeMirror-cursor {
width: auto; width: auto;
border: 0; border: 0 !important;
background: #7e7; background: #7e7;
} }
.cm-fat-cursor div.CodeMirror-cursors { .cm-fat-cursor div.CodeMirror-cursors {
z-index: 1; z-index: 1;
} }
.cm-fat-cursor-mark {
background-color: rgba(20, 255, 20, 0.5);
-webkit-animation: blink 1.06s steps(1) infinite;
-moz-animation: blink 1.06s steps(1) infinite;
animation: blink 1.06s steps(1) infinite;
}
.cm-animate-fat-cursor { .cm-animate-fat-cursor {
width: auto; width: auto;
border: 0; border: 0;
@ -88,8 +94,14 @@
.cm-tab { display: inline-block; text-decoration: inherit; } .cm-tab { display: inline-block; text-decoration: inherit; }
.CodeMirror-rulers {
position: absolute;
left: 0; right: 0; top: -50px; bottom: -20px;
overflow: hidden;
}
.CodeMirror-ruler { .CodeMirror-ruler {
border-left: 1px solid #ccc; border-left: 1px solid #ccc;
top: 0; bottom: 0;
position: absolute; position: absolute;
} }
@ -113,7 +125,7 @@
.cm-s-default .cm-property, .cm-s-default .cm-property,
.cm-s-default .cm-operator {} .cm-s-default .cm-operator {}
.cm-s-default .cm-variable-2 {color: #05a;} .cm-s-default .cm-variable-2 {color: #05a;}
.cm-s-default .cm-variable-3 {color: #085;} .cm-s-default .cm-variable-3, .cm-s-default .cm-type {color: #085;}
.cm-s-default .cm-comment {color: #a50;} .cm-s-default .cm-comment {color: #a50;}
.cm-s-default .cm-string {color: #a11;} .cm-s-default .cm-string {color: #a11;}
.cm-s-default .cm-string-2 {color: #f50;} .cm-s-default .cm-string-2 {color: #f50;}
@ -133,8 +145,8 @@
/* Default styles for common addons */ /* Default styles for common addons */
div.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;} div.CodeMirror span.CodeMirror-matchingbracket {color: #0b0;}
div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;} div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #a22;}
.CodeMirror-matchingtag { background: rgba(255, 150, 0, .3); } .CodeMirror-matchingtag { background: rgba(255, 150, 0, .3); }
.CodeMirror-activeline-background {background: #e8f2ff;} .CodeMirror-activeline-background {background: #e8f2ff;}
@ -200,9 +212,6 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
display: inline-block; display: inline-block;
vertical-align: top; vertical-align: top;
margin-bottom: -30px; margin-bottom: -30px;
/* Hack to make IE7 behave */
*zoom:1;
*display:inline;
} }
.CodeMirror-gutter-wrapper { .CodeMirror-gutter-wrapper {
position: absolute; position: absolute;
@ -220,11 +229,8 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
cursor: default; cursor: default;
z-index: 4; z-index: 4;
} }
.CodeMirror-gutter-wrapper { .CodeMirror-gutter-wrapper ::selection { background-color: transparent }
-webkit-user-select: none; .CodeMirror-gutter-wrapper ::-moz-selection { background-color: transparent }
-moz-user-select: none;
user-select: none;
}
.CodeMirror-lines { .CodeMirror-lines {
cursor: text; cursor: text;
@ -246,8 +252,8 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
position: relative; position: relative;
overflow: visible; overflow: visible;
-webkit-tap-highlight-color: transparent; -webkit-tap-highlight-color: transparent;
-webkit-font-variant-ligatures: none; -webkit-font-variant-ligatures: contextual;
font-variant-ligatures: none; font-variant-ligatures: contextual;
} }
.CodeMirror-wrap pre { .CodeMirror-wrap pre {
word-wrap: break-word; word-wrap: break-word;
@ -264,11 +270,13 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
.CodeMirror-linewidget { .CodeMirror-linewidget {
position: relative; position: relative;
z-index: 2; z-index: 2;
overflow: auto; padding: 0.1px; /* Force widget margins to stay inside of the container */
} }
.CodeMirror-widget {} .CodeMirror-widget {}
.CodeMirror-rtl pre { direction: rtl; }
.CodeMirror-code { .CodeMirror-code {
outline: none; outline: none;
} }
@ -291,7 +299,10 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
visibility: hidden; visibility: hidden;
} }
.CodeMirror-cursor { position: absolute; } .CodeMirror-cursor {
position: absolute;
pointer-events: none;
}
.CodeMirror-measure pre { position: static; } .CodeMirror-measure pre { position: static; }
div.CodeMirror-cursors { div.CodeMirror-cursors {
@ -314,13 +325,10 @@ div.CodeMirror-dragcursors {
.CodeMirror-line::-moz-selection, .CodeMirror-line > span::-moz-selection, .CodeMirror-line > span > span::-moz-selection { background: #d7d4f0; } .CodeMirror-line::-moz-selection, .CodeMirror-line > span::-moz-selection, .CodeMirror-line > span > span::-moz-selection { background: #d7d4f0; }
.cm-searching { .cm-searching {
background: #ffa; background-color: #ffa;
background: rgba(255, 255, 0, .4); background-color: rgba(255, 255, 0, .4);
} }
/* IE7 hack to prevent it from returning funny offsetTops on the spans */
.CodeMirror span { *vertical-align: text-bottom; }
/* Used to force a border model for a node */ /* Used to force a border model for a node */
.cm-force-border { padding-right: .1px; } .cm-force-border { padding-right: .1px; }

@ -1,5 +1,5 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others // CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE // Distributed under an MIT license: https://codemirror.net/LICENSE
(function(mod) { (function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS if (typeof exports == "object" && typeof module == "object") // CommonJS
@ -11,21 +11,19 @@
})(function(CodeMirror) { })(function(CodeMirror) {
"use strict"; "use strict";
function Context(indented, column, type, align, prev) { function Context(indented, column, type, info, align, prev) {
this.indented = indented; this.indented = indented;
this.column = column; this.column = column;
this.type = type; this.type = type;
this.info = info;
this.align = align; this.align = align;
this.prev = prev; this.prev = prev;
} }
function isStatement(type) { function pushContext(state, col, type, info) {
return type == "statement" || type == "switchstatement" || type == "namespace";
}
function pushContext(state, col, type) {
var indent = state.indented; var indent = state.indented;
if (state.context && isStatement(state.context.type) && !isStatement(type)) if (state.context && state.context.type == "statement" && type != "statement")
indent = state.context.indented; indent = state.context.indented;
return state.context = new Context(indent, col, type, null, state.context); return state.context = new Context(indent, col, type, info, null, state.context);
} }
function popContext(state) { function popContext(state) {
var t = state.context.type; var t = state.context.type;
@ -34,15 +32,16 @@ function popContext(state) {
return state.context = state.context.prev; return state.context = state.context.prev;
} }
function typeBefore(stream, state) { function typeBefore(stream, state, pos) {
if (state.prevToken == "variable" || state.prevToken == "variable-3") return true; if (state.prevToken == "variable" || state.prevToken == "type") return true;
if (/\S(?:[^- ]>|[*\]])\s*$|\*$/.test(stream.string.slice(0, stream.start))) return true; if (/\S(?:[^- ]>|[*\]])\s*$|\*$/.test(stream.string.slice(0, pos))) return true;
if (state.typeAtEndOfLine && stream.column() == stream.indentation()) return true;
} }
function isTopScope(context) { function isTopScope(context) {
for (;;) { for (;;) {
if (!context || context.type == "top") return true; if (!context || context.type == "top") return true;
if (context.type == "}" && context.prev.type != "namespace") return false; if (context.type == "}" && context.prev.info != "namespace") return false;
context = context.prev; context = context.prev;
} }
} }
@ -66,7 +65,10 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
numberStart = parserConfig.numberStart || /[\d\.]/, numberStart = parserConfig.numberStart || /[\d\.]/,
number = parserConfig.number || /^(?:0x[a-f\d]+|0b[01]+|(?:\d+\.?\d*|\.\d+)(?:e[-+]?\d+)?)(u|ll?|l|f)?/i, number = parserConfig.number || /^(?:0x[a-f\d]+|0b[01]+|(?:\d+\.?\d*|\.\d+)(?:e[-+]?\d+)?)(u|ll?|l|f)?/i,
isOperatorChar = parserConfig.isOperatorChar || /[+\-*&%=<>!?|\/]/, isOperatorChar = parserConfig.isOperatorChar || /[+\-*&%=<>!?|\/]/,
endStatement = parserConfig.endStatement || /^[;:,]$/; isIdentifierChar = parserConfig.isIdentifierChar || /[\w\$_\xa1-\uffff]/,
// An optional function that takes a {string} token and returns true if it
// should be treated as a builtin.
isReservedIdentifier = parserConfig.isReservedIdentifier || false;
var curPunc, isDefKeyword; var curPunc, isDefKeyword;
@ -103,9 +105,9 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
while (!stream.match(/^\/[\/*]/, false) && stream.eat(isOperatorChar)) {} while (!stream.match(/^\/[\/*]/, false) && stream.eat(isOperatorChar)) {}
return "operator"; return "operator";
} }
stream.eatWhile(/[\w\$_\xa1-\uffff]/); stream.eatWhile(isIdentifierChar);
if (namespaceSeparator) while (stream.match(namespaceSeparator)) if (namespaceSeparator) while (stream.match(namespaceSeparator))
stream.eatWhile(/[\w\$_\xa1-\uffff]/); stream.eatWhile(isIdentifierChar);
var cur = stream.current(); var cur = stream.current();
if (contains(keywords, cur)) { if (contains(keywords, cur)) {
@ -113,8 +115,9 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
if (contains(defKeywords, cur)) isDefKeyword = true; if (contains(defKeywords, cur)) isDefKeyword = true;
return "keyword"; return "keyword";
} }
if (contains(types, cur)) return "variable-3"; if (contains(types, cur)) return "type";
if (contains(builtin, cur)) { if (contains(builtin, cur)
|| (isReservedIdentifier && isReservedIdentifier(cur))) {
if (contains(blockKeywords, cur)) curPunc = "newstatement"; if (contains(blockKeywords, cur)) curPunc = "newstatement";
return "builtin"; return "builtin";
} }
@ -147,13 +150,18 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
return "comment"; return "comment";
} }
function maybeEOL(stream, state) {
if (parserConfig.typeFirstDefinitions && stream.eol() && isTopScope(state.context))
state.typeAtEndOfLine = typeBefore(stream, state, stream.pos)
}
// Interface // Interface
return { return {
startState: function(basecolumn) { startState: function(basecolumn) {
return { return {
tokenize: null, tokenize: null,
context: new Context((basecolumn || 0) - indentUnit, 0, "top", false), context: new Context((basecolumn || 0) - indentUnit, 0, "top", null, false),
indented: 0, indented: 0,
startOfLine: true, startOfLine: true,
prevToken: null prevToken: null
@ -167,36 +175,32 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
state.indented = stream.indentation(); state.indented = stream.indentation();
state.startOfLine = true; state.startOfLine = true;
} }
if (stream.eatSpace()) return null; if (stream.eatSpace()) { maybeEOL(stream, state); return null; }
curPunc = isDefKeyword = null; curPunc = isDefKeyword = null;
var style = (state.tokenize || tokenBase)(stream, state); var style = (state.tokenize || tokenBase)(stream, state);
if (style == "comment" || style == "meta") return style; if (style == "comment" || style == "meta") return style;
if (ctx.align == null) ctx.align = true; if (ctx.align == null) ctx.align = true;
if (endStatement.test(curPunc)) while (isStatement(state.context.type)) popContext(state); if (curPunc == ";" || curPunc == ":" || (curPunc == "," && stream.match(/^\s*(?:\/\/.*)?$/, false)))
while (state.context.type == "statement") popContext(state);
else if (curPunc == "{") pushContext(state, stream.column(), "}"); else if (curPunc == "{") pushContext(state, stream.column(), "}");
else if (curPunc == "[") pushContext(state, stream.column(), "]"); else if (curPunc == "[") pushContext(state, stream.column(), "]");
else if (curPunc == "(") pushContext(state, stream.column(), ")"); else if (curPunc == "(") pushContext(state, stream.column(), ")");
else if (curPunc == "}") { else if (curPunc == "}") {
while (isStatement(ctx.type)) ctx = popContext(state); while (ctx.type == "statement") ctx = popContext(state);
if (ctx.type == "}") ctx = popContext(state); if (ctx.type == "}") ctx = popContext(state);
while (isStatement(ctx.type)) ctx = popContext(state); while (ctx.type == "statement") ctx = popContext(state);
} }
else if (curPunc == ctx.type) popContext(state); else if (curPunc == ctx.type) popContext(state);
else if (indentStatements && else if (indentStatements &&
(((ctx.type == "}" || ctx.type == "top") && curPunc != ";") || (((ctx.type == "}" || ctx.type == "top") && curPunc != ";") ||
(isStatement(ctx.type) && curPunc == "newstatement"))) { (ctx.type == "statement" && curPunc == "newstatement"))) {
var type = "statement"; pushContext(state, stream.column(), "statement", stream.current());
if (curPunc == "newstatement" && indentSwitch && stream.current() == "switch")
type = "switchstatement";
else if (style == "keyword" && stream.current() == "namespace")
type = "namespace";
pushContext(state, stream.column(), type);
} }
if (style == "variable" && if (style == "variable" &&
((state.prevToken == "def" || ((state.prevToken == "def" ||
(parserConfig.typeFirstDefinitions && typeBefore(stream, state) && (parserConfig.typeFirstDefinitions && typeBefore(stream, state, stream.start) &&
isTopScope(state.context) && stream.match(/^\s*\(/, false))))) isTopScope(state.context) && stream.match(/^\s*\(/, false)))))
style = "def"; style = "def";
@ -209,24 +213,28 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
state.startOfLine = false; state.startOfLine = false;
state.prevToken = isDefKeyword ? "def" : style || curPunc; state.prevToken = isDefKeyword ? "def" : style || curPunc;
maybeEOL(stream, state);
return style; return style;
}, },
indent: function(state, textAfter) { indent: function(state, textAfter) {
if (state.tokenize != tokenBase && state.tokenize != null) return CodeMirror.Pass; if (state.tokenize != tokenBase && state.tokenize != null || state.typeAtEndOfLine) return CodeMirror.Pass;
var ctx = state.context, firstChar = textAfter && textAfter.charAt(0); var ctx = state.context, firstChar = textAfter && textAfter.charAt(0);
if (isStatement(ctx.type) && firstChar == "}") ctx = ctx.prev; var closing = firstChar == ctx.type;
if (ctx.type == "statement" && firstChar == "}") ctx = ctx.prev;
if (parserConfig.dontIndentStatements)
while (ctx.type == "statement" && parserConfig.dontIndentStatements.test(ctx.info))
ctx = ctx.prev
if (hooks.indent) { if (hooks.indent) {
var hook = hooks.indent(state, ctx, textAfter); var hook = hooks.indent(state, ctx, textAfter, indentUnit);
if (typeof hook == "number") return hook if (typeof hook == "number") return hook
} }
var closing = firstChar == ctx.type; var switchBlock = ctx.prev && ctx.prev.info == "switch";
var switchBlock = ctx.prev && ctx.prev.type == "switchstatement";
if (parserConfig.allmanIndentation && /[{(]/.test(firstChar)) { if (parserConfig.allmanIndentation && /[{(]/.test(firstChar)) {
while (ctx.type != "top" && ctx.type != "}") ctx = ctx.prev while (ctx.type != "top" && ctx.type != "}") ctx = ctx.prev
return ctx.indented return ctx.indented
} }
if (isStatement(ctx.type)) if (ctx.type == "statement")
return ctx.indented + (firstChar == "{" ? 0 : statementIndentUnit); return ctx.indented + (firstChar == "{" ? 0 : statementIndentUnit);
if (ctx.align && (!dontAlignCalls || ctx.type != ")")) if (ctx.align && (!dontAlignCalls || ctx.type != ")"))
return ctx.column + (closing ? 0 : 1); return ctx.column + (closing ? 0 : 1);
@ -240,6 +248,7 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
electricInput: indentSwitch ? /^\s*(?:case .*?:|default:|\{\}?|\})$/ : /^\s*[{}]$/, electricInput: indentSwitch ? /^\s*(?:case .*?:|default:|\{\}?|\})$/ : /^\s*[{}]$/,
blockCommentStart: "/*", blockCommentStart: "/*",
blockCommentEnd: "*/", blockCommentEnd: "*/",
blockCommentContinue: " * ",
lineComment: "//", lineComment: "//",
fold: "brace" fold: "brace"
}; };
@ -258,8 +267,33 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
} }
} }
var cKeywords = "auto if break case register continue return default do sizeof " + var cKeywords = "auto if break case register continue return default do sizeof " +
"static else struct switch extern typedef union for goto while enum const volatile"; "static else struct switch extern typedef union for goto while enum const " +
var cTypes = "int long char short double float unsigned signed void size_t ptrdiff_t"; "volatile inline restrict asm fortran";
// Do not use this. Use the cTypes function below. This is global just to avoid
// excessive calls when cTypes is being called multiple times during a parse.
var basicCTypes = words("int long char short double float unsigned signed " +
"void bool");
// Do not use this. Use the objCTypes function below. This is global just to avoid
// excessive calls when objCTypes is being called multiple times during a parse.
var basicObjCTypes = words("SEL instancetype id Class Protocol BOOL");
// Returns true if identifier is a "C" type.
// C type is defined as those that are reserved by the compiler (basicTypes),
// and those that end in _t (Reserved by POSIX for types)
// http://www.gnu.org/software/libc/manual/html_node/Reserved-Names.html
function cTypes(identifier) {
return contains(basicCTypes, identifier) || /.+_t/.test(identifier);
}
// Returns true if identifier is a "Objective C" type.
function objCTypes(identifier) {
return cTypes(identifier) || contains(basicObjCTypes, identifier);
}
var cBlockKeywords = "case do else for if switch while struct enum union";
var cDefKeywords = "struct enum union";
function cppHook(stream, state) { function cppHook(stream, state) {
if (!state.startOfLine) return false if (!state.startOfLine) return false
@ -277,10 +311,18 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
} }
function pointerHook(_stream, state) { function pointerHook(_stream, state) {
if (state.prevToken == "variable-3") return "variable-3"; if (state.prevToken == "type") return "type";
return false; return false;
} }
// For C and C++ (and ObjC): identifiers starting with __
// or _ followed by a capital letter are reserved for the compiler.
function cIsReservedIdentifier(token) {
if (!token || token.length < 2) return false;
if (token[0] != '_') return false;
return (token[1] == '_') || (token[1] !== token[1].toLowerCase());
}
function cpp14Literal(stream) { function cpp14Literal(stream) {
stream.eatWhile(/[\w\.']/); stream.eatWhile(/[\w\.']/);
return "number"; return "number";
@ -311,7 +353,7 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
} }
function cppLooksLikeConstructor(word) { function cppLooksLikeConstructor(word) {
var lastTwo = /(\w+)::(\w+)$/.exec(word); var lastTwo = /(\w+)::~?(\w+)$/.exec(word);
return lastTwo && lastTwo[1] == lastTwo[2]; return lastTwo && lastTwo[1] == lastTwo[2];
} }
@ -363,29 +405,34 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
def(["text/x-csrc", "text/x-c", "text/x-chdr"], { def(["text/x-csrc", "text/x-c", "text/x-chdr"], {
name: "clike", name: "clike",
keywords: words(cKeywords), keywords: words(cKeywords),
types: words(cTypes + " bool _Complex _Bool float_t double_t intptr_t intmax_t " + types: cTypes,
"int8_t int16_t int32_t int64_t uintptr_t uintmax_t uint8_t uint16_t " + blockKeywords: words(cBlockKeywords),
"uint32_t uint64_t"), defKeywords: words(cDefKeywords),
blockKeywords: words("case do else for if switch while struct"),
defKeywords: words("struct"),
typeFirstDefinitions: true, typeFirstDefinitions: true,
atoms: words("null true false"), atoms: words("NULL true false"),
hooks: {"#": cppHook, "*": pointerHook}, isReservedIdentifier: cIsReservedIdentifier,
hooks: {
"#": cppHook,
"*": pointerHook,
},
modeProps: {fold: ["brace", "include"]} modeProps: {fold: ["brace", "include"]}
}); });
def(["text/x-c++src", "text/x-c++hdr"], { def(["text/x-c++src", "text/x-c++hdr"], {
name: "clike", name: "clike",
keywords: words(cKeywords + " asm dynamic_cast namespace reinterpret_cast try explicit new " + keywords: words(cKeywords + " dynamic_cast namespace reinterpret_cast try explicit new " +
"static_cast typeid catch operator template typename class friend private " + "static_cast typeid catch operator template typename class friend private " +
"this using const_cast inline public throw virtual delete mutable protected " + "this using const_cast public throw virtual delete mutable protected " +
"alignas alignof constexpr decltype nullptr noexcept thread_local final " + "alignas alignof constexpr decltype nullptr noexcept thread_local final " +
"static_assert override"), "static_assert override"),
types: words(cTypes + " bool wchar_t"), types: cTypes,
blockKeywords: words("catch class do else finally for if struct switch try while"), blockKeywords: words(cBlockKeywords +" class try catch finally"),
defKeywords: words("class namespace struct enum union"), defKeywords: words(cDefKeywords + " class namespace"),
typeFirstDefinitions: true, typeFirstDefinitions: true,
atoms: words("true false null"), atoms: words("true false NULL"),
dontIndentStatements: /^template$/,
isIdentifierChar: /[\w\$_~\xa1-\uffff]/,
isReservedIdentifier: cIsReservedIdentifier,
hooks: { hooks: {
"#": cppHook, "#": cppHook,
"*": pointerHook, "*": pointerHook,
@ -421,16 +468,19 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
"do else enum extends final finally float for goto if implements import " + "do else enum extends final finally float for goto if implements import " +
"instanceof interface native new package private protected public " + "instanceof interface native new package private protected public " +
"return static strictfp super switch synchronized this throw throws transient " + "return static strictfp super switch synchronized this throw throws transient " +
"try volatile while"), "try volatile while @interface"),
types: words("byte short int long float double boolean char void Boolean Byte Character Double Float " + types: words("byte short int long float double boolean char void Boolean Byte Character Double Float " +
"Integer Long Number Object Short String StringBuffer StringBuilder Void"), "Integer Long Number Object Short String StringBuffer StringBuilder Void"),
blockKeywords: words("catch class do else finally for if switch try while"), blockKeywords: words("catch class do else finally for if switch try while"),
defKeywords: words("class interface package enum"), defKeywords: words("class interface enum @interface"),
typeFirstDefinitions: true, typeFirstDefinitions: true,
atoms: words("true false null"), atoms: words("true false null"),
endStatement: /^[;:]$/, number: /^(?:0x[a-f\d_]+|0b[01_]+|(?:[\d_]+\.?\d*|\.\d+)(?:e[-+]?[\d_]+)?)(u|ll?|l|f)?/i,
hooks: { hooks: {
"@": function(stream) { "@": function(stream) {
// Don't match the @interface keyword.
if (stream.match('interface', false)) return false;
stream.eatWhile(/[\w\$_]/); stream.eatWhile(/[\w\$_]/);
return "meta"; return "meta";
} }
@ -479,21 +529,38 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
return "string"; return "string";
} }
function tokenNestedComment(depth) {
return function (stream, state) {
var ch
while (ch = stream.next()) {
if (ch == "*" && stream.eat("/")) {
if (depth == 1) {
state.tokenize = null
break
} else {
state.tokenize = tokenNestedComment(depth - 1)
return state.tokenize(stream, state)
}
} else if (ch == "/" && stream.eat("*")) {
state.tokenize = tokenNestedComment(depth + 1)
return state.tokenize(stream, state)
}
}
return "comment"
}
}
def("text/x-scala", { def("text/x-scala", {
name: "clike", name: "clike",
keywords: words( keywords: words(
/* scala */ /* scala */
"abstract case catch class def do else extends final finally for forSome if " + "abstract case catch class def do else extends final finally for forSome if " +
"implicit import lazy match new null object override package private protected return " + "implicit import lazy match new null object override package private protected return " +
"sealed super this throw trait try type val var while with yield _ : = => <- <: " + "sealed super this throw trait try type val var while with yield _ " +
"<% >: # @ " +
/* package scala */ /* package scala */
"assert assume require print println printf readLine readBoolean readByte readShort " + "assert assume require print println printf readLine readBoolean readByte readShort " +
"readChar readInt readLong readFloat readDouble " + "readChar readInt readLong readFloat readDouble"
":: #:: "
), ),
types: words( types: words(
"AnyVal App Application Array BufferedIterator BigDecimal BigInt Char Console Either " + "AnyVal App Application Array BufferedIterator BigDecimal BigInt Char Console Either " +
@ -509,11 +576,12 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
"StringBuffer System Thread ThreadGroup ThreadLocal Throwable Triple Void" "StringBuffer System Thread ThreadGroup ThreadLocal Throwable Triple Void"
), ),
multiLineStrings: true, multiLineStrings: true,
blockKeywords: words("catch class do else finally for forSome if match switch try while"), blockKeywords: words("catch class enum do else finally for forSome if match switch try while"),
defKeywords: words("class def object package trait type val var"), defKeywords: words("class enum def object package trait type val var"),
atoms: words("true false null"), atoms: words("true false null"),
indentStatements: false, indentStatements: false,
indentSwitch: false, indentSwitch: false,
isOperatorChar: /[+\-*&%=<>!?|\/#:@]/,
hooks: { hooks: {
"@": function(stream) { "@": function(stream) {
stream.eatWhile(/[\w\$_]/); stream.eatWhile(/[\w\$_]/);
@ -531,14 +599,20 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
"=": function(stream, state) { "=": function(stream, state) {
var cx = state.context var cx = state.context
if (cx.type == "}" && cx.align && stream.eat(">")) { if (cx.type == "}" && cx.align && stream.eat(">")) {
state.context = new Context(cx.indented, cx.column, cx.type, null, cx.prev) state.context = new Context(cx.indented, cx.column, cx.type, cx.info, null, cx.prev)
return "operator" return "operator"
} else { } else {
return false return false
} }
},
"/": function(stream, state) {
if (!stream.eat("*")) return false
state.tokenize = tokenNestedComment(1)
return state.tokenize(stream, state)
} }
}, },
modeProps: {closeBrackets: {triples: '"'}} modeProps: {closeBrackets: {pairs: '()[]{}""', triples: '"'}}
}); });
function tokenKotlinString(tripleString){ function tokenKotlinString(tripleString){
@ -562,33 +636,51 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
name: "clike", name: "clike",
keywords: words( keywords: words(
/*keywords*/ /*keywords*/
"package as typealias class interface this super val " + "package as typealias class interface this super val operator " +
"var fun for is in This throw return " + "var fun for is in This throw return annotation " +
"break continue object if else while do try when !in !is as? " + "break continue object if else while do try when !in !is as? " +
/*soft keywords*/ /*soft keywords*/
"file import where by get set abstract enum open inner override private public internal " + "file import where by get set abstract enum open inner override private public internal " +
"protected catch finally out final vararg reified dynamic companion constructor init " + "protected catch finally out final vararg reified dynamic companion constructor init " +
"sealed field property receiver param sparam lateinit data inline noinline tailrec " + "sealed field property receiver param sparam lateinit data inline noinline tailrec " +
"external annotation crossinline const operator infix" "external annotation crossinline const operator infix suspend actual expect setparam"
), ),
types: words( types: words(
/* package java.lang */ /* package java.lang */
"Boolean Byte Character CharSequence Class ClassLoader Cloneable Comparable " + "Boolean Byte Character CharSequence Class ClassLoader Cloneable Comparable " +
"Compiler Double Exception Float Integer Long Math Number Object Package Pair Process " + "Compiler Double Exception Float Integer Long Math Number Object Package Pair Process " +
"Runtime Runnable SecurityManager Short StackTraceElement StrictMath String " + "Runtime Runnable SecurityManager Short StackTraceElement StrictMath String " +
"StringBuffer System Thread ThreadGroup ThreadLocal Throwable Triple Void" "StringBuffer System Thread ThreadGroup ThreadLocal Throwable Triple Void Annotation Any BooleanArray " +
"ByteArray Char CharArray DeprecationLevel DoubleArray Enum FloatArray Function Int IntArray Lazy " +
"LazyThreadSafetyMode LongArray Nothing ShortArray Unit"
), ),
intendSwitch: false, intendSwitch: false,
indentStatements: false, indentStatements: false,
multiLineStrings: true, multiLineStrings: true,
number: /^(?:0x[a-f\d_]+|0b[01_]+|(?:[\d_]+(\.\d+)?|\.\d+)(?:e[-+]?[\d_]+)?)(u|ll?|l|f)?/i,
blockKeywords: words("catch class do else finally for if where try while enum"), blockKeywords: words("catch class do else finally for if where try while enum"),
defKeywords: words("class val var object package interface fun"), defKeywords: words("class val var object interface fun"),
atoms: words("true false null this"), atoms: words("true false null this"),
hooks: { hooks: {
"@": function(stream) {
stream.eatWhile(/[\w\$_]/);
return "meta";
},
'"': function(stream, state) { '"': function(stream, state) {
state.tokenize = tokenKotlinString(stream.match('""')); state.tokenize = tokenKotlinString(stream.match('""'));
return state.tokenize(stream, state); return state.tokenize(stream, state);
},
indent: function(state, ctx, textAfter, indentUnit) {
var firstChar = textAfter && textAfter.charAt(0);
if ((state.prevToken == "}" || state.prevToken == ")") && textAfter == "")
return state.indented;
if (state.prevToken == "operator" && textAfter != "}" ||
state.prevToken == "variable" && firstChar == "." ||
(state.prevToken == "}" || state.prevToken == ")") && firstChar == ".")
return indentUnit * 2 + ctx.indented;
if (ctx.align && ctx.type == "}")
return ctx.indented + (state.context.type == (textAfter || "").charAt(0) ? 0 : indentUnit);
} }
}, },
modeProps: {closeBrackets: {triples: '"'}} modeProps: {closeBrackets: {triples: '"'}}
@ -655,11 +747,11 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
def("text/x-nesc", { def("text/x-nesc", {
name: "clike", name: "clike",
keywords: words(cKeywords + "as atomic async call command component components configuration event generic " + keywords: words(cKeywords + " as atomic async call command component components configuration event generic " +
"implementation includes interface module new norace nx_struct nx_union post provides " + "implementation includes interface module new norace nx_struct nx_union post provides " +
"signal task uses abstract extends"), "signal task uses abstract extends"),
types: words(cTypes), types: cTypes,
blockKeywords: words("case do else for if switch while struct"), blockKeywords: words(cBlockKeywords),
atoms: words("null true false"), atoms: words("null true false"),
hooks: {"#": cppHook}, hooks: {"#": cppHook},
modeProps: {fold: ["brace", "include"]} modeProps: {fold: ["brace", "include"]}
@ -667,28 +759,34 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
def("text/x-objectivec", { def("text/x-objectivec", {
name: "clike", name: "clike",
keywords: words(cKeywords + "inline restrict _Bool _Complex _Imaginery BOOL Class bycopy byref id IMP in " + keywords: words(cKeywords + " bycopy byref in inout oneway out self super atomic nonatomic retain copy " +
"inout nil oneway out Protocol SEL self super atomic nonatomic retain copy readwrite readonly"), "readwrite readonly strong weak assign typeof nullable nonnull null_resettable _cmd " +
types: words(cTypes), "@interface @implementation @end @protocol @encode @property @synthesize @dynamic @class " +
atoms: words("YES NO NULL NILL ON OFF true false"), "@public @package @private @protected @required @optional @try @catch @finally @import " +
"@selector @encode @defs @synchronized @autoreleasepool @compatibility_alias @available"),
types: objCTypes,
builtin: words("FOUNDATION_EXPORT FOUNDATION_EXTERN NS_INLINE NS_FORMAT_FUNCTION NS_RETURNS_RETAINED " +
"NS_ERROR_ENUM NS_RETURNS_NOT_RETAINED NS_RETURNS_INNER_POINTER NS_DESIGNATED_INITIALIZER " +
"NS_ENUM NS_OPTIONS NS_REQUIRES_NIL_TERMINATION NS_ASSUME_NONNULL_BEGIN " +
"NS_ASSUME_NONNULL_END NS_SWIFT_NAME NS_REFINED_FOR_SWIFT"),
blockKeywords: words(cBlockKeywords + " @synthesize @try @catch @finally @autoreleasepool @synchronized"),
defKeywords: words(cDefKeywords + " @interface @implementation @protocol @class"),
dontIndentStatements: /^@.*$/,
typeFirstDefinitions: true,
atoms: words("YES NO NULL Nil nil true false nullptr"),
isReservedIdentifier: cIsReservedIdentifier,
hooks: { hooks: {
"@": function(stream) {
stream.eatWhile(/[\w\$]/);
return "keyword";
},
"#": cppHook, "#": cppHook,
indent: function(_state, ctx, textAfter) { "*": pointerHook,
if (ctx.type == "statement" && /^@\w/.test(textAfter)) return ctx.indented
}
}, },
modeProps: {fold: "brace"} modeProps: {fold: ["brace", "include"]}
}); });
def("text/x-squirrel", { def("text/x-squirrel", {
name: "clike", name: "clike",
keywords: words("base break clone continue const default delete enum extends function in class" + keywords: words("base break clone continue const default delete enum extends function in class" +
" foreach local resume return this throw typeof yield constructor instanceof static"), " foreach local resume return this throw typeof yield constructor instanceof static"),
types: words(cTypes), types: cTypes,
blockKeywords: words("case catch class else for foreach if switch try while"), blockKeywords: words("case catch class else for foreach if switch try while"),
defKeywords: words("function local class"), defKeywords: words("function local class"),
typeFirstDefinitions: true, typeFirstDefinitions: true,
@ -766,7 +864,7 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
return "atom"; return "atom";
}, },
token: function(_stream, state, style) { token: function(_stream, state, style) {
if ((style == "variable" || style == "variable-3") && if ((style == "variable" || style == "type") &&
state.prevToken == ".") { state.prevToken == ".") {
return "variable-2"; return "variable-2";
} }

@ -1,5 +1,5 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others // CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE // Distributed under an MIT license: https://codemirror.net/LICENSE
(function(mod) { (function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS if (typeof exports == "object" && typeof module == "object") // CommonJS
@ -11,11 +11,6 @@
})(function(CodeMirror) { })(function(CodeMirror) {
"use strict"; "use strict";
function expressionAllowed(stream, state, backUp) {
return /^(?:operator|sof|keyword c|case|new|export|default|[\[{}\(,;:]|=>)$/.test(state.lastType) ||
(state.lastType == "quasi" && /\{\s*$/.test(stream.string.slice(0, stream.pos - (backUp || 0))))
}
CodeMirror.defineMode("javascript", function(config, parserConfig) { CodeMirror.defineMode("javascript", function(config, parserConfig) {
var indentUnit = config.indentUnit; var indentUnit = config.indentUnit;
var statementIndent = parserConfig.statementIndent; var statementIndent = parserConfig.statementIndent;
@ -28,53 +23,21 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
var keywords = function(){ var keywords = function(){
function kw(type) {return {type: type, style: "keyword"};} function kw(type) {return {type: type, style: "keyword"};}
var A = kw("keyword a"), B = kw("keyword b"), C = kw("keyword c"); var A = kw("keyword a"), B = kw("keyword b"), C = kw("keyword c"), D = kw("keyword d");
var operator = kw("operator"), atom = {type: "atom", style: "atom"}; var operator = kw("operator"), atom = {type: "atom", style: "atom"};
var jsKeywords = { return {
"if": kw("if"), "while": A, "with": A, "else": B, "do": B, "try": B, "finally": B, "if": kw("if"), "while": A, "with": A, "else": B, "do": B, "try": B, "finally": B,
"return": C, "break": C, "continue": C, "new": kw("new"), "delete": C, "throw": C, "debugger": C, "return": D, "break": D, "continue": D, "new": kw("new"), "delete": C, "void": C, "throw": C,
"var": kw("var"), "const": kw("var"), "let": kw("var"), "debugger": kw("debugger"), "var": kw("var"), "const": kw("var"), "let": kw("var"),
"function": kw("function"), "catch": kw("catch"), "function": kw("function"), "catch": kw("catch"),
"for": kw("for"), "switch": kw("switch"), "case": kw("case"), "default": kw("default"), "for": kw("for"), "switch": kw("switch"), "case": kw("case"), "default": kw("default"),
"in": operator, "typeof": operator, "instanceof": operator, "in": operator, "typeof": operator, "instanceof": operator,
"true": atom, "false": atom, "null": atom, "undefined": atom, "NaN": atom, "Infinity": atom, "true": atom, "false": atom, "null": atom, "undefined": atom, "NaN": atom, "Infinity": atom,
"this": kw("this"), "class": kw("class"), "super": kw("atom"), "this": kw("this"), "class": kw("class"), "super": kw("atom"),
"yield": C, "export": kw("export"), "import": kw("import"), "extends": C, "yield": C, "export": kw("export"), "import": kw("import"), "extends": C,
"await": C, "async": kw("async") "await": C
}; };
// Extend the 'normal' keywords with the TypeScript language extensions
if (isTS) {
var type = {type: "variable", style: "variable-3"};
var tsKeywords = {
// object-like things
"interface": kw("class"),
"implements": C,
"namespace": C,
"module": kw("module"),
"enum": kw("module"),
"type": kw("type"),
// scope modifiers
"public": kw("modifier"),
"private": kw("modifier"),
"protected": kw("modifier"),
"abstract": kw("modifier"),
// operators
"as": operator,
// types
"string": type, "number": type, "boolean": type, "any": type
};
for (var attr in tsKeywords) {
jsKeywords[attr] = tsKeywords[attr];
}
}
return jsKeywords;
}(); }();
var isOperatorChar = /[+\-*&%=<>!?|~^@]/; var isOperatorChar = /[+\-*&%=<>!?|~^@]/;
@ -112,17 +75,10 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
return ret(ch); return ret(ch);
} else if (ch == "=" && stream.eat(">")) { } else if (ch == "=" && stream.eat(">")) {
return ret("=>", "operator"); return ret("=>", "operator");
} else if (ch == "0" && stream.eat(/x/i)) { } else if (ch == "0" && stream.match(/^(?:x[\da-f]+|o[0-7]+|b[01]+)n?/i)) {
stream.eatWhile(/[\da-f]/i);
return ret("number", "number");
} else if (ch == "0" && stream.eat(/o/i)) {
stream.eatWhile(/[0-7]/i);
return ret("number", "number");
} else if (ch == "0" && stream.eat(/b/i)) {
stream.eatWhile(/[01]/i);
return ret("number", "number"); return ret("number", "number");
} else if (/\d/.test(ch)) { } else if (/\d/.test(ch)) {
stream.match(/^\d*(?:\.\d*)?(?:[eE][+\-]?\d+)?/); stream.match(/^\d*(?:n|(?:\.\d*)?(?:[eE][+\-]?\d+)?)?/);
return ret("number", "number"); return ret("number", "number");
} else if (ch == "/") { } else if (ch == "/") {
if (stream.eat("*")) { if (stream.eat("*")) {
@ -133,10 +89,10 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
return ret("comment", "comment"); return ret("comment", "comment");
} else if (expressionAllowed(stream, state, 1)) { } else if (expressionAllowed(stream, state, 1)) {
readRegexp(stream); readRegexp(stream);
stream.match(/^\b(([gimyu])(?![gimyu]*\2))+\b/); stream.match(/^\b(([gimyus])(?![gimyus]*\2))+\b/);
return ret("regexp", "string-2"); return ret("regexp", "string-2");
} else { } else {
stream.eatWhile(isOperatorChar); stream.eat("=");
return ret("operator", "operator", stream.current()); return ret("operator", "operator", stream.current());
} }
} else if (ch == "`") { } else if (ch == "`") {
@ -146,14 +102,27 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
stream.skipToEnd(); stream.skipToEnd();
return ret("error", "error"); return ret("error", "error");
} else if (isOperatorChar.test(ch)) { } else if (isOperatorChar.test(ch)) {
if (ch != ">" || !state.lexical || state.lexical.type != ">") if (ch != ">" || !state.lexical || state.lexical.type != ">") {
stream.eatWhile(isOperatorChar); if (stream.eat("=")) {
if (ch == "!" || ch == "=") stream.eat("=")
} else if (/[<>*+\-]/.test(ch)) {
stream.eat(ch)
if (ch == ">") stream.eat(ch)
}
}
return ret("operator", "operator", stream.current()); return ret("operator", "operator", stream.current());
} else if (wordRE.test(ch)) { } else if (wordRE.test(ch)) {
stream.eatWhile(wordRE); stream.eatWhile(wordRE);
var word = stream.current(), known = keywords.propertyIsEnumerable(word) && keywords[word]; var word = stream.current()
return (known && state.lastType != ".") ? ret(known.type, known.style, word) : if (state.lastType != ".") {
ret("variable", "variable", word); if (keywords.propertyIsEnumerable(word)) {
var kw = keywords[word]
return ret(kw.type, kw.style, word)
}
if (word == "async" && stream.match(/^(\s|\/\*.*?\*\/)*[\[\(\w]/, false))
return ret("async", "keyword", word)
}
return ret("variable", "variable", word)
} }
} }
@ -289,35 +258,68 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
pass.apply(null, arguments); pass.apply(null, arguments);
return true; return true;
} }
function inList(name, list) {
for (var v = list; v; v = v.next) if (v.name == name) return true
return false;
}
function register(varname) { function register(varname) {
function inList(list) {
for (var v = list; v; v = v.next)
if (v.name == varname) return true;
return false;
}
var state = cx.state; var state = cx.state;
cx.marked = "def"; cx.marked = "def";
if (state.context) { if (state.context) {
if (inList(state.localVars)) return; if (state.lexical.info == "var" && state.context && state.context.block) {
state.localVars = {name: varname, next: state.localVars}; // FIXME function decls are also not block scoped
var newContext = registerVarScoped(varname, state.context)
if (newContext != null) {
state.context = newContext
return
}
} else if (!inList(varname, state.localVars)) {
state.localVars = new Var(varname, state.localVars)
return
}
}
// Fall through means this is global
if (parserConfig.globalVars && !inList(varname, state.globalVars))
state.globalVars = new Var(varname, state.globalVars)
}
function registerVarScoped(varname, context) {
if (!context) {
return null
} else if (context.block) {
var inner = registerVarScoped(varname, context.prev)
if (!inner) return null
if (inner == context.prev) return context
return new Context(inner, context.vars, true)
} else if (inList(varname, context.vars)) {
return context
} else { } else {
if (inList(state.globalVars)) return; return new Context(context.prev, new Var(varname, context.vars), false)
if (parserConfig.globalVars)
state.globalVars = {name: varname, next: state.globalVars};
} }
} }
function isModifier(name) {
return name == "public" || name == "private" || name == "protected" || name == "abstract" || name == "readonly"
}
// Combinators // Combinators
var defaultVars = {name: "this", next: {name: "arguments"}}; function Context(prev, vars, block) { this.prev = prev; this.vars = vars; this.block = block }
function Var(name, next) { this.name = name; this.next = next }
var defaultVars = new Var("this", new Var("arguments", null))
function pushcontext() { function pushcontext() {
cx.state.context = {prev: cx.state.context, vars: cx.state.localVars}; cx.state.context = new Context(cx.state.context, cx.state.localVars, false)
cx.state.localVars = defaultVars; cx.state.localVars = defaultVars
}
function pushblockcontext() {
cx.state.context = new Context(cx.state.context, cx.state.localVars, true)
cx.state.localVars = null
} }
function popcontext() { function popcontext() {
cx.state.localVars = cx.state.context.vars; cx.state.localVars = cx.state.context.vars
cx.state.context = cx.state.context.prev; cx.state.context = cx.state.context.prev
} }
popcontext.lex = true
function pushlex(type, info) { function pushlex(type, info) {
var result = function() { var result = function() {
var state = cx.state, indent = state.indented; var state = cx.state, indent = state.indented;
@ -342,17 +344,19 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
function expect(wanted) { function expect(wanted) {
function exp(type) { function exp(type) {
if (type == wanted) return cont(); if (type == wanted) return cont();
else if (wanted == ";") return pass(); else if (wanted == ";" || type == "}" || type == ")" || type == "]") return pass();
else return cont(exp); else return cont(exp);
}; };
return exp; return exp;
} }
function statement(type, value) { function statement(type, value) {
if (type == "var") return cont(pushlex("vardef", value.length), vardef, expect(";"), poplex); if (type == "var") return cont(pushlex("vardef", value), vardef, expect(";"), poplex);
if (type == "keyword a") return cont(pushlex("form"), parenExpr, statement, poplex); if (type == "keyword a") return cont(pushlex("form"), parenExpr, statement, poplex);
if (type == "keyword b") return cont(pushlex("form"), statement, poplex); if (type == "keyword b") return cont(pushlex("form"), statement, poplex);
if (type == "{") return cont(pushlex("}"), block, poplex); if (type == "keyword d") return cx.stream.match(/^\s*$/, false) ? cont() : cont(pushlex("stat"), maybeexpression, expect(";"), poplex);
if (type == "debugger") return cont(expect(";"));
if (type == "{") return cont(pushlex("}"), pushblockcontext, block, poplex, popcontext);
if (type == ";") return cont(); if (type == ";") return cont();
if (type == "if") { if (type == "if") {
if (cx.state.lexical.info == "else" && cx.state.cc[cx.state.cc.length - 1] == poplex) if (cx.state.lexical.info == "else" && cx.state.cc[cx.state.cc.length - 1] == poplex)
@ -361,60 +365,75 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
} }
if (type == "function") return cont(functiondef); if (type == "function") return cont(functiondef);
if (type == "for") return cont(pushlex("form"), forspec, statement, poplex); if (type == "for") return cont(pushlex("form"), forspec, statement, poplex);
if (type == "variable") return cont(pushlex("stat"), maybelabel); if (type == "class" || (isTS && value == "interface")) { cx.marked = "keyword"; return cont(pushlex("form"), className, poplex); }
if (type == "switch") return cont(pushlex("form"), parenExpr, pushlex("}", "switch"), expect("{"), if (type == "variable") {
block, poplex, poplex); if (isTS && value == "declare") {
cx.marked = "keyword"
return cont(statement)
} else if (isTS && (value == "module" || value == "enum" || value == "type") && cx.stream.match(/^\s*\w/, false)) {
cx.marked = "keyword"
if (value == "enum") return cont(enumdef);
else if (value == "type") return cont(typeexpr, expect("operator"), typeexpr, expect(";"));
else return cont(pushlex("form"), pattern, expect("{"), pushlex("}"), block, poplex, poplex)
} else if (isTS && value == "namespace") {
cx.marked = "keyword"
return cont(pushlex("form"), expression, block, poplex)
} else if (isTS && value == "abstract") {
cx.marked = "keyword"
return cont(statement)
} else {
return cont(pushlex("stat"), maybelabel);
}
}
if (type == "switch") return cont(pushlex("form"), parenExpr, expect("{"), pushlex("}", "switch"), pushblockcontext,
block, poplex, poplex, popcontext);
if (type == "case") return cont(expression, expect(":")); if (type == "case") return cont(expression, expect(":"));
if (type == "default") return cont(expect(":")); if (type == "default") return cont(expect(":"));
if (type == "catch") return cont(pushlex("form"), pushcontext, expect("("), funarg, expect(")"), if (type == "catch") return cont(pushlex("form"), pushcontext, maybeCatchBinding, statement, poplex, popcontext);
statement, poplex, popcontext);
if (type == "class") return cont(pushlex("form"), className, poplex);
if (type == "export") return cont(pushlex("stat"), afterExport, poplex); if (type == "export") return cont(pushlex("stat"), afterExport, poplex);
if (type == "import") return cont(pushlex("stat"), afterImport, poplex); if (type == "import") return cont(pushlex("stat"), afterImport, poplex);
if (type == "module") return cont(pushlex("form"), pattern, pushlex("}"), expect("{"), block, poplex, poplex)
if (type == "type") return cont(typeexpr, expect("operator"), typeexpr, expect(";"));
if (type == "async") return cont(statement) if (type == "async") return cont(statement)
if (value == "@") return cont(expression, statement) if (value == "@") return cont(expression, statement)
return pass(pushlex("stat"), expression, expect(";"), poplex); return pass(pushlex("stat"), expression, expect(";"), poplex);
} }
function expression(type) { function maybeCatchBinding(type) {
return expressionInner(type, false); if (type == "(") return cont(funarg, expect(")"))
}
function expression(type, value) {
return expressionInner(type, value, false);
} }
function expressionNoComma(type) { function expressionNoComma(type, value) {
return expressionInner(type, true); return expressionInner(type, value, true);
} }
function parenExpr(type) { function parenExpr(type) {
if (type != "(") return pass() if (type != "(") return pass()
return cont(pushlex(")"), expression, expect(")"), poplex) return cont(pushlex(")"), expression, expect(")"), poplex)
} }
function expressionInner(type, noComma) { function expressionInner(type, value, noComma) {
if (cx.state.fatArrowAt == cx.stream.start) { if (cx.state.fatArrowAt == cx.stream.start) {
var body = noComma ? arrowBodyNoComma : arrowBody; var body = noComma ? arrowBodyNoComma : arrowBody;
if (type == "(") return cont(pushcontext, pushlex(")"), commasep(pattern, ")"), poplex, expect("=>"), body, popcontext); if (type == "(") return cont(pushcontext, pushlex(")"), commasep(funarg, ")"), poplex, expect("=>"), body, popcontext);
else if (type == "variable") return pass(pushcontext, pattern, expect("=>"), body, popcontext); else if (type == "variable") return pass(pushcontext, pattern, expect("=>"), body, popcontext);
} }
var maybeop = noComma ? maybeoperatorNoComma : maybeoperatorComma; var maybeop = noComma ? maybeoperatorNoComma : maybeoperatorComma;
if (atomicTypes.hasOwnProperty(type)) return cont(maybeop); if (atomicTypes.hasOwnProperty(type)) return cont(maybeop);
if (type == "function") return cont(functiondef, maybeop); if (type == "function") return cont(functiondef, maybeop);
if (type == "class") return cont(pushlex("form"), classExpression, poplex); if (type == "class" || (isTS && value == "interface")) { cx.marked = "keyword"; return cont(pushlex("form"), classExpression, poplex); }
if (type == "keyword c" || type == "async") return cont(noComma ? maybeexpressionNoComma : maybeexpression); if (type == "keyword c" || type == "async") return cont(noComma ? expressionNoComma : expression);
if (type == "(") return cont(pushlex(")"), maybeexpression, expect(")"), poplex, maybeop); if (type == "(") return cont(pushlex(")"), maybeexpression, expect(")"), poplex, maybeop);
if (type == "operator" || type == "spread") return cont(noComma ? expressionNoComma : expression); if (type == "operator" || type == "spread") return cont(noComma ? expressionNoComma : expression);
if (type == "[") return cont(pushlex("]"), arrayLiteral, poplex, maybeop); if (type == "[") return cont(pushlex("]"), arrayLiteral, poplex, maybeop);
if (type == "{") return contCommasep(objprop, "}", null, maybeop); if (type == "{") return contCommasep(objprop, "}", null, maybeop);
if (type == "quasi") return pass(quasi, maybeop); if (type == "quasi") return pass(quasi, maybeop);
if (type == "new") return cont(maybeTarget(noComma)); if (type == "new") return cont(maybeTarget(noComma));
if (type == "import") return cont(expression);
return cont(); return cont();
} }
function maybeexpression(type) { function maybeexpression(type) {
if (type.match(/[;\}\)\],]/)) return pass(); if (type.match(/[;\}\)\],]/)) return pass();
return pass(expression); return pass(expression);
} }
function maybeexpressionNoComma(type) {
if (type.match(/[;\}\)\],]/)) return pass();
return pass(expressionNoComma);
}
function maybeoperatorComma(type, value) { function maybeoperatorComma(type, value) {
if (type == ",") return cont(expression); if (type == ",") return cont(expression);
@ -425,7 +444,9 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
var expr = noComma == false ? expression : expressionNoComma; var expr = noComma == false ? expression : expressionNoComma;
if (type == "=>") return cont(pushcontext, noComma ? arrowBodyNoComma : arrowBody, popcontext); if (type == "=>") return cont(pushcontext, noComma ? arrowBodyNoComma : arrowBody, popcontext);
if (type == "operator") { if (type == "operator") {
if (/\+\+|--/.test(value)) return cont(me); if (/\+\+|--/.test(value) || isTS && value == "!") return cont(me);
if (isTS && value == "<" && cx.stream.match(/^([^>]|<.*?>)*>\s*\(/, false))
return cont(pushlex(">"), commasep(typeexpr, ">"), poplex, me);
if (value == "?") return cont(expression, expect(":"), expr); if (value == "?") return cont(expression, expect(":"), expr);
return cont(expr); return cont(expr);
} }
@ -434,6 +455,12 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
if (type == "(") return contCommasep(expressionNoComma, ")", "call", me); if (type == "(") return contCommasep(expressionNoComma, ")", "call", me);
if (type == ".") return cont(property, me); if (type == ".") return cont(property, me);
if (type == "[") return cont(pushlex("]"), maybeexpression, expect("]"), poplex, me); if (type == "[") return cont(pushlex("]"), maybeexpression, expect("]"), poplex, me);
if (isTS && value == "as") { cx.marked = "keyword"; return cont(typeexpr, me) }
if (type == "regexp") {
cx.state.lastType = cx.marked = "operator"
cx.stream.backUp(cx.stream.pos - cx.stream.start - 1)
return cont(expr)
}
} }
function quasi(type, value) { function quasi(type, value) {
if (type != "quasi") return pass(); if (type != "quasi") return pass();
@ -458,6 +485,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
function maybeTarget(noComma) { function maybeTarget(noComma) {
return function(type) { return function(type) {
if (type == ".") return cont(noComma ? targetNoComma : target); if (type == ".") return cont(noComma ? targetNoComma : target);
else if (type == "variable" && isTS) return cont(maybeTypeArgs, noComma ? maybeoperatorNoComma : maybeoperatorComma)
else return pass(noComma ? expressionNoComma : expression); else return pass(noComma ? expressionNoComma : expression);
}; };
} }
@ -481,18 +509,25 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
} else if (type == "variable" || cx.style == "keyword") { } else if (type == "variable" || cx.style == "keyword") {
cx.marked = "property"; cx.marked = "property";
if (value == "get" || value == "set") return cont(getterSetter); if (value == "get" || value == "set") return cont(getterSetter);
var m // Work around fat-arrow-detection complication for detecting typescript typed arrow params
if (isTS && cx.state.fatArrowAt == cx.stream.start && (m = cx.stream.match(/^\s*:\s*/, false)))
cx.state.fatArrowAt = cx.stream.pos + m[0].length
return cont(afterprop); return cont(afterprop);
} else if (type == "number" || type == "string") { } else if (type == "number" || type == "string") {
cx.marked = jsonldMode ? "property" : (cx.style + " property"); cx.marked = jsonldMode ? "property" : (cx.style + " property");
return cont(afterprop); return cont(afterprop);
} else if (type == "jsonld-keyword") { } else if (type == "jsonld-keyword") {
return cont(afterprop); return cont(afterprop);
} else if (type == "modifier") { } else if (isTS && isModifier(value)) {
cx.marked = "keyword"
return cont(objprop) return cont(objprop)
} else if (type == "[") { } else if (type == "[") {
return cont(expression, expect("]"), afterprop); return cont(expression, maybetype, expect("]"), afterprop);
} else if (type == "spread") { } else if (type == "spread") {
return cont(expression); return cont(expressionNoComma, afterprop);
} else if (value == "*") {
cx.marked = "keyword";
return cont(objprop);
} else if (type == ":") { } else if (type == ":") {
return pass(afterprop) return pass(afterprop)
} }
@ -539,11 +574,32 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
if (value == "?") return cont(maybetype); if (value == "?") return cont(maybetype);
} }
} }
function typeexpr(type) { function mayberettype(type) {
if (type == "variable") {cx.marked = "variable-3"; return cont(afterType);} if (isTS && type == ":") {
if (cx.stream.match(/^\s*\w+\s+is\b/, false)) return cont(expression, isKW, typeexpr)
else return cont(typeexpr)
}
}
function isKW(_, value) {
if (value == "is") {
cx.marked = "keyword"
return cont()
}
}
function typeexpr(type, value) {
if (value == "keyof" || value == "typeof") {
cx.marked = "keyword"
return cont(value == "keyof" ? typeexpr : expressionNoComma)
}
if (type == "variable" || value == "void") {
cx.marked = "type"
return cont(afterType)
}
if (type == "string" || type == "number" || type == "atom") return cont(afterType); if (type == "string" || type == "number" || type == "atom") return cont(afterType);
if (type == "{") return cont(pushlex("}"), commasep(typeprop, "}", ",;"), poplex) if (type == "[") return cont(pushlex("]"), commasep(typeexpr, "]", ","), poplex, afterType)
if (type == "{") return cont(pushlex("}"), commasep(typeprop, "}", ",;"), poplex, afterType)
if (type == "(") return cont(commasep(typearg, ")"), maybeReturnType) if (type == "(") return cont(commasep(typearg, ")"), maybeReturnType)
if (type == "<") return cont(commasep(typeexpr, ">"), typeexpr)
} }
function maybeReturnType(type) { function maybeReturnType(type) {
if (type == "=>") return cont(typeexpr) if (type == "=>") return cont(typeexpr)
@ -556,25 +612,39 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
return cont(typeprop) return cont(typeprop)
} else if (type == ":") { } else if (type == ":") {
return cont(typeexpr) return cont(typeexpr)
} else if (type == "[") {
return cont(expression, maybetype, expect("]"), typeprop)
} }
} }
function typearg(type) { function typearg(type, value) {
if (type == "variable") return cont(typearg) if (type == "variable" && cx.stream.match(/^\s*[?:]/, false) || value == "?") return cont(typearg)
else if (type == ":") return cont(typeexpr) if (type == ":") return cont(typeexpr)
return pass(typeexpr)
} }
function afterType(type, value) { function afterType(type, value) {
if (value == "<") return cont(pushlex(">"), commasep(typeexpr, ">"), poplex, afterType) if (value == "<") return cont(pushlex(">"), commasep(typeexpr, ">"), poplex, afterType)
if (value == "|" || type == ".") return cont(typeexpr) if (value == "|" || type == "." || value == "&") return cont(typeexpr)
if (type == "[") return cont(expect("]"), afterType) if (type == "[") return cont(expect("]"), afterType)
if (value == "extends" || value == "implements") { cx.marked = "keyword"; return cont(typeexpr) }
}
function maybeTypeArgs(_, value) {
if (value == "<") return cont(pushlex(">"), commasep(typeexpr, ">"), poplex, afterType)
} }
function vardef() { function typeparam() {
return pass(typeexpr, maybeTypeDefault)
}
function maybeTypeDefault(_, value) {
if (value == "=") return cont(typeexpr)
}
function vardef(_, value) {
if (value == "enum") {cx.marked = "keyword"; return cont(enumdef)}
return pass(pattern, maybetype, maybeAssign, vardefCont); return pass(pattern, maybetype, maybeAssign, vardefCont);
} }
function pattern(type, value) { function pattern(type, value) {
if (type == "modifier") return cont(pattern) if (isTS && isModifier(value)) { cx.marked = "keyword"; return cont(pattern) }
if (type == "variable") { register(value); return cont(); } if (type == "variable") { register(value); return cont(); }
if (type == "spread") return cont(pattern); if (type == "spread") return cont(pattern);
if (type == "[") return contCommasep(pattern, "]"); if (type == "[") return contCommasep(eltpattern, "]");
if (type == "{") return contCommasep(proppattern, "}"); if (type == "{") return contCommasep(proppattern, "}");
} }
function proppattern(type, value) { function proppattern(type, value) {
@ -587,6 +657,9 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
if (type == "}") return pass(); if (type == "}") return pass();
return cont(expect(":"), pattern, maybeAssign); return cont(expect(":"), pattern, maybeAssign);
} }
function eltpattern() {
return pass(pattern, maybeAssign)
}
function maybeAssign(_type, value) { function maybeAssign(_type, value) {
if (value == "=") return cont(expressionNoComma); if (value == "=") return cont(expressionNoComma);
} }
@ -596,7 +669,8 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
function maybeelse(type, value) { function maybeelse(type, value) {
if (type == "keyword b" && value == "else") return cont(pushlex("form", "else"), statement, poplex); if (type == "keyword b" && value == "else") return cont(pushlex("form", "else"), statement, poplex);
} }
function forspec(type) { function forspec(type, value) {
if (value == "await") return cont(forspec);
if (type == "(") return cont(pushlex(")"), forspec1, expect(")"), poplex); if (type == "(") return cont(pushlex(")"), forspec1, expect(")"), poplex);
} }
function forspec1(type) { function forspec1(type) {
@ -620,11 +694,13 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
function functiondef(type, value) { function functiondef(type, value) {
if (value == "*") {cx.marked = "keyword"; return cont(functiondef);} if (value == "*") {cx.marked = "keyword"; return cont(functiondef);}
if (type == "variable") {register(value); return cont(functiondef);} if (type == "variable") {register(value); return cont(functiondef);}
if (type == "(") return cont(pushcontext, pushlex(")"), commasep(funarg, ")"), poplex, maybetype, statement, popcontext); if (type == "(") return cont(pushcontext, pushlex(")"), commasep(funarg, ")"), poplex, mayberettype, statement, popcontext);
if (isTS && value == "<") return cont(pushlex(">"), commasep(typeexpr, ">"), poplex, functiondef) if (isTS && value == "<") return cont(pushlex(">"), commasep(typeparam, ">"), poplex, functiondef)
} }
function funarg(type) { function funarg(type, value) {
if (value == "@") cont(expression, funarg)
if (type == "spread") return cont(funarg); if (type == "spread") return cont(funarg);
if (isTS && isModifier(value)) { cx.marked = "keyword"; return cont(funarg); }
return pass(pattern, maybetype, maybeAssign); return pass(pattern, maybetype, maybeAssign);
} }
function classExpression(type, value) { function classExpression(type, value) {
@ -636,24 +712,27 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
if (type == "variable") {register(value); return cont(classNameAfter);} if (type == "variable") {register(value); return cont(classNameAfter);}
} }
function classNameAfter(type, value) { function classNameAfter(type, value) {
if (value == "<") return cont(pushlex(">"), commasep(typeexpr, ">"), poplex, classNameAfter) if (value == "<") return cont(pushlex(">"), commasep(typeparam, ">"), poplex, classNameAfter)
if (value == "extends" || value == "implements" || (isTS && type == ",")) if (value == "extends" || value == "implements" || (isTS && type == ",")) {
if (value == "implements") cx.marked = "keyword";
return cont(isTS ? typeexpr : expression, classNameAfter); return cont(isTS ? typeexpr : expression, classNameAfter);
}
if (type == "{") return cont(pushlex("}"), classBody, poplex); if (type == "{") return cont(pushlex("}"), classBody, poplex);
} }
function classBody(type, value) { function classBody(type, value) {
if (type == "async" ||
(type == "variable" &&
(value == "static" || value == "get" || value == "set" || (isTS && isModifier(value))) &&
cx.stream.match(/^\s+[\w$\xa1-\uffff]/, false))) {
cx.marked = "keyword";
return cont(classBody);
}
if (type == "variable" || cx.style == "keyword") { if (type == "variable" || cx.style == "keyword") {
if ((value == "async" || value == "static" || value == "get" || value == "set" ||
(isTS && (value == "public" || value == "private" || value == "protected" || value == "readonly" || value == "abstract"))) &&
cx.stream.match(/^\s+[\w$\xa1-\uffff]/, false)) {
cx.marked = "keyword";
return cont(classBody);
}
cx.marked = "property"; cx.marked = "property";
return cont(isTS ? classfield : functiondef, classBody); return cont(isTS ? classfield : functiondef, classBody);
} }
if (type == "[") if (type == "[")
return cont(expression, expect("]"), isTS ? classfield : functiondef, classBody) return cont(expression, maybetype, expect("]"), isTS ? classfield : functiondef, classBody)
if (value == "*") { if (value == "*") {
cx.marked = "keyword"; cx.marked = "keyword";
return cont(classBody); return cont(classBody);
@ -680,6 +759,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
} }
function afterImport(type) { function afterImport(type) {
if (type == "string") return cont(); if (type == "string") return cont();
if (type == "(") return pass(expression);
return pass(importSpec, maybeMoreImports, maybeFrom); return pass(importSpec, maybeMoreImports, maybeFrom);
} }
function importSpec(type, value) { function importSpec(type, value) {
@ -701,6 +781,12 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
if (type == "]") return cont(); if (type == "]") return cont();
return pass(commasep(expressionNoComma, "]")); return pass(commasep(expressionNoComma, "]"));
} }
function enumdef() {
return pass(pushlex("form"), pattern, expect("{"), pushlex("}"), commasep(enummember, "}"), poplex, poplex)
}
function enummember() {
return pass(pattern, maybeAssign);
}
function isContinuedStatement(state, textAfter) { function isContinuedStatement(state, textAfter) {
return state.lastType == "operator" || state.lastType == "," || return state.lastType == "operator" || state.lastType == "," ||
@ -708,6 +794,12 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
/[,.]/.test(textAfter.charAt(0)); /[,.]/.test(textAfter.charAt(0));
} }
function expressionAllowed(stream, state, backUp) {
return state.tokenize == tokenBase &&
/^(?:operator|sof|keyword [bcd]|case|new|export|default|spread|[\[{}\(,;:]|=>)$/.test(state.lastType) ||
(state.lastType == "quasi" && /\{\s*$/.test(stream.string.slice(0, stream.pos - (backUp || 0))))
}
// Interface // Interface
return { return {
@ -718,7 +810,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
cc: [], cc: [],
lexical: new JSLexical((basecolumn || 0) - indentUnit, 0, "block", false), lexical: new JSLexical((basecolumn || 0) - indentUnit, 0, "block", false),
localVars: parserConfig.localVars, localVars: parserConfig.localVars,
context: parserConfig.localVars && {vars: parserConfig.localVars}, context: parserConfig.localVars && new Context(null, null, false),
indented: basecolumn || 0 indented: basecolumn || 0
}; };
if (parserConfig.globalVars && typeof parserConfig.globalVars == "object") if (parserConfig.globalVars && typeof parserConfig.globalVars == "object")
@ -759,7 +851,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
lexical = lexical.prev; lexical = lexical.prev;
var type = lexical.type, closing = firstChar == type; var type = lexical.type, closing = firstChar == type;
if (type == "vardef") return lexical.indented + (state.lastType == "operator" || state.lastType == "," ? lexical.info + 1 : 0); if (type == "vardef") return lexical.indented + (state.lastType == "operator" || state.lastType == "," ? lexical.info.length + 1 : 0);
else if (type == "form" && firstChar == "{") return lexical.indented; else if (type == "form" && firstChar == "{") return lexical.indented;
else if (type == "form") return lexical.indented + indentUnit; else if (type == "form") return lexical.indented + indentUnit;
else if (type == "stat") else if (type == "stat")
@ -773,6 +865,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
electricInput: /^\s*(?:case .*?:|default:|\{|\})$/, electricInput: /^\s*(?:case .*?:|default:|\{|\})$/,
blockCommentStart: jsonMode ? null : "/*", blockCommentStart: jsonMode ? null : "/*",
blockCommentEnd: jsonMode ? null : "*/", blockCommentEnd: jsonMode ? null : "*/",
blockCommentContinue: jsonMode ? null : " * ",
lineComment: jsonMode ? null : "//", lineComment: jsonMode ? null : "//",
fold: "brace", fold: "brace",
closeBrackets: "()[]{}''\"\"``", closeBrackets: "()[]{}''\"\"``",
@ -782,6 +875,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
jsonMode: jsonMode, jsonMode: jsonMode,
expressionAllowed: expressionAllowed, expressionAllowed: expressionAllowed,
skipExpression: function(state) { skipExpression: function(state) {
var top = state.cc[state.cc.length - 1] var top = state.cc[state.cc.length - 1]
if (top == expression || top == expressionNoComma) state.cc.pop() if (top == expression || top == expressionNoComma) state.cc.pop()

@ -1,5 +1,5 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others // CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE // Distributed under an MIT license: https://codemirror.net/LICENSE
(function(mod) { (function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS if (typeof exports == "object" && typeof module == "object") // CommonJS
@ -151,7 +151,7 @@
}; };
CodeMirror.defineMode("php", function(config, parserConfig) { CodeMirror.defineMode("php", function(config, parserConfig) {
var htmlMode = CodeMirror.getMode(config, "text/html"); var htmlMode = CodeMirror.getMode(config, (parserConfig && parserConfig.htmlMode) || "text/html");
var phpMode = CodeMirror.getMode(config, phpConfig); var phpMode = CodeMirror.getMode(config, phpConfig);
function dispatch(stream, state) { function dispatch(stream, state) {

@ -1,5 +1,5 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others // CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE // Distributed under an MIT license: https://codemirror.net/LICENSE
(function(mod) { (function(mod) {
'use strict'; 'use strict';

@ -1,5 +1,5 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others // CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE // Distributed under an MIT license: https://codemirror.net/LICENSE
(function(mod) { (function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS if (typeof exports == "object" && typeof module == "object") // CommonJS
@ -41,10 +41,11 @@
CodeMirror.defineMode("python", function(conf, parserConf) { CodeMirror.defineMode("python", function(conf, parserConf) {
var ERRORCLASS = "error"; var ERRORCLASS = "error";
var singleDelimiters = parserConf.singleDelimiters || /^[\(\)\[\]\{\}@,:`=;\.]/; var delimiters = parserConf.delimiters || parserConf.singleDelimiters || /^[\(\)\[\]\{\}@,:`=;\.\\]/;
var doubleOperators = parserConf.doubleOperators || /^([!<>]==|<>|<<|>>|\/\/|\*\*)/; // (Backwards-compatiblity with old, cumbersome config system)
var doubleDelimiters = parserConf.doubleDelimiters || /^(\+=|\-=|\*=|%=|\/=|&=|\|=|\^=)/; var operators = [parserConf.singleOperators, parserConf.doubleOperators, parserConf.doubleDelimiters, parserConf.tripleDelimiters,
var tripleDelimiters = parserConf.tripleDelimiters || /^(\/\/=|>>=|<<=|\*\*=)/; parserConf.operators || /^([-+*/%\/&|^]=?|[<>=]+|\/\/=?|\*\*=?|!=|[~!@])/]
for (var i = 0; i < operators.length; i++) if (!operators[i]) operators.splice(i--, 1)
var hangingIndent = parserConf.hangingIndent || conf.indentUnit; var hangingIndent = parserConf.hangingIndent || conf.indentUnit;
@ -58,13 +59,11 @@
var py3 = !(parserConf.version && Number(parserConf.version) < 3) var py3 = !(parserConf.version && Number(parserConf.version) < 3)
if (py3) { if (py3) {
// since http://legacy.python.org/dev/peps/pep-0465/ @ is also an operator // since http://legacy.python.org/dev/peps/pep-0465/ @ is also an operator
var singleOperators = parserConf.singleOperators || /^[\+\-\*\/%&|\^~<>!@]/;
var identifiers = parserConf.identifiers|| /^[_A-Za-z\u00A1-\uFFFF][_A-Za-z0-9\u00A1-\uFFFF]*/; var identifiers = parserConf.identifiers|| /^[_A-Za-z\u00A1-\uFFFF][_A-Za-z0-9\u00A1-\uFFFF]*/;
myKeywords = myKeywords.concat(["nonlocal", "False", "True", "None", "async", "await"]); myKeywords = myKeywords.concat(["nonlocal", "False", "True", "None", "async", "await"]);
myBuiltins = myBuiltins.concat(["ascii", "bytes", "exec", "print"]); myBuiltins = myBuiltins.concat(["ascii", "bytes", "exec", "print"]);
var stringPrefixes = new RegExp("^(([rbuf]|(br))?('{3}|\"{3}|['\"]))", "i"); var stringPrefixes = new RegExp("^(([rbuf]|(br)|(fr))?('{3}|\"{3}|['\"]))", "i");
} else { } else {
var singleOperators = parserConf.singleOperators || /^[\+\-\*\/%&|\^~<>!]/;
var identifiers = parserConf.identifiers|| /^[_A-Za-z][_A-Za-z0-9]*/; var identifiers = parserConf.identifiers|| /^[_A-Za-z][_A-Za-z0-9]*/;
myKeywords = myKeywords.concat(["exec", "print"]); myKeywords = myKeywords.concat(["exec", "print"]);
myBuiltins = myBuiltins.concat(["apply", "basestring", "buffer", "cmp", "coerce", "execfile", myBuiltins = myBuiltins.concat(["apply", "basestring", "buffer", "cmp", "coerce", "execfile",
@ -77,9 +76,10 @@
// tokenizers // tokenizers
function tokenBase(stream, state) { function tokenBase(stream, state) {
if (stream.sol()) state.indent = stream.indentation() var sol = stream.sol() && state.lastToken != "\\"
if (sol) state.indent = stream.indentation()
// Handle scope changes // Handle scope changes
if (stream.sol() && top(state).type == "py") { if (sol && top(state).type == "py") {
var scopeOffset = top(state).offset; var scopeOffset = top(state).offset;
if (stream.eatSpace()) { if (stream.eatSpace()) {
var lineOffset = stream.indentation(); var lineOffset = stream.indentation();
@ -101,13 +101,8 @@
function tokenBaseInner(stream, state) { function tokenBaseInner(stream, state) {
if (stream.eatSpace()) return null; if (stream.eatSpace()) return null;
var ch = stream.peek();
// Handle Comments // Handle Comments
if (ch == "#") { if (stream.match(/^#.*/)) return "comment";
stream.skipToEnd();
return "comment";
}
// Handle Number Literals // Handle Number Literals
if (stream.match(/^[0-9\.]/, false)) { if (stream.match(/^[0-9\.]/, false)) {
@ -147,19 +142,20 @@
// Handle Strings // Handle Strings
if (stream.match(stringPrefixes)) { if (stream.match(stringPrefixes)) {
state.tokenize = tokenStringFactory(stream.current()); var isFmtString = stream.current().toLowerCase().indexOf('f') !== -1;
return state.tokenize(stream, state); if (!isFmtString) {
state.tokenize = tokenStringFactory(stream.current());
return state.tokenize(stream, state);
} else {
state.tokenize = formatStringFactory(stream.current(), state.tokenize);
return state.tokenize(stream, state);
}
} }
// Handle operators and Delimiters for (var i = 0; i < operators.length; i++)
if (stream.match(tripleDelimiters) || stream.match(doubleDelimiters)) if (stream.match(operators[i])) return "operator"
return "punctuation";
if (stream.match(doubleOperators) || stream.match(singleOperators))
return "operator";
if (stream.match(singleDelimiters)) if (stream.match(delimiters)) return "punctuation";
return "punctuation";
if (state.lastToken == "." && stream.match(identifiers)) if (state.lastToken == "." && stream.match(identifiers))
return "property"; return "property";
@ -184,6 +180,77 @@
return ERRORCLASS; return ERRORCLASS;
} }
function formatStringFactory(delimiter, tokenOuter) {
while ("rubf".indexOf(delimiter.charAt(0).toLowerCase()) >= 0)
delimiter = delimiter.substr(1);
var singleline = delimiter.length == 1;
var OUTCLASS = "string";
function tokenFString(stream, state) {
// inside f-str Expression
if (stream.match(delimiter)) {
// expression ends pre-maturally, but very common in editing
// Could show error to remind users to close brace here
state.tokenize = tokenString
return OUTCLASS;
} else if (stream.match('{')) {
// starting brace, if not eaten below
return "punctuation";
} else if (stream.match('}')) {
// return to regular inside string state
state.tokenize = tokenString
return "punctuation";
} else {
// use tokenBaseInner to parse the expression
return tokenBaseInner(stream, state);
}
}
function tokenString(stream, state) {
while (!stream.eol()) {
stream.eatWhile(/[^'"\{\}\\]/);
if (stream.eat("\\")) {
stream.next();
if (singleline && stream.eol())
return OUTCLASS;
} else if (stream.match(delimiter)) {
state.tokenize = tokenOuter;
return OUTCLASS;
} else if (stream.match('{{')) {
// ignore {{ in f-str
return OUTCLASS;
} else if (stream.match('{', false)) {
// switch to nested mode
state.tokenize = tokenFString
if (stream.current()) {
return OUTCLASS;
} else {
// need to return something, so eat the starting {
stream.next();
return "punctuation";
}
} else if (stream.match('}}')) {
return OUTCLASS;
} else if (stream.match('}')) {
// single } in f-string is an error
return ERRORCLASS;
} else {
stream.eat(/['"]/);
}
}
if (singleline) {
if (parserConf.singleLineStringErrors)
return ERRORCLASS;
else
state.tokenize = tokenOuter;
}
return OUTCLASS;
}
tokenString.isString = true;
return tokenString;
}
function tokenStringFactory(delimiter) { function tokenStringFactory(delimiter) {
while ("rubf".indexOf(delimiter.charAt(0).toLowerCase()) >= 0) while ("rubf".indexOf(delimiter.charAt(0).toLowerCase()) >= 0)
delimiter = delimiter.substr(1); delimiter = delimiter.substr(1);
@ -264,14 +331,16 @@
if (current == ":" && !state.lambda && top(state).type == "py") if (current == ":" && !state.lambda && top(state).type == "py")
pushPyScope(state); pushPyScope(state);
var delimiter_index = current.length == 1 ? "[({".indexOf(current) : -1; if (current.length == 1 && !/string|comment/.test(style)) {
if (delimiter_index != -1) var delimiter_index = "[({".indexOf(current);
pushBracketScope(stream, state, "])}".slice(delimiter_index, delimiter_index+1)); if (delimiter_index != -1)
pushBracketScope(stream, state, "])}".slice(delimiter_index, delimiter_index+1));
delimiter_index = "])}".indexOf(current); delimiter_index = "])}".indexOf(current);
if (delimiter_index != -1) { if (delimiter_index != -1) {
if (top(state).type == current) state.indent = state.scopes.pop().offset - hangingIndent if (top(state).type == current) state.indent = state.scopes.pop().offset - hangingIndent
else return ERRORCLASS; else return ERRORCLASS;
}
} }
if (state.dedent > 0 && stream.eol() && top(state).type == "py") { if (state.dedent > 0 && stream.eol() && top(state).type == "py") {
if (state.scopes.length > 1) state.scopes.pop(); if (state.scopes.length > 1) state.scopes.pop();
@ -332,8 +401,8 @@
CodeMirror.defineMIME("text/x-cython", { CodeMirror.defineMIME("text/x-cython", {
name: "python", name: "python",
extra_keywords: words("by cdef cimport cpdef ctypedef enum except"+ extra_keywords: words("by cdef cimport cpdef ctypedef enum except "+
"extern gil include nogil property public"+ "extern gil include nogil property public "+
"readonly struct union DEF IF ELIF ELSE") "readonly struct union DEF IF ELIF ELSE")
}); });

@ -1,5 +1,5 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others // CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE // Distributed under an MIT license: https://codemirror.net/LICENSE
(function(mod) { (function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS if (typeof exports == "object" && typeof module == "object") // CommonJS
@ -14,26 +14,27 @@
CodeMirror.defineMode('shell', function() { CodeMirror.defineMode('shell', function() {
var words = {}; var words = {};
function define(style, string) { function define(style, dict) {
var split = string.split(' '); for(var i = 0; i < dict.length; i++) {
for(var i = 0; i < split.length; i++) { words[dict[i]] = style;
words[split[i]] = style;
} }
}; };
// Atoms var commonAtoms = ["true", "false"];
define('atom', 'true false'); var commonKeywords = ["if", "then", "do", "else", "elif", "while", "until", "for", "in", "esac", "fi",
"fin", "fil", "done", "exit", "set", "unset", "export", "function"];
var commonCommands = ["ab", "awk", "bash", "beep", "cat", "cc", "cd", "chown", "chmod", "chroot", "clear",
"cp", "curl", "cut", "diff", "echo", "find", "gawk", "gcc", "get", "git", "grep", "hg", "kill", "killall",
"ln", "ls", "make", "mkdir", "openssl", "mv", "nc", "nl", "node", "npm", "ping", "ps", "restart", "rm",
"rmdir", "sed", "service", "sh", "shopt", "shred", "source", "sort", "sleep", "ssh", "start", "stop",
"su", "sudo", "svn", "tee", "telnet", "top", "touch", "vi", "vim", "wall", "wc", "wget", "who", "write",
"yes", "zsh"];
// Keywords CodeMirror.registerHelper("hintWords", "shell", commonAtoms.concat(commonKeywords, commonCommands));
define('keyword', 'if then do else elif while until for in esac fi fin ' +
'fil done exit set unset export function');
// Commands define('atom', commonAtoms);
define('builtin', 'ab awk bash beep cat cc cd chown chmod chroot clear cp ' + define('keyword', commonKeywords);
'curl cut diff echo find gawk gcc get git grep kill killall ln ls make ' + define('builtin', commonCommands);
'mkdir openssl mv nc node npm ping ps restart rm rmdir sed service sh ' +
'shopt shred source sort sleep ssh start stop su sudo tee telnet top ' +
'touch vi vim wall wc wget who write yes zsh');
function tokenBase(stream, state) { function tokenBase(stream, state) {
if (stream.eatSpace()) return null; if (stream.eatSpace()) return null;
@ -84,29 +85,38 @@ CodeMirror.defineMode('shell', function() {
function tokenString(quote, style) { function tokenString(quote, style) {
var close = quote == "(" ? ")" : quote == "{" ? "}" : quote var close = quote == "(" ? ")" : quote == "{" ? "}" : quote
return function(stream, state) { return function(stream, state) {
var next, end = false, escaped = false; var next, escaped = false;
while ((next = stream.next()) != null) { while ((next = stream.next()) != null) {
if (next === close && !escaped) { if (next === close && !escaped) {
end = true; state.tokens.shift();
break; break;
} } else if (next === '$' && !escaped && quote !== "'" && stream.peek() != close) {
if (next === '$' && !escaped && quote !== "'") {
escaped = true; escaped = true;
stream.backUp(1); stream.backUp(1);
state.tokens.unshift(tokenDollar); state.tokens.unshift(tokenDollar);
break; break;
} } else if (!escaped && quote !== close && next === quote) {
if (!escaped && next === quote && quote !== close) {
state.tokens.unshift(tokenString(quote, style)) state.tokens.unshift(tokenString(quote, style))
return tokenize(stream, state) return tokenize(stream, state)
} else if (!escaped && /['"]/.test(next) && !/['"]/.test(quote)) {
state.tokens.unshift(tokenStringStart(next, "string"));
stream.backUp(1);
break;
} }
escaped = !escaped && next === '\\'; escaped = !escaped && next === '\\';
} }
if (end || !escaped) state.tokens.shift();
return style; return style;
}; };
}; };
function tokenStringStart(quote, style) {
return function(stream, state) {
state.tokens[0] = tokenString(quote, style)
stream.next()
return tokenize(stream, state)
}
}
var tokenDollar = function(stream, state) { var tokenDollar = function(stream, state) {
if (state.tokens.length > 1) stream.eat('$'); if (state.tokens.length > 1) stream.eat('$');
var ch = stream.next() var ch = stream.next()
@ -135,5 +145,8 @@ CodeMirror.defineMode('shell', function() {
}); });
CodeMirror.defineMIME('text/x-sh', 'shell'); CodeMirror.defineMIME('text/x-sh', 'shell');
// Apache uses a slightly different Media Type for Shell scripts
// http://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types
CodeMirror.defineMIME('application/x-sh', 'shell');
}); });

File diff suppressed because one or more lines are too long
Loading…
Cancel
Save