7 changes: 5 additions & 2 deletions addon/search/search.js
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,10 @@
persistentDialog(cm, queryDialog, q, function(query, event) {
CodeMirror.e_stop(event);
if (!query) return;
if (query != state.queryText) startSearch(cm, state, query);
if (query != state.queryText) {
startSearch(cm, state, query);
state.posFrom = state.posTo = cm.getCursor();
}
if (hiding) hiding.style.opacity = 1
findNext(cm, event.shiftKey, function(_, to) {
var dialog
Expand Down Expand Up @@ -193,7 +196,7 @@
replaceAll(cm, query, text)
} else {
clearSearch(cm);
var cursor = getSearchCursor(cm, query, cm.getCursor());
var cursor = getSearchCursor(cm, query, cm.getCursor("from"));
var advance = function() {
var start = cursor.from(), match;
if (!(match = cursor.findNext())) {
Expand Down
4 changes: 2 additions & 2 deletions addon/tern/tern.js
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@
var data = findDoc(ts, doc);

var argHints = ts.cachedArgHints;
if (argHints && argHints.doc == doc && cmpPos(argHints.start, change.to) <= 0)
if (argHints && argHints.doc == doc && cmpPos(argHints.start, change.to) >= 0)
ts.cachedArgHints = null;

var changed = data.changed;
Expand Down Expand Up @@ -306,7 +306,7 @@
ts.request(cm, {type: "type", preferFunction: true, end: start}, function(error, data) {
if (error || !data.type || !(/^fn\(/).test(data.type)) return;
ts.cachedArgHints = {
start: pos,
start: start,
type: parseFnType(data.type),
name: data.exprName || data.name || "fn",
guess: data.guess,
Expand Down
4 changes: 2 additions & 2 deletions bin/compress
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
// Script files are specified without .js ending. Prefixing them with
// their full (local) path is optional. So you may say lib/codemirror
// or mode/xml/xml to be more precise. In fact, even the .js suffix
// may be speficied, if wanted.
// may be specified, if wanted.

"use strict";

Expand Down Expand Up @@ -68,7 +68,7 @@ walk("mode/");
if (!local && !blob) help(false);

if (files.length) {
console.log("Some speficied files were not found: " +
console.log("Some specified files were not found: " +
files.map(function(a){return a.name;}).join(", "));
process.exit(1);
}
Expand Down
63 changes: 55 additions & 8 deletions demo/complete.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
<script src="../addon/hint/show-hint.js"></script>
<script src="../addon/hint/javascript-hint.js"></script>
<script src="../mode/javascript/javascript.js"></script>
<script src="../mode/markdown/markdown.js"></script>

<div id=nav>
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
Expand Down Expand Up @@ -69,11 +70,57 @@ <h2>Autocomplete Demo</h2>
and <a href="../doc/manual.html#addon_javascript-hint"><code>javascript-hint</code></a>
addons.</p>

<script>
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
lineNumbers: true,
extraKeys: {"Ctrl-Space": "autocomplete"},
mode: {name: "javascript", globalVars: true}
});
</script>
</article>
<form><textarea style="display: none" id="synonyms" name="synonyms">
Here, the completion use an asynchronous hinting functions to provide
synonyms for each words. If your browser support `Promises`, the
hinting function can also return one.
</textarea></form>

<script>
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
lineNumbers: true,
extraKeys: {"Ctrl-Space": "autocomplete"},
mode: {name: "javascript", globalVars: true}
});

if (typeof Promise !== undefined) {
var comp = [
["here", "hither"],
["asynchronous", "nonsynchronous"],
["completion", "achievement", "conclusion", "culmination", "expirations"],
["hinting", "advive", "broach", "imply"],
["function","action"],
["provide", "add", "bring", "give"],
["synonyms", "equivalents"],
["words", "token"],
["each", "every"],
]

function synonyms(cm, option) {
return new Promise(function(accept) {
setTimeout(function() {
var cursor = cm.getCursor(), line = cm.getLine(cursor.line)
var start = cursor.ch, end = cursor.ch
while (start && /\w/.test(line.charAt(start - 1))) --start
while (end < line.length && /\w/.test(line.charAt(end))) ++end
var word = line.slice(start, end).toLowerCase()
for (var i = 0; i < comp.length; i++) if (comp[i].indexOf(word) != -1)
return accept({list: comp[i],
from: CodeMirror.Pos(cursor.line, start),
to: CodeMirror.Pos(cursor.line, end)})
return accept(null)
}, 100)
})
}

var editor2 = CodeMirror.fromTextArea(document.getElementById("synonyms"), {
extraKeys: {"Ctrl-Space": "autocomplete"},
lineNumbers: true,
lineWrapping: true,
mode: "text/x-markdown",
hintOptions: {hint: synonyms}
})
}
</script>

</article>
4 changes: 4 additions & 0 deletions doc/compress.html
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ <h2>Script compression helper</h2>
<input type="hidden" id="download" name="download" value="codemirror-compressed.js"/>
<p>Version: <select id="version" onchange="setVersion(this);" style="padding: 1px;">
<option value="http://codemirror.net/">HEAD</option>
<option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=5.14.0;f=">5.14</option>
<option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=5.13.2;f=">5.13</option>
<option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=5.13.0;f=">5.13</option>
<option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=5.12.0;f=">5.12</option>
Expand Down Expand Up @@ -168,6 +169,7 @@ <h2>Script compression helper</h2>
<option value="http://codemirror.net/mode/lua/lua.js">lua.js</option>
<option value="http://codemirror.net/mode/markdown/markdown.js">markdown.js</option>
<option value="http://codemirror.net/mode/mathematica/mathematica.js">mathematica.js</option>
<option value="http://codemirror.net/mode/mbox/mbox.js">mbox.js</option>
<option value="http://codemirror.net/mode/mirc/mirc.js">mirc.js</option>
<option value="http://codemirror.net/mode/mllike/mllike.js">mllike.js</option>
<option value="http://codemirror.net/mode/modelica/modelica.js">modelica.js</option>
Expand All @@ -182,6 +184,7 @@ <h2>Script compression helper</h2>
<option value="http://codemirror.net/mode/perl/perl.js">perl.js</option>
<option value="http://codemirror.net/mode/php/php.js">php.js</option>
<option value="http://codemirror.net/mode/pig/pig.js">pig.js</option>
<option value="http://codemirror.net/mode/powershell/powershell.js">powershell.js</option>
<option value="http://codemirror.net/mode/properties/properties.js">properties.js</option>
<option value="http://codemirror.net/mode/protobuf/protobuf.js">protobuf.js</option>
<option value="http://codemirror.net/mode/python/python.js">python.js</option>
Expand Down Expand Up @@ -225,6 +228,7 @@ <h2>Script compression helper</h2>
<option value="http://codemirror.net/mode/verilog/verilog.js">verilog.js</option>
<option value="http://codemirror.net/mode/vhdl/vhdl.js">vhdl.js</option>
<option value="http://codemirror.net/mode/vue/vue.js">vue.js</option>
<option value="http://codemirror.net/mode/webidl/webidl.js">webidl.js</option>
<option value="http://codemirror.net/mode/xml/xml.js">xml.js</option>
<option value="http://codemirror.net/mode/xquery/xquery.js">xquery.js</option>
<option value="http://codemirror.net/mode/yaml/yaml.js">yaml.js</option>
Expand Down
64 changes: 36 additions & 28 deletions doc/manual.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<!doctype html>
<!doctype html>

<title>CodeMirror: User Manual</title>
<meta charset="utf-8"/>
Expand Down Expand Up @@ -69,7 +69,7 @@
<section class=first id=overview>
<h2 style="position: relative">
User manual and reference guide
<span style="color: #888; font-size: 1rem; position: absolute; right: 0; bottom: 0">version 5.13.3</span>
<span style="color: #888; font-size: 1rem; position: absolute; right: 0; bottom: 0">version 5.14.0</span>
</h2>

<p>CodeMirror is a code-editor component that can be embedded in
Expand Down Expand Up @@ -1254,7 +1254,7 @@ <h3 id="api_selection">Cursor and selection methods</h3>
separator to put between the lines in the output. When multiple
selections are present, they are concatenated with instances
of <code>lineSep</code> in between.</dd>
<dt id="getSelections"><code><strong>doc.getSelections</strong>(?lineSep: string) → string</code></dt>
<dt id="getSelections"><code><strong>doc.getSelections</strong>(?lineSep: string) → array&lt;string&gt;</code></dt>
<dd>Returns an array containing a string for each selection,
representing the content of the selections.</dd>

Expand Down Expand Up @@ -2064,26 +2064,29 @@ <h3 id="api_static">Static properties</h3>
else (usually one) for dev snapshots.</dd>

<dt id="fromTextArea"><code><strong>CodeMirror.fromTextArea</strong>(textArea: TextAreaElement, ?config: object)</code></dt>
<dd>
The method provides another way to initialize an editor. It
takes a textarea DOM node as first argument and an optional
configuration object as second. It will replace the textarea
with a CodeMirror instance, and wire up the form of that
textarea (if any) to make sure the editor contents are put
into the textarea when the form is submitted. The text in the
textarea will provide the content for the editor. A CodeMirror
instance created this way has three additional methods:
<dl>
<dt id="save"><code><strong>cm.save</strong>()</code></dt>
<dd>Copy the content of the editor into the textarea.</dd>

<dt id="toTextArea"><code><strong>cm.toTextArea</strong>()</code></dt>
<dd>Remove the editor, and restore the original textarea (with
the editor's current content).</dd>

<dt id="getTextArea"><code><strong>cm.getTextArea</strong>() → TextAreaElement</code></dt>
<dd>Returns the textarea that the instance was based on.</dd>
</dl>
<dd>This method provides another way to initialize an editor. It
takes a textarea DOM node as first argument and an optional
configuration object as second. It will replace the textarea
with a CodeMirror instance, and wire up the form of that
textarea (if any) to make sure the editor contents are put into
the textarea when the form is submitted. The text in the
textarea will provide the content for the editor. A CodeMirror
instance created this way has three additional methods:
<dl>
<dt id="save"><code><strong>cm.save</strong>()</code></dt>
<dd>Copy the content of the editor into the textarea.</dd>

<dt id="toTextArea"><code><strong>cm.toTextArea</strong>()</code></dt>
<dd>Remove the editor, and restore the original textarea (with
the editor's current content). If you dynamically create and
destroy editors made with `fromTextArea`, without destroying
the form they are part of, you should make sure to call
`toTextArea` to remove the editor, or its `"submit"` handler
on the form will cause a memory leak.</dd>

<dt id="getTextArea"><code><strong>cm.getTextArea</strong>() → TextAreaElement</code></dt>
<dd>Returns the textarea that the instance was based on.</dd>
</dl>
</dd>

<dt id="defaults"><code><strong>CodeMirror.defaults</strong>: object</code></dt>
Expand All @@ -2100,7 +2103,7 @@ <h3 id="api_static">Static properties</h3>
created from then on.</dd>

<dt id="defineDocExtension"><code><strong>CodeMirror.defineDocExtension</strong>(name: string, value: any)</code></dt>
<dd>Like <a href="#defineExtenstion"><code>defineExtension</code></a>,
<dd>Like <a href="#defineExtension"><code>defineExtension</code></a>,
but the method will be added to the interface
for <a href="#Doc"><code>Doc</code></a> objects instead.</dd>

Expand Down Expand Up @@ -2565,8 +2568,9 @@ <h2 id="addons">Addons</h2>
<dt><code><strong>to</strong>: {line, ch}</code></dt>
<dd>Optional <code>to</code> position that will be used by <code>pick()</code> instead
of the global one passed with the full list of completions.</dd>
</dl>
The plugin understands the following options (the options object
</dl></dd>

<dd>The plugin understands the following options (the options object
will also be passed along to the hinting function, which may
understand additional options):
<dl>
Expand All @@ -2577,7 +2581,10 @@ <h2 id="addons">Addons</h2>
arguments <code>(cm, callback, ?options)</code>, and the
completion interface will only be popped up when the hinting
function calls the callback, passing it the object holding the
completions. By default, hinting only works when there is no
completions.
The hinting function can also return a promise, and the completion
interface will only be popped when the promise resolves.
By default, hinting only works when there is no
selection. You can give a hinting function
a <code>supportsSelection</code> property with a truthy value
to indicate that it supports selections.</dd>
Expand Down Expand Up @@ -2693,7 +2700,8 @@ <h2 id="addons">Addons</h2>
(default 2), <code>style</code>, for the style to be used to
highlight the matches (default <code>"matchhighlight"</code>,
which will correspond to CSS
class <code>cm-matchhighlight</code>),
class <code>cm-matchhighlight</code>), <code>trim</code>, which
controls whether whitespace is trimmed from the selection,
and <code>showToken</code> which can be set to <code>true</code>
or to a regexp matching the characters that make up a word. When
enabled, it causes the current word to be highlighted when
Expand Down
4 changes: 3 additions & 1 deletion doc/realworld.html
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ <h2>CodeMirror real-world uses</h2>
<li><a href="https://github.com/simogeo/Filemanager">Filemanager</a></li>
<li><a href="https://hacks.mozilla.org/2013/11/firefox-developer-tools-episode-27-edit-as-html-codemirror-more/">Firefox Developer Tools</a></li>
<li><a href="http://www.firepad.io">Firepad</a> (collaborative text editor)</li>
<li><a href="https://code.google.com/p/gerrit/">Gerrit</a>'s diff view</li>
<li><a href="https://gerritcodereview.com/">Gerrit</a>'s diff view and inline editor</li>
<li><a href="https://github.com/maks/git-crx">Git Crx</a> (Chrome App for browsing local git repos)</li>
<li><a href="http://tour.golang.org">Go language tour</a></li>
<li><a href="https://github.com/github/android">GitHub's Android app</a></li>
Expand All @@ -94,6 +94,7 @@ <h2>CodeMirror real-world uses</h2>
<li><a href="http://www.homegenie.it/docs/automation_getstarted.php">Homegenie</a> (home automation server)</li>
<li><a href="http://icecoder.net">ICEcoder</a> (web IDE)</li>
<li><a href="http://ipython.org/">IPython</a> (interactive computing shell)</li>
<li><a href="joelpinheiro.github.io/itrading/">iTrading</a> (Algorithmic Trading)</li>
<li><a href="http://i-mos.org/imos/">i-MOS</a> (modeling and simulation platform)</li>
<li><a href="http://www.janvas.com/">Janvas</a> (vector graphics editor)</li>
<li><a href="http://extensions.joomla.org/extensions/edition/editors/8723">Joomla plugin</a></li>
Expand Down Expand Up @@ -121,6 +122,7 @@ <h2>CodeMirror real-world uses</h2>
<li><a href="https://github.com/soliton4/nodeMirror">nodeMirror</a> (IDE project)</li>
<li><a href="https://notex.ch">NoTex</a> (rST authoring)</li>
<li><a href="http://oakoutliner.com">Oak</a> (online outliner)</li>
<li><a href="http://www.greycampus.com/opencampus">OpenCampus</a></li>
<li><a href="http://clrhome.org/asm/">ORG</a> (z80 assembly IDE)</li>
<li><a href="https://github.com/mamacdon/orion-codemirror">Orion-CodeMirror integration</a> (running CodeMirror modes in Orion)</li>
<li><a href="http://paperjs.org/">Paper.js</a> (graphics scripting)</li>
Expand Down
18 changes: 18 additions & 0 deletions doc/releases.html
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,24 @@ <h2>Release notes and version history</h2>

<h2>Version 5.x</h2>

<p class="rel">20-04-2016: <a href="http://codemirror.net/codemirror-5.14.0.zip">Version 5.14.0</a>:</p>

<ul class="rel-note">
<li><a href="http://codemirror.net/doc/manual.html#posFromIndex"><code>posFromIndex</code></a> and <a href="http://codemirror.net/doc/manual.html#indexFromPos"><code>indexFromPos</code></a> now take <a href="http://codemirror.net/doc/manual.html#option_lineSeparator"><code>lineSeparator</code></a> into account</li>
<li><a href="http://codemirror.net/demo/vim.html">vim bindings</a>: Only call <code>.save()</code> when it is actually available</li>
<li><a href="http://codemirror.net/doc/manual.html#addon_comment">commend addon</a>: Be careful not to mangle multi-line strings</li>
<li><a href="http://codemirror.net/mode/python/index.html">Python mode</a>: Improve distinguishing of decorators from <code>@</code> operators</li>
<li><a href="http://codemirror.net/doc/manual.html#findMarks"><code>findMarks</code></a>: No longer return marks that touch but don't overlap given range</li>
<li><a href="http://codemirror.net/demo/vim.html">vim bindings</a>: Add yank command</li>
<li><a href="http://codemirror.net/doc/manual.html#addon_match-highlighter">match-highlighter addon</a>: Add <code>trim</code> option to disable ignoring of whitespace</li>
<li><a href="http://codemirror.net/mode/powershell/index.html">PowerShell mode</a>: Added</li>
<li><a href="http://codemirror.net/mode/yacas/index.html">Yacas mode</a>: Added</li>
<li><a href="http://codemirror.net/mode/webidl/index.html">Web IDL mode</a>: Added</li>
<li><a href="http://codemirror.net/mode/sas/index.html">SAS mode</a>: Added</li>
<li><a href="http://codemirror.net/mode/mbox/index.html">mbox mode</a>: Added</li>
<li>Full <a href="https://github.com/codemirror/CodeMirror/compare/5.13.4...5.14.0">list of patches</a></li>
</ul>

<p class="rel">21-03-2016: <a href="http://codemirror.net/codemirror-5.13.2.zip">Version 5.13.2</a>:</p>

<ul class="rel-note">
Expand Down
4 changes: 2 additions & 2 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ <h2>This is CodeMirror</h2>
</div>
</div>
<div class=actionsleft>
Get the current version: <a href="http://codemirror.net/codemirror.zip">5.13</a>.<br>
Get the current version: <a href="http://codemirror.net/codemirror.zip">5.13.2</a>.<br>
You can see the <a href="https://github.com/codemirror/codemirror" title="Github repository">code</a> or<br>
read the <a href="doc/releases.html">release notes</a>.<br>
There is a <a href="doc/compress.html">minification helper</a>.
Expand All @@ -106,7 +106,7 @@ <h2>This is CodeMirror</h2>
maintainers need to subsist.<br>
Current funding status = <img src="https://marijnhaverbeke.nl/fund/status_s.png" title="Current maintainer happiness" style="vertical-align: middle; height: 16px; width: 16px"><br>
You can help <a href="https://marijnhaverbeke.nl/fund/" title="Set up a monthly contribution">per month</a> or
<a title="Donate with Paypal" href="javascript:document.getElementById('paypal').submit();">once</a>.
<a title="Donate with PayPal" href="javascript:document.getElementById('paypal').submit();">once</a>.
<form action="https://www.paypal.com/cgi-bin/webscr" method="post" id="paypal">
<input type="hidden" name="cmd" value="_s-xclick"/>
<input type="hidden" name="hosted_button_id" value="3FVHS5FGUY7CC"/>
Expand Down
2 changes: 2 additions & 0 deletions keymap/sublime.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@
cmds[map["Alt-Left"] = "goSubwordLeft"] = function(cm) { moveSubword(cm, -1); };
cmds[map["Alt-Right"] = "goSubwordRight"] = function(cm) { moveSubword(cm, 1); };

if (mac) map["Cmd-Left"] = "goLineStartSmart";

var scrollLineCombo = mac ? "Ctrl-Alt-" : "Ctrl-";

cmds[map[scrollLineCombo + "Up"] = "scrollLineUp"] = function(cm) {
Expand Down
34 changes: 20 additions & 14 deletions keymap/vim.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
* 2. Variable declarations and short basic helpers
* 3. Instance (External API) implementation
* 4. Internal state tracking objects (input state, counter) implementation
* and instanstiation
* and instantiation
* 5. Key handler (the main command dispatcher) implementation
* 6. Motion, operator, and action implementations
* 7. Helper functions for the key handler, motions, operators, and actions
Expand Down Expand Up @@ -226,6 +226,7 @@
{ name: 'sort', shortName: 'sor' },
{ name: 'substitute', shortName: 's', possiblyAsync: true },
{ name: 'nohlsearch', shortName: 'noh' },
{ name: 'yank', shortName: 'y' },
{ name: 'delmarks', shortName: 'delm' },
{ name: 'registers', shortName: 'reg', excludeFromCommandHistory: true },
{ name: 'global', shortName: 'g' }
Expand Down Expand Up @@ -641,7 +642,7 @@
jumpList: createCircularJumpList(),
macroModeState: new MacroModeState,
// Recording latest f, t, F or T motion command.
lastChararacterSearch: {increment:0, forward:true, selectedCharacter:''},
lastCharacterSearch: {increment:0, forward:true, selectedCharacter:''},
registerController: new RegisterController({}),
// search history buffer
searchHistoryController: new HistoryController({}),
Expand Down Expand Up @@ -1047,7 +1048,7 @@
};
function HistoryController() {
this.historyBuffer = [];
this.iterator;
this.iterator = 0;
this.initialPrefix = null;
}
HistoryController.prototype = {
Expand Down Expand Up @@ -1372,7 +1373,7 @@
}
},
evalInput: function(cm, vim) {
// If the motion comand is set, execute both the operator and motion.
// If the motion command is set, execute both the operator and motion.
// Otherwise return.
var inputState = vim.inputState;
var motion = inputState.motion;
Expand Down Expand Up @@ -1909,7 +1910,7 @@
},

repeatLastCharacterSearch: function(cm, head, motionArgs) {
var lastSearch = vimGlobalState.lastChararacterSearch;
var lastSearch = vimGlobalState.lastCharacterSearch;
var repeat = motionArgs.repeat;
var forward = motionArgs.forward === lastSearch.forward;
var increment = (lastSearch.increment ? 1 : 0) * (forward ? -1 : 1);
Expand Down Expand Up @@ -3002,7 +3003,7 @@
// Only clip if the selection ends with trailing newline + whitespace
if (/\n\s*$/.test(selection)) {
var lines = selection.split('\n');
// We know this is all whitepsace.
// We know this is all whitespace.
lines.pop();

// Cases:
Expand Down Expand Up @@ -3088,9 +3089,9 @@
}

function recordLastCharacterSearch(increment, args) {
vimGlobalState.lastChararacterSearch.increment = increment;
vimGlobalState.lastChararacterSearch.forward = args.forward;
vimGlobalState.lastChararacterSearch.selectedCharacter = args.selectedCharacter;
vimGlobalState.lastCharacterSearch.increment = increment;
vimGlobalState.lastCharacterSearch.forward = args.forward;
vimGlobalState.lastCharacterSearch.selectedCharacter = args.selectedCharacter;
}

var symbolToMode = {
Expand Down Expand Up @@ -3289,8 +3290,6 @@
line = cm.getLine(lineNum);
pos = (dir > 0) ? 0 : line.length;
}
// Should never get here.
throw new Error('The impossible happened.');
}

/**
Expand Down Expand Up @@ -3452,7 +3451,7 @@
}

// TODO: perhaps this finagling of start and end positions belonds
// in codmirror/replaceRange?
// in codemirror/replaceRange?
function selectCompanionObject(cm, head, symb, inclusive) {
var cur = head, start, end;

Expand Down Expand Up @@ -4514,14 +4513,21 @@
if (CodeMirror.commands.save) {
// If a save command is defined, call it.
CodeMirror.commands.save(cm);
} else {
// Saves to text area if no save command is defined.
} else if (cm.save) {
// Saves to text area if no save command is defined and cm.save() is available.
cm.save();
}
},
nohlsearch: function(cm) {
clearSearchHighlight(cm);
},
yank: function (cm) {
var cur = copyCursor(cm.getCursor());
var line = cur.line;
var lineText = cm.getLine(line);
vimGlobalState.registerController.pushText(
'0', 'yank', lineText, true, true);
},
delmarks: function(cm, params) {
if (!params.argString || !trim(params.argString)) {
showConfirm(cm, 'Argument required');
Expand Down
16 changes: 9 additions & 7 deletions lib/codemirror.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
// This is woefully incomplete. Suggestions for alternative methods welcome.
var mobile = ios || /Android|webOS|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(userAgent);
var mac = ios || /Mac/.test(platform);
var chromeOS = /\bCrOS\b/.test(userAgent);
var windows = /win/i.test(platform);

var presto_version = presto && userAgent.match(/Version\/(\d*\.\d*)/);
Expand Down Expand Up @@ -3680,7 +3681,7 @@
ourIndex = doc.sel.primIndex;
}

if (e.altKey) {
if (chromeOS ? e.shiftKey && e.metaKey : e.altKey) {
type = "rect";
if (!addNew) ourRange = new Range(start, start);
start = posFromMouse(cm, e, true, true);
Expand Down Expand Up @@ -7625,9 +7626,9 @@
var spans = line.markedSpans;
if (spans) for (var i = 0; i < spans.length; i++) {
var span = spans[i];
if (!(span.to != null && lineNo == from.line && from.ch > span.to ||
if (!(span.to != null && lineNo == from.line && from.ch >= span.to ||
span.from == null && lineNo != from.line ||
span.from != null && lineNo == to.line && span.from > to.ch) &&
span.from != null && lineNo == to.line && span.from >= to.ch) &&
(!filter || filter(span.marker)))
found.push(span.marker.parent || span.marker);
}
Expand All @@ -7646,9 +7647,9 @@
},

posFromIndex: function(off) {
var ch, lineNo = this.first;
var ch, lineNo = this.first, sepSize = this.lineSeparator().length;
this.iter(function(line) {
var sz = line.text.length + 1;
var sz = line.text.length + sepSize;
if (sz > off) { ch = off; return true; }
off -= sz;
++lineNo;
Expand All @@ -7659,8 +7660,9 @@
coords = clipPos(this, coords);
var index = coords.ch;
if (coords.line < this.first || coords.ch < 0) return 0;
var sepSize = this.lineSeparator().length;
this.iter(this.first, coords.line, function (line) {
index += line.text.length + 1;
index += line.text.length + sepSize;
});
return index;
},
Expand Down Expand Up @@ -8889,7 +8891,7 @@

// THE END

CodeMirror.version = "5.13.3";
CodeMirror.version = "5.14.0";

return CodeMirror;
});
2 changes: 1 addition & 1 deletion mode/clike/clike.js
Original file line number Diff line number Diff line change
Expand Up @@ -667,7 +667,7 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {

def("text/x-objectivec", {
name: "clike",
keywords: words(cKeywords + "inline restrict _Bool _Complex _Imaginery BOOL Class bycopy byref id IMP in " +
keywords: words(cKeywords + "inline restrict _Bool _Complex _Imaginary BOOL Class bycopy byref id IMP in " +
"inout nil oneway out Protocol SEL self super atomic nonatomic retain copy readwrite readonly"),
types: words(cTypes),
atoms: words("YES NO NULL NILL ON OFF true false"),
Expand Down
2 changes: 1 addition & 1 deletion mode/crystal/crystal.js
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@

// Operators
if (stream.match(operators)) {
stream.eat("="); // Operators can follow assigin symbol.
stream.eat("="); // Operators can follow assign symbol.
return "operator";
}

Expand Down
16 changes: 8 additions & 8 deletions mode/django/django.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,11 +66,11 @@
}

// A string can be included in either single or double quotes (this is
// the delimeter). Mark everything as a string until the start delimeter
// the delimiter). Mark everything as a string until the start delimiter
// occurs again.
function inString (delimeter, previousTokenizer) {
function inString (delimiter, previousTokenizer) {
return function (stream, state) {
if (!state.escapeNext && stream.eat(delimeter)) {
if (!state.escapeNext && stream.eat(delimiter)) {
state.tokenize = previousTokenizer;
} else {
if (state.escapeNext) {
Expand All @@ -80,7 +80,7 @@
var ch = stream.next();

// Take into account the backslash for escaping characters, such as
// the string delimeter.
// the string delimiter.
if (ch == "\\") {
state.escapeNext = true;
}
Expand All @@ -100,7 +100,7 @@
return "null";
}

// Dot folowed by a non-word character should be considered an error.
// Dot followed by a non-word character should be considered an error.
if (stream.match(/\.\W+/)) {
return "error";
} else if (stream.eat(".")) {
Expand All @@ -119,7 +119,7 @@
return "null";
}

// Pipe folowed by a non-word character should be considered an error.
// Pipe followed by a non-word character should be considered an error.
if (stream.match(/\.\W+/)) {
return "error";
} else if (stream.eat("|")) {
Expand Down Expand Up @@ -199,7 +199,7 @@
return "null";
}

// Dot folowed by a non-word character should be considered an error.
// Dot followed by a non-word character should be considered an error.
if (stream.match(/\.\W+/)) {
return "error";
} else if (stream.eat(".")) {
Expand All @@ -218,7 +218,7 @@
return "null";
}

// Pipe folowed by a non-word character should be considered an error.
// Pipe followed by a non-word character should be considered an error.
if (stream.match(/\.\W+/)) {
return "error";
} else if (stream.eat("|")) {
Expand Down
12 changes: 6 additions & 6 deletions mode/dtd/dtd.js
Original file line number Diff line number Diff line change
Expand Up @@ -114,17 +114,17 @@ CodeMirror.defineMode("dtd", function(config) {

if( textAfter.match(/\]\s+|\]/) )n=n-1;
else if(textAfter.substr(textAfter.length-1, textAfter.length) === ">"){
if(textAfter.substr(0,1) === "<")n;
else if( type == "doindent" && textAfter.length > 1 )n;
if(textAfter.substr(0,1) === "<") {}
else if( type == "doindent" && textAfter.length > 1 ) {}
else if( type == "doindent")n--;
else if( type == ">" && textAfter.length > 1)n;
else if( type == "tag" && textAfter !== ">")n;
else if( type == ">" && textAfter.length > 1) {}
else if( type == "tag" && textAfter !== ">") {}
else if( type == "tag" && state.stack[state.stack.length-1] == "rule")n--;
else if( type == "tag")n++;
else if( textAfter === ">" && state.stack[state.stack.length-1] == "rule" && type === ">")n--;
else if( textAfter === ">" && state.stack[state.stack.length-1] == "rule")n;
else if( textAfter === ">" && state.stack[state.stack.length-1] == "rule") {}
else if( textAfter.substr(0,1) !== "<" && textAfter.substr(0,1) === ">" )n=n-1;
else if( textAfter === ">")n;
else if( textAfter === ">") {}
else n=n-1;
//over rule them all
if(type == null || type == "]")n--;
Expand Down
2 changes: 1 addition & 1 deletion mode/gfm/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ <h2>GFM mode</h2>
GFM adds syntax to strikethrough text, which is missing from standard Markdown.

~~Mistaken text.~~
~~**works with other fomatting**~~
~~**works with other formatting**~~

~~spans across
lines~~
Expand Down
6 changes: 6 additions & 0 deletions mode/gfm/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,12 @@
"[comment ```]",
"bar");

MT("fencedCodeBlockModeSwitchingObjc",
"[comment ```objective-c]",
"[keyword @property] [variable NSString] [operator *] [variable foo];",
"[comment ```]",
"bar");

MT("fencedCodeBlocksNoTildes",
"~~~",
"foo",
Expand Down
2 changes: 1 addition & 1 deletion mode/haml/haml.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
})(function(CodeMirror) {
"use strict";

// full haml mode. This handled embeded ruby and html fragments too
// full haml mode. This handled embedded ruby and html fragments too
CodeMirror.defineMode("haml", function(config) {
var htmlMode = CodeMirror.getMode(config, {name: "htmlmixed"});
var rubyMode = CodeMirror.getMode(config, "ruby");
Expand Down
2 changes: 1 addition & 1 deletion mode/htmlembedded/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ <h2>Html Embedded Scripts mode</h2>
</script>

<p>Mode for html embedded scripts like JSP and ASP.NET. Depends on HtmlMixed which in turn depends on
JavaScript, CSS and XML.<br />Other dependancies include those of the scriping language chosen.</p>
JavaScript, CSS and XML.<br />Other dependencies include those of the scripting language chosen.</p>

<p><strong>MIME types defined:</strong> <code>application/x-aspx</code> (ASP.NET),
<code>application/x-ejs</code> (Embedded Javascript), <code>application/x-jsp</code> (JavaServer Pages)</p>
Expand Down
5 changes: 5 additions & 0 deletions mode/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ <h2>Language modes</h2>
<li><a href="lua/index.html">Lua</a></li>
<li><a href="markdown/index.html">Markdown</a> (<a href="gfm/index.html">GitHub-flavour</a>)</li>
<li><a href="mathematica/index.html">Mathematica</a></li>
<li><a href="mbox/index.html">mbox</a></li>
<li><a href="mirc/index.html">mIRC</a></li>
<li><a href="modelica/index.html">Modelica</a></li>
<li><a href="mscgen/index.html">MscGen</a></li>
Expand All @@ -103,6 +104,7 @@ <h2>Language modes</h2>
<li><a href="asciiarmor/index.html">PGP (ASCII armor)</a></li>
<li><a href="php/index.html">PHP</a></li>
<li><a href="pig/index.html">Pig Latin</a></li>
<li><a href="powershell/index.html">PowerShell</a></li>
<li><a href="properties/index.html">Properties files</a></li>
<li><a href="protobuf/index.html">ProtoBuf</a></li>
<li><a href="puppet/index.html">Puppet</a></li>
Expand All @@ -113,6 +115,7 @@ <h2>Language modes</h2>
<li><a href="rst/index.html">reStructuredText</a></li>
<li><a href="ruby/index.html">Ruby</a></li>
<li><a href="rust/index.html">Rust</a></li>
<li><a href="sas/index.html">SAS</a></li>
<li><a href="sass/index.html">Sass</a></li>
<li><a href="spreadsheet/index.html">Spreadsheet</a></li>
<li><a href="clike/scala.html">Scala</a></li>
Expand Down Expand Up @@ -148,8 +151,10 @@ <h2>Language modes</h2>
<li><a href="verilog/index.html">Verilog/SystemVerilog</a></li>
<li><a href="vhdl/index.html">VHDL</a></li>
<li><a href="vue/index.html">Vue.js app</a></li>
<li><a href="webidl/index.html">Web IDL</a></li>
<li><a href="xml/index.html">XML/HTML</a></li>
<li><a href="xquery/index.html">XQuery</a></li>
<li><a href="yacas/index.html">Yacas</a></li>
<li><a href="yaml/index.html">YAML</a></li>
<li><a href="yaml-frontmatter/index.html">YAML frontmatter</a></li>
<li><a href="z80/index.html">Z80</a></li>
Expand Down
2 changes: 1 addition & 1 deletion mode/markdown/markdown.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
, setextHeaderRE = /^ *(?:\={1,}|-{1,})\s*$/
, textRE = /^[^#!\[\]*_\\<>` "'(~]+/
, fencedCodeRE = new RegExp("^(" + (modeCfg.fencedCodeBlocks === true ? "~~~+|```+" : modeCfg.fencedCodeBlocks) +
")[ \\t]*([\\w+#]*)");
")[ \\t]*([\\w+#\-]*)");

function switchInline(stream, state, f) {
state.f = state.inline = f;
Expand Down
6 changes: 3 additions & 3 deletions mode/markdown/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -647,7 +647,7 @@
MT("linkReferenceEmStrong",
"[link [[][link&strong **][link&em&strong *foo**][link&em *][link ]]][string&url [[bar]]] hello");

// Reference-style links with optional space separator (per docuentation)
// Reference-style links with optional space separator (per documentation)
// "You can optionally use a space to separate the sets of brackets"
MT("linkReferenceSpace",
"[link [[foo]]] [string&url [[bar]]] hello");
Expand Down Expand Up @@ -683,7 +683,7 @@
MT("labelTitleSingleQuotes",
"[link [[foo]]:] [string&url http://example.com/ 'bar']");

MT("labelTitleParenthese",
MT("labelTitleParentheses",
"[link [[foo]]:] [string&url http://example.com/ (bar)]");

MT("labelTitleInvalid",
Expand All @@ -700,7 +700,7 @@
"[link [[foo]]:] [string&url http://example.com/]",
"[string 'bar'] hello");

MT("labelTitleNextParenthese",
MT("labelTitleNextParentheses",
"[link [[foo]]:] [string&url http://example.com/]",
"[string (bar)] hello");

Expand Down
1 change: 1 addition & 0 deletions mode/mathematica/mathematica.js
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ CodeMirror.defineMode('mathematica', function(_config, _parserConfig) {
}

// everything else is an error
stream.next(); // advance the stream.
return 'error';
}

Expand Down
44 changes: 44 additions & 0 deletions mode/mbox/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<!doctype html>

<title>CodeMirror: mbox mode</title>
<meta charset="utf-8"/>
<link rel=stylesheet href="../../doc/docs.css">

<link rel="stylesheet" href="../../lib/codemirror.css">
<script src="../../lib/codemirror.js"></script>
<script src="mbox.js"></script>
<style>.CodeMirror { border-top: 1px solid #ddd; border-bottom: 1px solid #ddd; }</style>
<div id=nav>
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>

<ul>
<li><a href="../../index.html">Home</a>
<li><a href="../../doc/manual.html">Manual</a>
<li><a href="https://github.com/codemirror/codemirror">Code</a>
</ul>
<ul>
<li><a href="../index.html">Language modes</a>
<li><a class=active href="#">mbox</a>
</ul>
</div>

<article>
<h2>mbox mode</h2>
<form><textarea id="code" name="code">
From timothygu99@gmail.com Sun Apr 17 01:40:43 2016
From: Timothy Gu &lt;timothygu99@gmail.com&gt;
Date: Sat, 16 Apr 2016 18:40:43 -0700
Subject: mbox mode
Message-ID: &lt;Z8d+bTT50U/az94FZnyPkDjZmW0=@gmail.com&gt;

mbox mode is working!

Timothy
</textarea></form>
<script>
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {});
</script>

<p><strong>MIME types defined:</strong> <code>application/mbox</code>.</p>

</article>
129 changes: 129 additions & 0 deletions mode/mbox/mbox.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE

(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";

var rfc2822 = [
"From", "Sender", "Reply-To", "To", "Cc", "Bcc", "Message-ID",
"In-Reply-To", "References", "Resent-From", "Resent-Sender", "Resent-To",
"Resent-Cc", "Resent-Bcc", "Resent-Message-ID", "Return-Path", "Received"
];
var rfc2822NoEmail = [
"Date", "Subject", "Comments", "Keywords", "Resent-Date"
];

CodeMirror.registerHelper("hintWords", "mbox", rfc2822.concat(rfc2822NoEmail));

var whitespace = /^[ \t]/;
var separator = /^From /; // See RFC 4155
var rfc2822Header = new RegExp("^(" + rfc2822.join("|") + "): ");
var rfc2822HeaderNoEmail = new RegExp("^(" + rfc2822NoEmail.join("|") + "): ");
var header = /^[^:]+:/; // Optional fields defined in RFC 2822
var email = /^[^ ]+@[^ ]+/;
var untilEmail = /^.*?(?=[^ ]+?@[^ ]+)/;
var bracketedEmail = /^<.*?>/;
var untilBracketedEmail = /^.*?(?=<.*>)/;

function styleForHeader(header) {
if (header === "Subject") return "header";
return "string";
}

function readToken(stream, state) {
if (stream.sol()) {
// From last line
state.inSeparator = false;
if (state.inHeader && stream.match(whitespace)) {
// Header folding
return null;
} else {
state.inHeader = false;
state.header = null;
}

if (stream.match(separator)) {
state.inHeaders = true;
state.inSeparator = true;
return "atom";
}

var match;
var emailPermitted = false;
if ((match = stream.match(rfc2822HeaderNoEmail)) ||
(emailPermitted = true) && (match = stream.match(rfc2822Header))) {
state.inHeaders = true;
state.inHeader = true;
state.emailPermitted = emailPermitted;
state.header = match[1];
return "atom";
}

// Use vim's heuristics: recognize custom headers only if the line is in a
// block of legitimate headers.
if (state.inHeaders && (match = stream.match(header))) {
state.inHeader = true;
state.emailPermitted = true;
state.header = match[1];
return "atom";
}

state.inHeaders = false;
stream.skipToEnd();
return null;
}

if (state.inSeparator) {
if (stream.match(email)) return "link";
if (stream.match(untilEmail)) return "atom";
stream.skipToEnd();
return "atom";
}

if (state.inHeader) {
var style = styleForHeader(state.header);

if (state.emailPermitted) {
if (stream.match(bracketedEmail)) return style + " link";
if (stream.match(untilBracketedEmail)) return style;
}
stream.skipToEnd();
return style;
}

stream.skipToEnd();
return null;
};

CodeMirror.defineMode("mbox", function() {
return {
startState: function() {
return {
// Is in a mbox separator
inSeparator: false,
// Is in a mail header
inHeader: false,
// If bracketed email is permitted. Only applicable when inHeader
emailPermitted: false,
// Name of current header
header: null,
// Is in a region of mail headers
inHeaders: false
};
},
token: readToken,
blankLine: function(state) {
state.inHeaders = state.inSeparator = state.inHeader = false;
}
};
});

CodeMirror.defineMIME("application/mbox", "mbox");
});
8 changes: 6 additions & 2 deletions mode/meta.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@
{name: "Nginx", mime: "text/x-nginx-conf", mode: "nginx", file: /nginx.*\.conf$/i},
{name: "NSIS", mime: "text/x-nsis", mode: "nsis", ext: ["nsh", "nsi"]},
{name: "NTriples", mime: "text/n-triples", mode: "ntriples", ext: ["nt"]},
{name: "Objective C", mime: "text/x-objectivec", mode: "clike", ext: ["m", "mm"]},
{name: "Objective C", mime: "text/x-objectivec", mode: "clike", ext: ["m", "mm"], alias: ["objective-c", "objc"]},
{name: "OCaml", mime: "text/x-ocaml", mode: "mllike", ext: ["ml", "mli", "mll", "mly"]},
{name: "Octave", mime: "text/x-octave", mode: "octave", ext: ["m"]},
{name: "Oz", mime: "text/x-oz", mode: "oz", ext: ["oz"]},
Expand All @@ -102,9 +102,10 @@
{name: "Pig", mime: "text/x-pig", mode: "pig", ext: ["pig"]},
{name: "Plain Text", mime: "text/plain", mode: "null", ext: ["txt", "text", "conf", "def", "list", "log"]},
{name: "PLSQL", mime: "text/x-plsql", mode: "sql", ext: ["pls"]},
{name: "PowerShell", mime: "application/x-powershell", mode: "powershell", ext: ["ps1", "psd1", "psm1"]},
{name: "Properties files", mime: "text/x-properties", mode: "properties", ext: ["properties", "ini", "in"], alias: ["ini", "properties"]},
{name: "ProtoBuf", mime: "text/x-protobuf", mode: "protobuf", ext: ["proto"]},
{name: "Python", mime: "text/x-python", mode: "python", ext: ["py", "pyw"]},
{name: "Python", mime: "text/x-python", mode: "python", ext: ["BUILD", "bzl", "py", "pyw"], file: /^(BUCK|BUILD)$/},
{name: "Puppet", mime: "text/x-puppet", mode: "puppet", ext: ["pp"]},
{name: "Q", mime: "text/x-q", mode: "q", ext: ["q"]},
{name: "R", mime: "text/x-rsrc", mode: "r", ext: ["r"], alias: ["rscript"]},
Expand All @@ -113,6 +114,7 @@
{name: "RPM Spec", mime: "text/x-rpm-spec", mode: "rpm", ext: ["spec"]},
{name: "Ruby", mime: "text/x-ruby", mode: "ruby", ext: ["rb"], alias: ["jruby", "macruby", "rake", "rb", "rbx"]},
{name: "Rust", mime: "text/x-rustsrc", mode: "rust", ext: ["rs"]},
{name: "SAS", mime: "text/x-sas", mode: "sas", ext: ["sas"]},
{name: "Sass", mime: "text/x-sass", mode: "sass", ext: ["sass"]},
{name: "Scala", mime: "text/x-scala", mode: "clike", ext: ["scala"]},
{name: "Scheme", mime: "text/x-scheme", mode: "scheme", ext: ["scm", "ss"]},
Expand Down Expand Up @@ -144,13 +146,15 @@
{name: "Turtle", mime: "text/turtle", mode: "turtle", ext: ["ttl"]},
{name: "TypeScript", mime: "application/typescript", mode: "javascript", ext: ["ts"], alias: ["ts"]},
{name: "Twig", mime: "text/x-twig", mode: "twig"},
{name: "Web IDL", mime: "text/x-webidl", mode: "webidl", ext: ["webidl"]},
{name: "VB.NET", mime: "text/x-vb", mode: "vb", ext: ["vb"]},
{name: "VBScript", mime: "text/vbscript", mode: "vbscript", ext: ["vbs"]},
{name: "Velocity", mime: "text/velocity", mode: "velocity", ext: ["vtl"]},
{name: "Verilog", mime: "text/x-verilog", mode: "verilog", ext: ["v"]},
{name: "VHDL", mime: "text/x-vhdl", mode: "vhdl", ext: ["vhd", "vhdl"]},
{name: "XML", mimes: ["application/xml", "text/xml"], mode: "xml", ext: ["xml", "xsl", "xsd"], alias: ["rss", "wsdl", "xsd"]},
{name: "XQuery", mime: "application/xquery", mode: "xquery", ext: ["xy", "xquery"]},
{name: "Yacas", mime: "text/x-yacas", mode: "yacas", ext: ["ys"]},
{name: "YAML", mime: "text/x-yaml", mode: "yaml", ext: ["yaml", "yml"], alias: ["yml"]},
{name: "Z80", mime: "text/x-z80", mode: "z80", ext: ["z80"]},
{name: "mscgen", mime: "text/x-mscgen", mode: "mscgen", ext: ["mscgen", "mscin", "msc"]},
Expand Down
2 changes: 1 addition & 1 deletion mode/octave/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ <h2>Octave mode</h2>

%one line comment
%{ multi
line commment %}
line comment %}

</textarea></div>
<script>
Expand Down
10 changes: 5 additions & 5 deletions mode/pegjs/pegjs.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ CodeMirror.defineMode("pegjs", function (config) {
inString: false,
stringType: null,
inComment: false,
inChracterClass: false,
inCharacterClass: false,
braced: 0,
lhs: true,
localState: null
Expand Down Expand Up @@ -66,15 +66,15 @@ CodeMirror.defineMode("pegjs", function (config) {
}
}
return "comment";
} else if (state.inChracterClass) {
while (state.inChracterClass && !stream.eol()) {
} else if (state.inCharacterClass) {
while (state.inCharacterClass && !stream.eol()) {
if (!(stream.match(/^[^\]\\]+/) || stream.match(/^\\./))) {
state.inChracterClass = false;
state.inCharacterClass = false;
}
}
} else if (stream.peek() === '[') {
stream.next();
state.inChracterClass = true;
state.inCharacterClass = true;
return 'bracket';
} else if (stream.match(/^\/\//)) {
stream.skipToEnd();
Expand Down
2 changes: 1 addition & 1 deletion mode/perl/perl.js
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@ CodeMirror.defineMode("perl",function(){
chmod :1, // - changes the permissions on a list of files
chomp :1, // - remove a trailing record separator from a string
chop :1, // - remove the last character from a string
chown :1, // - change the owership on a list of files
chown :1, // - change the ownership on a list of files
chr :1, // - get character this number represents
chroot :1, // - make directory new root for path lookups
close :1, // - close file (or pipe or socket) handle
Expand Down
204 changes: 204 additions & 0 deletions mode/powershell/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>CodeMirror: Powershell mode</title>
<link rel="stylesheet" href="../../doc/docs.css">
<link rel="stylesheet" href="../../lib/codemirror.css">
<script src="../../lib/codemirror.js"></script>
<script src="powershell.js"></script>
<style>.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
</head>
<body>
<div id=nav>
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>

<ul>
<li><a href="../../index.html">Home</a>
<li><a href="../../doc/manual.html">Manual</a>
<li><a href="https://github.com/codemirror/codemirror">Code</a>
</ul>
<ul>
<li><a href="../index.html">Language modes</a>
<li><a class=active href="#">JavaScript</a>
</ul>
</div>
<article>
<h2>PowerShell mode</h2>

<div><textarea id="code" name="code">
# Number Literals
0 12345
12kb 12mb 12gB 12Tb 12PB 12L 12D 12lkb 12dtb
1.234 1.234e56 1. 1.e2 .2 .2e34
1.2MB 1.kb .1dTb 1.e1gb
0x1 0xabcdef 0x3tb 0xelmb

# String Literals
'Literal escaping'''
'Literal $variable'
"Escaping 1`""
"Escaping 2"""
"Escaped `$variable"
"Text, $variable and more text"
"Text, ${variable with spaces} and more text."
"Text, $($expression + 3) and more text."
"Text, $("interpolation $("inception")") and more text."

@"
Multiline
string
"@
# --
@"
Multiline
string with quotes "'
"@
# --
@'
Multiline literal
string with quotes "'
'@

# Array and Hash literals
@( 'a','b','c' )
@{ 'key': 'value' }

# Variables
$Variable = 5
$global:variable = 5
${Variable with spaces} = 5

# Operators
= += -= *= /= %=
++ -- .. -f * / % + -
-not ! -bnot
-split -isplit -csplit
-join
-is -isnot -as
-eq -ieq -ceq -ne -ine -cne
-gt -igt -cgt -ge -ige -cge
-lt -ilt -clt -le -ile -cle
-like -ilike -clike -notlike -inotlike -cnotlike
-match -imatch -cmatch -notmatch -inotmatch -cnotmatch
-contains -icontains -ccontains -notcontains -inotcontains -cnotcontains
-replace -ireplace -creplace
-band -bor -bxor
-and -or -xor

# Punctuation
() [] {} , : ` = ; .

# Keywords
elseif begin function for foreach return else trap while do data dynamicparam
until end break if throw param continue finally in switch exit filter from try
process catch

# Built-in variables
$$ $? $^ $_
$args $ConfirmPreference $ConsoleFileName $DebugPreference $Error
$ErrorActionPreference $ErrorView $ExecutionContext $false $FormatEnumerationLimit
$HOME $Host $input $MaximumAliasCount $MaximumDriveCount $MaximumErrorCount
$MaximumFunctionCount $MaximumHistoryCount $MaximumVariableCount $MyInvocation
$NestedPromptLevel $null $OutputEncoding $PID $PROFILE $ProgressPreference
$PSBoundParameters $PSCommandPath $PSCulture $PSDefaultParameterValues
$PSEmailServer $PSHOME $PSScriptRoot $PSSessionApplicationName
$PSSessionConfigurationName $PSSessionOption $PSUICulture $PSVersionTable $PWD
$ShellId $StackTrace $true $VerbosePreference $WarningPreference $WhatIfPreference
$true $false $null

# Built-in functions
A:
Add-Computer Add-Content Add-History Add-Member Add-PSSnapin Add-Type
B:
C:
Checkpoint-Computer Clear-Content Clear-EventLog Clear-History Clear-Host Clear-Item
Clear-ItemProperty Clear-Variable Compare-Object Complete-Transaction Connect-PSSession
ConvertFrom-Csv ConvertFrom-Json ConvertFrom-SecureString ConvertFrom-StringData
Convert-Path ConvertTo-Csv ConvertTo-Html ConvertTo-Json ConvertTo-SecureString
ConvertTo-Xml Copy-Item Copy-ItemProperty
D:
Debug-Process Disable-ComputerRestore Disable-PSBreakpoint Disable-PSRemoting
Disable-PSSessionConfiguration Disconnect-PSSession
E:
Enable-ComputerRestore Enable-PSBreakpoint Enable-PSRemoting Enable-PSSessionConfiguration
Enter-PSSession Exit-PSSession Export-Alias Export-Clixml Export-Console Export-Counter
Export-Csv Export-FormatData Export-ModuleMember Export-PSSession
F:
ForEach-Object Format-Custom Format-List Format-Table Format-Wide
G:
Get-Acl Get-Alias Get-AuthenticodeSignature Get-ChildItem Get-Command Get-ComputerRestorePoint
Get-Content Get-ControlPanelItem Get-Counter Get-Credential Get-Culture Get-Date
Get-Event Get-EventLog Get-EventSubscriber Get-ExecutionPolicy Get-FormatData Get-Help
Get-History Get-Host Get-HotFix Get-Item Get-ItemProperty Get-Job Get-Location Get-Member
Get-Module Get-PfxCertificate Get-Process Get-PSBreakpoint Get-PSCallStack Get-PSDrive
Get-PSProvider Get-PSSession Get-PSSessionConfiguration Get-PSSnapin Get-Random Get-Service
Get-TraceSource Get-Transaction Get-TypeData Get-UICulture Get-Unique Get-Variable Get-Verb
Get-WinEvent Get-WmiObject Group-Object
H:
help
I:
Import-Alias Import-Clixml Import-Counter Import-Csv Import-LocalizedData Import-Module
Import-PSSession ImportSystemModules Invoke-Command Invoke-Expression Invoke-History
Invoke-Item Invoke-RestMethod Invoke-WebRequest Invoke-WmiMethod
J:
Join-Path
K:
L:
Limit-EventLog
M:
Measure-Command Measure-Object mkdir more Move-Item Move-ItemProperty
N:
New-Alias New-Event New-EventLog New-Item New-ItemProperty New-Module New-ModuleManifest
New-Object New-PSDrive New-PSSession New-PSSessionConfigurationFile New-PSSessionOption
New-PSTransportOption New-Service New-TimeSpan New-Variable New-WebServiceProxy
New-WinEvent
O:
oss Out-Default Out-File Out-GridView Out-Host Out-Null Out-Printer Out-String
P:
Pause Pop-Location prompt Push-Location
Q:
R:
Read-Host Receive-Job Receive-PSSession Register-EngineEvent Register-ObjectEvent
Register-PSSessionConfiguration Register-WmiEvent Remove-Computer Remove-Event
Remove-EventLog Remove-Item Remove-ItemProperty Remove-Job Remove-Module
Remove-PSBreakpoint Remove-PSDrive Remove-PSSession Remove-PSSnapin Remove-TypeData
Remove-Variable Remove-WmiObject Rename-Computer Rename-Item Rename-ItemProperty
Reset-ComputerMachinePassword Resolve-Path Restart-Computer Restart-Service
Restore-Computer Resume-Job Resume-Service
S:
Save-Help Select-Object Select-String Select-Xml Send-MailMessage Set-Acl Set-Alias
Set-AuthenticodeSignature Set-Content Set-Date Set-ExecutionPolicy Set-Item
Set-ItemProperty Set-Location Set-PSBreakpoint Set-PSDebug
Set-PSSessionConfiguration Set-Service Set-StrictMode Set-TraceSource Set-Variable
Set-WmiInstance Show-Command Show-ControlPanelItem Show-EventLog Sort-Object
Split-Path Start-Job Start-Process Start-Service Start-Sleep Start-Transaction
Start-Transcript Stop-Computer Stop-Job Stop-Process Stop-Service Stop-Transcript
Suspend-Job Suspend-Service
T:
TabExpansion2 Tee-Object Test-ComputerSecureChannel Test-Connection
Test-ModuleManifest Test-Path Test-PSSessionConfigurationFile Trace-Command
U:
Unblock-File Undo-Transaction Unregister-Event Unregister-PSSessionConfiguration
Update-FormatData Update-Help Update-List Update-TypeData Use-Transaction
V:
W:
Wait-Event Wait-Job Wait-Process Where-Object Write-Debug Write-Error Write-EventLog
Write-Host Write-Output Write-Progress Write-Verbose Write-Warning
X:
Y:
Z:</textarea></div>
<script>
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
mode: "powershell",
lineNumbers: true,
indentUnit: 4,
tabMode: "shift",
matchBrackets: true
});
</script>

<p><strong>MIME types defined:</strong> <code>application/x-powershell</code>.</p>
</article>
</body>
</html>
396 changes: 396 additions & 0 deletions mode/powershell/powershell.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,396 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE

(function(mod) {
'use strict';
if (typeof exports == 'object' && typeof module == 'object') // CommonJS
mod(require('codemirror'));
else if (typeof define == 'function' && define.amd) // AMD
define(['codemirror'], mod);
else // Plain browser env
mod(window.CodeMirror);
})(function(CodeMirror) {
'use strict';

CodeMirror.defineMode('powershell', function() {
function buildRegexp(patterns, options) {
options = options || {};
var prefix = options.prefix !== undefined ? options.prefix : '^';
var suffix = options.suffix !== undefined ? options.suffix : '\\b';

for (var i = 0; i < patterns.length; i++) {
if (patterns[i] instanceof RegExp) {
patterns[i] = patterns[i].source;
}
else {
patterns[i] = patterns[i].replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
}
}

return new RegExp(prefix + '(' + patterns.join('|') + ')' + suffix, 'i');
}

var notCharacterOrDash = '(?=[^A-Za-z\\d\\-_]|$)';
var varNames = /[\w\-:]/
var keywords = buildRegexp([
/begin|break|catch|continue|data|default|do|dynamicparam/,
/else|elseif|end|exit|filter|finally|for|foreach|from|function|if|in/,
/param|process|return|switch|throw|trap|try|until|where|while/
], { suffix: notCharacterOrDash });

var punctuation = /[\[\]{},;`\.]|@[({]/;
var wordOperators = buildRegexp([
'f',
/b?not/,
/[ic]?split/, 'join',
/is(not)?/, 'as',
/[ic]?(eq|ne|[gl][te])/,
/[ic]?(not)?(like|match|contains)/,
/[ic]?replace/,
/b?(and|or|xor)/
], { prefix: '-' });
var symbolOperators = /[+\-*\/%]=|\+\+|--|\.\.|[+\-*&^%:=!|\/]|<(?!#)|(?!#)>/;
var operators = buildRegexp([wordOperators, symbolOperators], { suffix: '' });

var numbers = /^((0x[\da-f]+)|((\d+\.\d+|\d\.|\.\d+|\d+)(e[\+\-]?\d+)?))[ld]?([kmgtp]b)?/i;

var identifiers = /^[A-Za-z\_][A-Za-z\-\_\d]*\b/;

var symbolBuiltins = /[A-Z]:|%|\?/i;
var namedBuiltins = buildRegexp([
/Add-(Computer|Content|History|Member|PSSnapin|Type)/,
/Checkpoint-Computer/,
/Clear-(Content|EventLog|History|Host|Item(Property)?|Variable)/,
/Compare-Object/,
/Complete-Transaction/,
/Connect-PSSession/,
/ConvertFrom-(Csv|Json|SecureString|StringData)/,
/Convert-Path/,
/ConvertTo-(Csv|Html|Json|SecureString|Xml)/,
/Copy-Item(Property)?/,
/Debug-Process/,
/Disable-(ComputerRestore|PSBreakpoint|PSRemoting|PSSessionConfiguration)/,
/Disconnect-PSSession/,
/Enable-(ComputerRestore|PSBreakpoint|PSRemoting|PSSessionConfiguration)/,
/(Enter|Exit)-PSSession/,
/Export-(Alias|Clixml|Console|Counter|Csv|FormatData|ModuleMember|PSSession)/,
/ForEach-Object/,
/Format-(Custom|List|Table|Wide)/,
new RegExp('Get-(Acl|Alias|AuthenticodeSignature|ChildItem|Command|ComputerRestorePoint|Content|ControlPanelItem|Counter|Credential'
+ '|Culture|Date|Event|EventLog|EventSubscriber|ExecutionPolicy|FormatData|Help|History|Host|HotFix|Item|ItemProperty|Job'
+ '|Location|Member|Module|PfxCertificate|Process|PSBreakpoint|PSCallStack|PSDrive|PSProvider|PSSession|PSSessionConfiguration'
+ '|PSSnapin|Random|Service|TraceSource|Transaction|TypeData|UICulture|Unique|Variable|Verb|WinEvent|WmiObject)'),
/Group-Object/,
/Import-(Alias|Clixml|Counter|Csv|LocalizedData|Module|PSSession)/,
/ImportSystemModules/,
/Invoke-(Command|Expression|History|Item|RestMethod|WebRequest|WmiMethod)/,
/Join-Path/,
/Limit-EventLog/,
/Measure-(Command|Object)/,
/Move-Item(Property)?/,
new RegExp('New-(Alias|Event|EventLog|Item(Property)?|Module|ModuleManifest|Object|PSDrive|PSSession|PSSessionConfigurationFile'
+ '|PSSessionOption|PSTransportOption|Service|TimeSpan|Variable|WebServiceProxy|WinEvent)'),
/Out-(Default|File|GridView|Host|Null|Printer|String)/,
/Pause/,
/(Pop|Push)-Location/,
/Read-Host/,
/Receive-(Job|PSSession)/,
/Register-(EngineEvent|ObjectEvent|PSSessionConfiguration|WmiEvent)/,
/Remove-(Computer|Event|EventLog|Item(Property)?|Job|Module|PSBreakpoint|PSDrive|PSSession|PSSnapin|TypeData|Variable|WmiObject)/,
/Rename-(Computer|Item(Property)?)/,
/Reset-ComputerMachinePassword/,
/Resolve-Path/,
/Restart-(Computer|Service)/,
/Restore-Computer/,
/Resume-(Job|Service)/,
/Save-Help/,
/Select-(Object|String|Xml)/,
/Send-MailMessage/,
new RegExp('Set-(Acl|Alias|AuthenticodeSignature|Content|Date|ExecutionPolicy|Item(Property)?|Location|PSBreakpoint|PSDebug' +
'|PSSessionConfiguration|Service|StrictMode|TraceSource|Variable|WmiInstance)'),
/Show-(Command|ControlPanelItem|EventLog)/,
/Sort-Object/,
/Split-Path/,
/Start-(Job|Process|Service|Sleep|Transaction|Transcript)/,
/Stop-(Computer|Job|Process|Service|Transcript)/,
/Suspend-(Job|Service)/,
/TabExpansion2/,
/Tee-Object/,
/Test-(ComputerSecureChannel|Connection|ModuleManifest|Path|PSSessionConfigurationFile)/,
/Trace-Command/,
/Unblock-File/,
/Undo-Transaction/,
/Unregister-(Event|PSSessionConfiguration)/,
/Update-(FormatData|Help|List|TypeData)/,
/Use-Transaction/,
/Wait-(Event|Job|Process)/,
/Where-Object/,
/Write-(Debug|Error|EventLog|Host|Output|Progress|Verbose|Warning)/,
/cd|help|mkdir|more|oss|prompt/,
/ac|asnp|cat|cd|chdir|clc|clear|clhy|cli|clp|cls|clv|cnsn|compare|copy|cp|cpi|cpp|cvpa|dbp|del|diff|dir|dnsn|ebp/,
/echo|epal|epcsv|epsn|erase|etsn|exsn|fc|fl|foreach|ft|fw|gal|gbp|gc|gci|gcm|gcs|gdr|ghy|gi|gjb|gl|gm|gmo|gp|gps/,
/group|gsn|gsnp|gsv|gu|gv|gwmi|h|history|icm|iex|ihy|ii|ipal|ipcsv|ipmo|ipsn|irm|ise|iwmi|iwr|kill|lp|ls|man|md/,
/measure|mi|mount|move|mp|mv|nal|ndr|ni|nmo|npssc|nsn|nv|ogv|oh|popd|ps|pushd|pwd|r|rbp|rcjb|rcsn|rd|rdr|ren|ri/,
/rjb|rm|rmdir|rmo|rni|rnp|rp|rsn|rsnp|rujb|rv|rvpa|rwmi|sajb|sal|saps|sasv|sbp|sc|select|set|shcm|si|sl|sleep|sls/,
/sort|sp|spjb|spps|spsv|start|sujb|sv|swmi|tee|trcm|type|where|wjb|write/
], { prefix: '', suffix: '' });
var variableBuiltins = buildRegexp([
/[$?^_]|Args|ConfirmPreference|ConsoleFileName|DebugPreference|Error|ErrorActionPreference|ErrorView|ExecutionContext/,
/FormatEnumerationLimit|Home|Host|Input|MaximumAliasCount|MaximumDriveCount|MaximumErrorCount|MaximumFunctionCount/,
/MaximumHistoryCount|MaximumVariableCount|MyInvocation|NestedPromptLevel|OutputEncoding|Pid|Profile|ProgressPreference/,
/PSBoundParameters|PSCommandPath|PSCulture|PSDefaultParameterValues|PSEmailServer|PSHome|PSScriptRoot|PSSessionApplicationName/,
/PSSessionConfigurationName|PSSessionOption|PSUICulture|PSVersionTable|Pwd|ShellId|StackTrace|VerbosePreference/,
/WarningPreference|WhatIfPreference/,

/Event|EventArgs|EventSubscriber|Sender/,
/Matches|Ofs|ForEach|LastExitCode|PSCmdlet|PSItem|PSSenderInfo|This/,
/true|false|null/
], { prefix: '\\$', suffix: '' });

var builtins = buildRegexp([symbolBuiltins, namedBuiltins, variableBuiltins], { suffix: notCharacterOrDash });

var grammar = {
keyword: keywords,
number: numbers,
operator: operators,
builtin: builtins,
punctuation: punctuation,
identifier: identifiers
};

// tokenizers
function tokenBase(stream, state) {
// Handle Comments
//var ch = stream.peek();

var parent = state.returnStack[state.returnStack.length - 1];
if (parent && parent.shouldReturnFrom(state)) {
state.tokenize = parent.tokenize;
state.returnStack.pop();
return state.tokenize(stream, state);
}

if (stream.eatSpace()) {
return null;
}

if (stream.eat('(')) {
state.bracketNesting += 1;
return 'punctuation';
}

if (stream.eat(')')) {
state.bracketNesting -= 1;
return 'punctuation';
}

for (var key in grammar) {
if (stream.match(grammar[key])) {
return key;
}
}

var ch = stream.next();

// single-quote string
if (ch === "'") {
return tokenSingleQuoteString(stream, state);
}

if (ch === '$') {
return tokenVariable(stream, state);
}

// double-quote string
if (ch === '"') {
return tokenDoubleQuoteString(stream, state);
}

if (ch === '<' && stream.eat('#')) {
state.tokenize = tokenComment;
return tokenComment(stream, state);
}

if (ch === '#') {
stream.skipToEnd();
return 'comment';
}

if (ch === '@') {
var quoteMatch = stream.eat(/["']/);
if (quoteMatch && stream.eol()) {
state.tokenize = tokenMultiString;
state.startQuote = quoteMatch[0];
return tokenMultiString(stream, state);
} else if (stream.peek().match(/[({]/)) {
return 'punctuation';
} else if (stream.peek().match(varNames)) {
// splatted variable
return tokenVariable(stream, state);
}
}
return 'error';
}

function tokenSingleQuoteString(stream, state) {
var ch;
while ((ch = stream.peek()) != null) {
stream.next();

if (ch === "'" && !stream.eat("'")) {
state.tokenize = tokenBase;
return 'string';
}
}

return 'error';
}

function tokenDoubleQuoteString(stream, state) {
var ch;
while ((ch = stream.peek()) != null) {
if (ch === '$') {
state.tokenize = tokenStringInterpolation;
return 'string';
}

stream.next();
if (ch === '`') {
stream.next();
continue;
}

if (ch === '"' && !stream.eat('"')) {
state.tokenize = tokenBase;
return 'string';
}
}

return 'error';
}

function tokenStringInterpolation(stream, state) {
return tokenInterpolation(stream, state, tokenDoubleQuoteString);
}

function tokenMultiStringReturn(stream, state) {
state.tokenize = tokenMultiString;
state.startQuote = '"'
return tokenMultiString(stream, state);
}

function tokenHereStringInterpolation(stream, state) {
return tokenInterpolation(stream, state, tokenMultiStringReturn);
}

function tokenInterpolation(stream, state, parentTokenize) {
if (stream.match('$(')) {
var savedBracketNesting = state.bracketNesting;
state.returnStack.push({
/*jshint loopfunc:true */
shouldReturnFrom: function(state) {
return state.bracketNesting === savedBracketNesting;
},
tokenize: parentTokenize
});
state.tokenize = tokenBase;
state.bracketNesting += 1;
return 'punctuation';
} else {
stream.next();
state.returnStack.push({
shouldReturnFrom: function() { return true; },
tokenize: parentTokenize
});
state.tokenize = tokenVariable;
return state.tokenize(stream, state);
}
}

function tokenComment(stream, state) {
var maybeEnd = false, ch;
while ((ch = stream.next()) != null) {
if (maybeEnd && ch == '>') {
state.tokenize = tokenBase;
break;
}
maybeEnd = (ch === '#');
}
return 'comment';
}

function tokenVariable(stream, state) {
var ch = stream.peek();
if (stream.eat('{')) {
state.tokenize = tokenVariableWithBraces;
return tokenVariableWithBraces(stream, state);
} else if (ch != undefined && ch.match(varNames)) {
stream.eatWhile(varNames);
state.tokenize = tokenBase;
return 'variable-2';
} else {
state.tokenize = tokenBase;
return 'error';
}
}

function tokenVariableWithBraces(stream, state) {
var ch;
while ((ch = stream.next()) != null) {
if (ch === '}') {
state.tokenize = tokenBase;
break;
}
}
return 'variable-2';
}

function tokenMultiString(stream, state) {
var quote = state.startQuote;
if (stream.sol() && stream.match(new RegExp(quote + '@'))) {
state.tokenize = tokenBase;
}
else if (quote === '"') {
while (!stream.eol()) {
var ch = stream.peek();
if (ch === '$') {
state.tokenize = tokenHereStringInterpolation;
return 'string';
}

stream.next();
if (ch === '`') {
stream.next();
}
}
}
else {
stream.skipToEnd();
}

return 'string';
}

var external = {
startState: function() {
return {
returnStack: [],
bracketNesting: 0,
tokenize: tokenBase
};
},

token: function(stream, state) {
return state.tokenize(stream, state);
},

blockCommentStart: '<#',
blockCommentEnd: '#>',
lineComment: '#',
fold: 'brace'
};
return external;
});

CodeMirror.defineMIME('application/x-powershell', 'powershell');
});
72 changes: 72 additions & 0 deletions mode/powershell/test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE

(function() {
var mode = CodeMirror.getMode({indentUnit: 2}, "powershell");
function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); }

MT('comment', '[number 1][comment # A]');
MT('comment_multiline', '[number 1][comment <#]',
'[comment ABC]',
'[comment #>][number 2]');

[
'0', '1234',
'12kb', '12mb', '12Gb', '12Tb', '12PB', '12L', '12D', '12lkb', '12dtb',
'1.234', '1.234e56', '1.', '1.e2', '.2', '.2e34',
'1.2MB', '1.kb', '.1dTB', '1.e1gb', '.2', '.2e34',
'0x1', '0xabcdef', '0x3tb', '0xelmb'
].forEach(function(number) {
MT("number_" + number, "[number " + number + "]");
});

MT('string_literal_escaping', "[string 'a''']");
MT('string_literal_variable', "[string 'a $x']");
MT('string_escaping_1', '[string "a `""]');
MT('string_escaping_2', '[string "a """]');
MT('string_variable_escaping', '[string "a `$x"]');
MT('string_variable', '[string "a ][variable-2 $x][string b"]');
MT('string_variable_spaces', '[string "a ][variable-2 ${x y}][string b"]');
MT('string_expression', '[string "a ][punctuation $(][variable-2 $x][operator +][number 3][punctuation )][string b"]');
MT('string_expression_nested', '[string "A][punctuation $(][string "a][punctuation $(][string "w"][punctuation )][string b"][punctuation )][string B"]');

MT('string_heredoc', '[string @"]',
'[string abc]',
'[string "@]');
MT('string_heredoc_quotes', '[string @"]',
'[string abc "\']',
'[string "@]');
MT('string_heredoc_variable', '[string @"]',
'[string a ][variable-2 $x][string b]',
'[string "@]');
MT('string_heredoc_nested_string', '[string @"]',
'[string a][punctuation $(][string "w"][punctuation )][string b]',
'[string "@]');
MT('string_heredoc_literal_quotes', "[string @']",
'[string abc "\']',
"[string '@]");

MT('array', "[punctuation @(][string 'a'][punctuation ,][string 'b'][punctuation )]");
MT('hash', "[punctuation @{][string 'key'][operator :][string 'value'][punctuation }]");

MT('variable', "[variable-2 $test]");
MT('variable_global', "[variable-2 $global:test]");
MT('variable_spaces', "[variable-2 ${test test}]");
MT('operator_splat', "[variable-2 @x]");
MT('variable_builtin', "[builtin $ErrorActionPreference]");
MT('variable_builtin_symbols', "[builtin $$]");

MT('operator', "[operator +]");
MT('operator_unary', "[operator +][number 3]");
MT('operator_long', "[operator -match]");

[
'(', ')', '[[', ']]', '{', '}', ',', '`', ';', '.'
].forEach(function(punctuation) {
MT("punctuation_" + punctuation.replace(/^[\[\]]/,''), "[punctuation " + punctuation + "]");
});

MT('keyword', "[keyword if]");

MT('call_builtin', "[builtin Get-ChildItem]");
})();
2 changes: 1 addition & 1 deletion mode/properties/properties.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ CodeMirror.defineMode("properties", function() {
}

if (sol) {
while(stream.eatSpace());
while(stream.eatSpace()) {}
}

var ch = stream.next();
Expand Down
2 changes: 1 addition & 1 deletion mode/puppet/puppet.js
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ CodeMirror.defineMode("puppet", function () {
if (word && words.hasOwnProperty(word)) {
// Negates the initial next()
stream.backUp(1);
// Acutally move the stream
// rs move the stream
stream.match(/[\w]+/);
// We want to process these words differently
// do to the importance they have in Puppet
Expand Down
2 changes: 1 addition & 1 deletion mode/python/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ <h2>Advanced Configuration Options:</h2>
<li>singleOperators - RegEx - Regular Expression for single operator matching, default : <pre>^[\\+\\-\\*/%&amp;|\\^~&lt;&gt;!]</pre> including <pre>@</pre> on Python 3</li>
<li>singleDelimiters - RegEx - Regular Expression for single delimiter matching, default : <pre>^[\\(\\)\\[\\]\\{\\}@,:`=;\\.]</pre></li>
<li>doubleOperators - RegEx - Regular Expression for double operators matching, default : <pre>^((==)|(!=)|(&lt;=)|(&gt;=)|(&lt;&gt;)|(&lt;&lt;)|(&gt;&gt;)|(//)|(\\*\\*))</pre></li>
<li>doubleDelimiters - RegEx - Regular Expressoin for double delimiters matching, default : <pre>^((\\+=)|(\\-=)|(\\*=)|(%=)|(/=)|(&amp;=)|(\\|=)|(\\^=))</pre></li>
<li>doubleDelimiters - RegEx - Regular Expression for double delimiters matching, default : <pre>^((\\+=)|(\\-=)|(\\*=)|(%=)|(/=)|(&amp;=)|(\\|=)|(\\^=))</pre></li>
<li>tripleDelimiters - RegEx - Regular Expression for triple delimiters matching, default : <pre>^((//=)|(&gt;&gt;=)|(&lt;&lt;=)|(\\*\\*=))</pre></li>
<li>identifiers - RegEx - Regular Expression for identifier, default : <pre>^[_A-Za-z][_A-Za-z0-9]*</pre> on Python 2 and <pre>^[_A-Za-z\u00A1-\uFFFF][_A-Za-z0-9\u00A1-\uFFFF]*</pre> on Python 3.</li>
<li>extra_keywords - list of string - List of extra words ton consider as keywords</li>
Expand Down
48 changes: 20 additions & 28 deletions mode/python/python.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,6 @@
"sorted", "staticmethod", "str", "sum", "super", "tuple",
"type", "vars", "zip", "__import__", "NotImplemented",
"Ellipsis", "__debug__"];
var py2 = {builtins: ["apply", "basestring", "buffer", "cmp", "coerce", "execfile",
"file", "intern", "long", "raw_input", "reduce", "reload",
"unichr", "unicode", "xrange", "False", "True", "None"],
keywords: ["exec", "print"]};
var py3 = {builtins: ["ascii", "bytes", "exec", "print"],
keywords: ["nonlocal", "False", "True", "None", "async", "await"]};

CodeMirror.registerHelper("hintWords", "python", commonKeywords.concat(commonBuiltins));

function top(state) {
Expand All @@ -53,15 +46,6 @@
var doubleDelimiters = parserConf.doubleDelimiters || /^(\+=|\-=|\*=|%=|\/=|&=|\|=|\^=)/;
var tripleDelimiters = parserConf.tripleDelimiters || /^(\/\/=|>>=|<<=|\*\*=)/;

if (parserConf.version && parseInt(parserConf.version, 10) == 3) {
// 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]*/;
} else {
var singleOperators = parserConf.singleOperators || /^[\+\-\*\/%&|\^~<>!]/;
var identifiers = parserConf.identifiers|| /^[_A-Za-z][_A-Za-z0-9]*/;
}

var hangingIndent = parserConf.hangingIndent || conf.indentUnit;

var myKeywords = commonKeywords, myBuiltins = commonBuiltins;
Expand All @@ -71,13 +55,21 @@
if (parserConf.extra_builtins != undefined)
myBuiltins = myBuiltins.concat(parserConf.extra_builtins);

if (parserConf.version && parseInt(parserConf.version, 10) == 3) {
myKeywords = myKeywords.concat(py3.keywords);
myBuiltins = myBuiltins.concat(py3.builtins);
var stringPrefixes = new RegExp("^(([rb]|(br))?('{3}|\"{3}|['\"]))", "i");
var py3 = parserConf.version && parseInt(parserConf.version, 10) == 3
if (py3) {
// 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]*/;
myKeywords = myKeywords.concat(["nonlocal", "False", "True", "None", "async", "await"]);
myBuiltins = myBuiltins.concat(["ascii", "bytes", "exec", "print"]);
var stringPrefixes = new RegExp("^(([rbuf]|(br))?('{3}|\"{3}|['\"]))", "i");
} else {
myKeywords = myKeywords.concat(py2.keywords);
myBuiltins = myBuiltins.concat(py2.builtins);
var singleOperators = parserConf.singleOperators || /^[\+\-\*\/%&|\^~<>!]/;
var identifiers = parserConf.identifiers|| /^[_A-Za-z][_A-Za-z0-9]*/;
myKeywords = myKeywords.concat(["exec", "print"]);
myBuiltins = myBuiltins.concat(["apply", "basestring", "buffer", "cmp", "coerce", "execfile",
"file", "intern", "long", "raw_input", "reduce", "reload",
"unichr", "unicode", "xrange", "False", "True", "None"]);
var stringPrefixes = new RegExp("^(([rub]|(ur)|(br))?('{3}|\"{3}|['\"]))", "i");
}
var keywords = wordRegexp(myKeywords);
Expand Down Expand Up @@ -249,16 +241,16 @@
}

function tokenLexer(stream, state) {
if (stream.sol()) state.beginningOfLine = true;

var style = state.tokenize(stream, state);
var current = stream.current();

// Handle decorators
if (current == "@") {
if (parserConf.version && parseInt(parserConf.version, 10) == 3)
return stream.match(identifiers, false) ? "meta" : "operator";
else
return stream.match(identifiers, false) ? "meta" : ERRORCLASS;
}
if (state.beginningOfLine && current == "@")
return stream.match(identifiers, false) ? "meta" : py3 ? "operator" : ERRORCLASS;

if (/\S/.test(current)) state.beginningOfLine = false;

if ((style == "variable" || style == "builtin")
&& state.lastToken == "meta")
Expand Down
30 changes: 30 additions & 0 deletions mode/python/test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE

(function() {
var mode = CodeMirror.getMode({indentUnit: 4},
{name: "python",
version: 3,
singleLineStringErrors: false});
function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); }

// Error, because "foobarhello" is neither a known type or property, but
// property was expected (after "and"), and it should be in parentheses.
MT("decoratorStartOfLine",
"[meta @dec]",
"[keyword def] [def function]():",
" [keyword pass]");

MT("decoratorIndented",
"[keyword class] [def Foo]:",
" [meta @dec]",
" [keyword def] [def function]():",
" [keyword pass]");

MT("matmulWithSpace:", "[variable a] [operator @] [variable b]");
MT("matmulWithoutSpace:", "[variable a][operator @][variable b]");
MT("matmulSpaceBefore:", "[variable a] [operator @][variable b]");

MT("fValidStringPrefix", "[string f'this is a {formatted} string']");
MT("uValidStringPrefix", "[string u'this is an unicode string']");
})();
81 changes: 81 additions & 0 deletions mode/sas/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
<!doctype html>

<title>CodeMirror: SAS mode</title>
<meta charset="utf-8"/>
<link rel=stylesheet href="../../doc/docs.css">

<link rel="stylesheet" href="../../lib/codemirror.css">
<script src="../../lib/codemirror.js"></script>
<script src="../xml/xml.js"></script>
<script src="sas.js"></script>
<style type="text/css">
.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}
.cm-s-default .cm-trailing-space-a:before,
.cm-s-default .cm-trailing-space-b:before {position: absolute; content: "\00B7"; color: #777;}
.cm-s-default .cm-trailing-space-new-line:before {position: absolute; content: "\21B5"; color: #777;}
</style>
<div id=nav>
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>

<ul>
<li><a href="../../index.html">Home</a>
<li><a href="../../doc/manual.html">Manual</a>
<li><a href="https://github.com/codemirror/codemirror">Code</a>
</ul>
<ul>
<li><a href="../index.html">Language modes</a>
<li><a class=active href="#">SAS</a>
</ul>
</div>

<article>
<h2>SAS mode</h2>
<form><textarea id="code" name="code">
libname foo "/tmp/foobar";
%let count=1;

/* Multi line
Comment
*/
data _null_;
x=ranuni();
* single comment;
x2=x**2;
sx=sqrt(x);
if x=x2 then put "x must be 1";
else do;
put x=;
end;
run;

/* embedded comment
* comment;
*/

proc glm data=sashelp.class;
class sex;
model weight = height sex;
run;

proc sql;
select count(*)
from sashelp.class;

create table foo as
select * from sashelp.class;

select *
from foo;
quit;
</textarea></form>

<script>
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
mode: 'sas',
lineNumbers: true
});
</script>

<p><strong>MIME types defined:</strong> <code>text/x-sas</code>.</p>

</article>
315 changes: 315 additions & 0 deletions mode/sas/sas.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion mode/sparql/sparql.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ CodeMirror.defineMode("sparql", function(config) {
"strbefore", "strafter", "year", "month", "day", "hours", "minutes", "seconds",
"timezone", "tz", "now", "uuid", "struuid", "md5", "sha1", "sha256", "sha384",
"sha512", "coalesce", "if", "strlang", "strdt", "isnumeric", "regex", "exists",
"isblank", "isliteral", "a"]);
"isblank", "isliteral", "a", "bind"]);
var keywords = wordRegexp(["base", "prefix", "select", "distinct", "reduced", "construct", "describe",
"ask", "from", "named", "where", "order", "limit", "offset", "filter", "optional",
"graph", "by", "asc", "desc", "as", "having", "undef", "values", "group",
Expand Down
5 changes: 3 additions & 2 deletions mode/sql/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,9 @@ <h2>SQL Mode for CodeMirror</h2>
<code><a href="?mime=text/x-cassandra">text/x-cassandra</a></code>,
<code><a href="?mime=text/x-plsql">text/x-plsql</a></code>,
<code><a href="?mime=text/x-mssql">text/x-mssql</a></code>,
<code><a href="?mime=text/x-hive">text/x-hive</a></code>.
<code><a href="?mime=text/x-pgsql">text/x-pgsql</a></code>.
<code><a href="?mime=text/x-hive">text/x-hive</a></code>,
<code><a href="?mime=text/x-pgsql">text/x-pgsql</a></code>,
<code><a href="?mime=text/x-gql">text/x-gql</a></code>.
</p>
<script>
window.onload = function() {
Expand Down
12 changes: 10 additions & 2 deletions mode/sql/sql.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ CodeMirror.defineMode("sql", function(config, parserConfig) {
// ref: http://dev.mysql.com/doc/refman/5.5/en/string-literals.html
return "keyword";
} else if (/^[\(\),\;\[\]]/.test(ch)) {
// no highlightning
// no highlighting
return null;
} else if (support.commentSlashSlash && ch == "/" && stream.eat("/")) {
// 1-line comment
Expand Down Expand Up @@ -341,7 +341,7 @@ CodeMirror.defineMode("sql", function(config, parserConfig) {
name: "sql",
client: set("appinfo arraysize autocommit autoprint autorecovery autotrace blockterminator break btitle cmdsep colsep compatibility compute concat copycommit copytypecheck define describe echo editfile embedded escape exec execute feedback flagger flush heading headsep instance linesize lno loboffset logsource long longchunksize markup native newpage numformat numwidth pagesize pause pno recsep recsepchar release repfooter repheader serveroutput shiftinout show showmode size spool sqlblanklines sqlcase sqlcode sqlcontinue sqlnumber sqlpluscompatibility sqlprefix sqlprompt sqlterminator suffix tab term termout time timing trimout trimspool ttitle underline verify version wrap"),
keywords: set("abort accept access add all alter and any array arraylen as asc assert assign at attributes audit authorization avg base_table begin between binary_integer body boolean by case cast char char_base check close cluster clusters colauth column comment commit compress connect connected constant constraint crash create current currval cursor data_base database date dba deallocate debugoff debugon decimal declare default definition delay delete desc digits dispose distinct do drop else elseif elsif enable end entry escape exception exception_init exchange exclusive exists exit external fast fetch file for force form from function generic goto grant group having identified if immediate in increment index indexes indicator initial initrans insert interface intersect into is key level library like limited local lock log logging long loop master maxextents maxtrans member minextents minus mislabel mode modify multiset new next no noaudit nocompress nologging noparallel not nowait number_base object of off offline on online only open option or order out package parallel partition pctfree pctincrease pctused pls_integer positive positiven pragma primary prior private privileges procedure public raise range raw read rebuild record ref references refresh release rename replace resource restrict return returning returns reverse revoke rollback row rowid rowlabel rownum rows run savepoint schema segment select separate session set share snapshot some space split sql start statement storage subtype successful synonym tabauth table tables tablespace task terminate then to trigger truncate type union unique unlimited unrecoverable unusable update use using validate value values variable view views when whenever where while with work"),
builtin: set("abs acos add_months ascii asin atan atan2 average bfile bfilename bigserial bit blob ceil character chartorowid chr clob concat convert cos cosh count dec decode deref dual dump dup_val_on_index empty error exp false float floor found glb greatest hextoraw initcap instr instrb int integer isopen last_day least lenght lenghtb ln lower lpad ltrim lub make_ref max min mlslabel mod months_between natural naturaln nchar nclob new_time next_day nextval nls_charset_decl_len nls_charset_id nls_charset_name nls_initcap nls_lower nls_sort nls_upper nlssort no_data_found notfound null number numeric nvarchar2 nvl others power rawtohex real reftohex round rowcount rowidtochar rowtype rpad rtrim serial sign signtype sin sinh smallint soundex sqlcode sqlerrm sqrt stddev string substr substrb sum sysdate tan tanh to_char text to_date to_label to_multi_byte to_number to_single_byte translate true trunc uid unlogged upper user userenv varchar varchar2 variance varying vsize xml"),
builtin: set("abs acos add_months ascii asin atan atan2 average bfile bfilename bigserial bit blob ceil character chartorowid chr clob concat convert cos cosh count dec decode deref dual dump dup_val_on_index empty error exp false float floor found glb greatest hextoraw initcap instr instrb int integer isopen last_day least length lengthb ln lower lpad ltrim lub make_ref max min mlslabel mod months_between natural naturaln nchar nclob new_time next_day nextval nls_charset_decl_len nls_charset_id nls_charset_name nls_initcap nls_lower nls_sort nls_upper nlssort no_data_found notfound null number numeric nvarchar2 nvl others power rawtohex real reftohex round rowcount rowidtochar rowtype rpad rtrim serial sign signtype sin sinh smallint soundex sqlcode sqlerrm sqrt stddev string substr substrb sum sysdate tan tanh to_char text to_date to_label to_multi_byte to_number to_single_byte translate true trunc uid unlogged upper user userenv varchar varchar2 variance varying vsize xml"),
operatorChars: /^[*+\-%<>!=~]/,
dateSQL: set("date time timestamp"),
support: set("doubleQuote nCharCast zerolessFloat binaryNumber hexNumber")
Expand Down Expand Up @@ -371,6 +371,14 @@ CodeMirror.defineMode("sql", function(config, parserConfig) {
support: set("ODBCdotTable decimallessFloat zerolessFloat binaryNumber hexNumber nCharCast charsetCast commentHash commentSpaceRequired")
});

// Google's SQL-like query language, GQL
CodeMirror.defineMIME("text/x-gql", {
name: "sql",
keywords: set("ancestor and asc by contains desc descendant distinct from group has in is limit offset on order select superset where"),
atoms: set("false true"),
builtin: set("blob datetime first key __key__ string integer double boolean null"),
operatorChars: /^[*+\-%<>!=]/
});
}());

});
Expand Down
206 changes: 78 additions & 128 deletions mode/tiddlywiki/tiddlywiki.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
! Info
CoreVersion parameter is needed for TiddlyWiki only!
***/
//{{{

(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
Expand All @@ -32,73 +31,60 @@ CodeMirror.defineMode("tiddlywiki", function () {
// Tokenizer
var textwords = {};

var keywords = function () {
function kw(type) {
return { type: type, style: "macro"};
}
return {
"allTags": kw('allTags'), "closeAll": kw('closeAll'), "list": kw('list'),
"newJournal": kw('newJournal'), "newTiddler": kw('newTiddler'),
"permaview": kw('permaview'), "saveChanges": kw('saveChanges'),
"search": kw('search'), "slider": kw('slider'), "tabs": kw('tabs'),
"tag": kw('tag'), "tagging": kw('tagging'), "tags": kw('tags'),
"tiddler": kw('tiddler'), "timeline": kw('timeline'),
"today": kw('today'), "version": kw('version'), "option": kw('option'),

"with": kw('with'),
"filter": kw('filter')
};
}();
var keywords = {
"allTags": true, "closeAll": true, "list": true,
"newJournal": true, "newTiddler": true,
"permaview": true, "saveChanges": true,
"search": true, "slider": true, "tabs": true,
"tag": true, "tagging": true, "tags": true,
"tiddler": true, "timeline": true,
"today": true, "version": true, "option": true,
"with": true, "filter": true
};

var isSpaceName = /[\w_\-]/i,
reHR = /^\-\-\-\-+$/, // <hr>
reWikiCommentStart = /^\/\*\*\*$/, // /***
reWikiCommentStop = /^\*\*\*\/$/, // ***/
reBlockQuote = /^<<<$/,
reHR = /^\-\-\-\-+$/, // <hr>
reWikiCommentStart = /^\/\*\*\*$/, // /***
reWikiCommentStop = /^\*\*\*\/$/, // ***/
reBlockQuote = /^<<<$/,

reJsCodeStart = /^\/\/\{\{\{$/, // //{{{ js block start
reJsCodeStop = /^\/\/\}\}\}$/, // //}}} js stop
reXmlCodeStart = /^<!--\{\{\{-->$/, // xml block start
reXmlCodeStop = /^<!--\}\}\}-->$/, // xml stop
reJsCodeStart = /^\/\/\{\{\{$/, // //{{{ js block start
reJsCodeStop = /^\/\/\}\}\}$/, // //}}} js stop
reXmlCodeStart = /^<!--\{\{\{-->$/, // xml block start
reXmlCodeStop = /^<!--\}\}\}-->$/, // xml stop

reCodeBlockStart = /^\{\{\{$/, // {{{ TW text div block start
reCodeBlockStop = /^\}\}\}$/, // }}} TW text stop
reCodeBlockStart = /^\{\{\{$/, // {{{ TW text div block start
reCodeBlockStop = /^\}\}\}$/, // }}} TW text stop

reUntilCodeStop = /.*?\}\}\}/;
reUntilCodeStop = /.*?\}\}\}/;

function chain(stream, state, f) {
state.tokenize = f;
return f(stream, state);
}

function jsTokenBase(stream, state) {
var sol = stream.sol(), ch;
function tokenBase(stream, state) {
var sol = stream.sol(), ch = stream.peek();

state.block = false; // indicates the start of a code block.

ch = stream.peek(); // don't eat, to make matching simpler

// check start of blocks
if (sol && /[<\/\*{}\-]/.test(ch)) {
if (stream.match(reCodeBlockStart)) {
state.block = true;
return chain(stream, state, twTokenCode);
}
if (stream.match(reBlockQuote)) {
if (stream.match(reBlockQuote))
return 'quote';
}
if (stream.match(reWikiCommentStart) || stream.match(reWikiCommentStop)) {
if (stream.match(reWikiCommentStart) || stream.match(reWikiCommentStop))
return 'comment';
}
if (stream.match(reJsCodeStart) || stream.match(reJsCodeStop) || stream.match(reXmlCodeStart) || stream.match(reXmlCodeStop)) {
if (stream.match(reJsCodeStart) || stream.match(reJsCodeStop) || stream.match(reXmlCodeStart) || stream.match(reXmlCodeStop))
return 'comment';
}
if (stream.match(reHR)) {
if (stream.match(reHR))
return 'hr';
}
} // sol
ch = stream.next();
}

stream.next();
if (sol && /[\/\*!#;:>|]/.test(ch)) {
if (ch == "!") { // tw header
stream.skipToEnd();
Expand All @@ -124,95 +110,77 @@ CodeMirror.defineMode("tiddlywiki", function () {
stream.eatWhile(">");
return "quote";
}
if (ch == '|') {
if (ch == '|')
return 'header';
}
}

if (ch == '{' && stream.match(/\{\{/)) {
if (ch == '{' && stream.match(/\{\{/))
return chain(stream, state, twTokenCode);
}

// rudimentary html:// file:// link matching. TW knows much more ...
if (/[hf]/i.test(ch)) {
if (/[ti]/i.test(stream.peek()) && stream.match(/\b(ttps?|tp|ile):\/\/[\-A-Z0-9+&@#\/%?=~_|$!:,.;]*[A-Z0-9+&@#\/%=~_|$]/i)) {
return "link";
}
}
if (/[hf]/i.test(ch) &&
/[ti]/i.test(stream.peek()) &&
stream.match(/\b(ttps?|tp|ile):\/\/[\-A-Z0-9+&@#\/%?=~_|$!:,.;]*[A-Z0-9+&@#\/%=~_|$]/i))
return "link";

// just a little string indicator, don't want to have the whole string covered
if (ch == '"') {
if (ch == '"')
return 'string';
}
if (ch == '~') { // _no_ CamelCase indicator should be bold

if (ch == '~') // _no_ CamelCase indicator should be bold
return 'brace';
}
if (/[\[\]]/.test(ch)) { // check for [[..]]
if (stream.peek() == ch) {
stream.next();
return 'brace';
}
}

if (/[\[\]]/.test(ch) && stream.match(ch)) // check for [[..]]
return 'brace';

if (ch == "@") { // check for space link. TODO fix @@...@@ highlighting
stream.eatWhile(isSpaceName);
return "link";
}

if (/\d/.test(ch)) { // numbers
stream.eatWhile(/\d/);
return "number";
}

if (ch == "/") { // tw invisible comment
if (stream.eat("%")) {
return chain(stream, state, twTokenComment);
}
else if (stream.eat("/")) { //
} else if (stream.eat("/")) { //
return chain(stream, state, twTokenEm);
}
}
if (ch == "_") { // tw underline
if (stream.eat("_")) {

if (ch == "_" && stream.eat("_")) // tw underline
return chain(stream, state, twTokenUnderline);
}
}

// strikethrough and mdash handling
if (ch == "-") {
if (stream.eat("-")) {
// if strikethrough looks ugly, change CSS.
if (stream.peek() != ' ')
return chain(stream, state, twTokenStrike);
// mdash
if (stream.peek() == ' ')
return 'brace';
}
}
if (ch == "'") { // tw bold
if (stream.eat("'")) {
return chain(stream, state, twTokenStrong);
}
}
if (ch == "<") { // tw macro
if (stream.eat("<")) {
return chain(stream, state, twTokenMacro);
}
}
else {
return null;
if (ch == "-" && stream.eat("-")) {
// if strikethrough looks ugly, change CSS.
if (stream.peek() != ' ')
return chain(stream, state, twTokenStrike);
// mdash
if (stream.peek() == ' ')
return 'brace';
}

if (ch == "'" && stream.eat("'")) // tw bold
return chain(stream, state, twTokenStrong);

if (ch == "<" && stream.eat("<")) // tw macro
return chain(stream, state, twTokenMacro);

// core macro handling
stream.eatWhile(/[\w\$_]/);
var word = stream.current(),
known = textwords.propertyIsEnumerable(word) && textwords[word];

return known ? known.style : null;
} // jsTokenBase()
return textwords.propertyIsEnumerable(stream.current()) ? "keyword" : null
}

// tw invisible comment
function twTokenComment(stream, state) {
var maybeEnd = false,
ch;
var maybeEnd = false, ch;
while (ch = stream.next()) {
if (ch == "/" && maybeEnd) {
state.tokenize = jsTokenBase;
state.tokenize = tokenBase;
break;
}
maybeEnd = (ch == "%");
Expand All @@ -226,7 +194,7 @@ CodeMirror.defineMode("tiddlywiki", function () {
ch;
while (ch = stream.next()) {
if (ch == "'" && maybeEnd) {
state.tokenize = jsTokenBase;
state.tokenize = tokenBase;
break;
}
maybeEnd = (ch == "'");
Expand All @@ -243,12 +211,12 @@ CodeMirror.defineMode("tiddlywiki", function () {
}

if (!sb && stream.match(reUntilCodeStop)) {
state.tokenize = jsTokenBase;
state.tokenize = tokenBase;
return "comment";
}

if (sb && stream.sol() && stream.match(reCodeBlockStop)) {
state.tokenize = jsTokenBase;
state.tokenize = tokenBase;
return "comment";
}

Expand All @@ -262,7 +230,7 @@ CodeMirror.defineMode("tiddlywiki", function () {
ch;
while (ch = stream.next()) {
if (ch == "/" && maybeEnd) {
state.tokenize = jsTokenBase;
state.tokenize = tokenBase;
break;
}
maybeEnd = (ch == "/");
Expand All @@ -276,7 +244,7 @@ CodeMirror.defineMode("tiddlywiki", function () {
ch;
while (ch = stream.next()) {
if (ch == "_" && maybeEnd) {
state.tokenize = jsTokenBase;
state.tokenize = tokenBase;
break;
}
maybeEnd = (ch == "_");
Expand All @@ -291,7 +259,7 @@ CodeMirror.defineMode("tiddlywiki", function () {

while (ch = stream.next()) {
if (ch == "-" && maybeEnd) {
state.tokenize = jsTokenBase;
state.tokenize = tokenBase;
break;
}
maybeEnd = (ch == "-");
Expand All @@ -301,58 +269,40 @@ CodeMirror.defineMode("tiddlywiki", function () {

// macro
function twTokenMacro(stream, state) {
var ch, word, known;

if (stream.current() == '<<') {
return 'macro';
}

ch = stream.next();
var ch = stream.next();
if (!ch) {
state.tokenize = jsTokenBase;
state.tokenize = tokenBase;
return null;
}
if (ch == ">") {
if (stream.peek() == '>') {
stream.next();
state.tokenize = jsTokenBase;
state.tokenize = tokenBase;
return "macro";
}
}

stream.eatWhile(/[\w\$_]/);
word = stream.current();
known = keywords.propertyIsEnumerable(word) && keywords[word];

if (known) {
return known.style, word;
}
else {
return null, word;
}
return keywords.propertyIsEnumerable(stream.current()) ? "keyword" : null
}

// Interface
return {
startState: function () {
return {
tokenize: jsTokenBase,
indented: 0,
level: 0
};
return {tokenize: tokenBase};
},

token: function (stream, state) {
if (stream.eatSpace()) return null;
var style = state.tokenize(stream, state);
return style;
},

electricChars: ""
}
};
});

CodeMirror.defineMIME("text/x-tiddlywiki", "tiddlywiki");
});

//}}}
2 changes: 1 addition & 1 deletion mode/verilog/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ <h2>SystemVerilog mode</h2>
Syntax highlighting and indentation for the Verilog and SystemVerilog languages (IEEE 1800).
<h2>Configuration options:</h2>
<ul>
<li><strong>noIndentKeywords</strong> - List of keywords which should not cause identation to increase. E.g. ["package", "module"]. Default: None</li>
<li><strong>noIndentKeywords</strong> - List of keywords which should not cause indentation to increase. E.g. ["package", "module"]. Default: None</li>
</ul>
</p>

Expand Down
2 changes: 1 addition & 1 deletion mode/verilog/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@
""
);

MT("covergoup_with_function_indents_properly",
MT("covergroup_with_function_indents_properly",
"[keyword covergroup] [variable cg] [keyword with] [keyword function] [variable sample][bracket (][keyword bit] [variable b][bracket )];",
" [variable c] : [keyword coverpoint] [variable c];",
"[keyword endgroup]: [variable cg]",
Expand Down
2 changes: 1 addition & 1 deletion mode/verilog/verilog.js
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ CodeMirror.defineMode("verilog", function(config, parserConfig) {
if (text == contextClosing) {
return true;
} else {
// contextClosing may be mulitple keywords separated by ;
// contextClosing may be multiple keywords separated by ;
var closingKeywords = contextClosing.split(";");
for (var i in closingKeywords) {
if (text == closingKeywords[i]) {
Expand Down
2 changes: 1 addition & 1 deletion mode/vhdl/vhdl.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ CodeMirror.defineMode("vhdl", function(config, parserConfig) {
multiLineStrings = parserConfig.multiLineStrings;

var keywords = words("abs,access,after,alias,all,and,architecture,array,assert,attribute,begin,block," +
"body,buffer,bus,case,component,configuration,constant,disconnent,downto,else,elsif,end,end block,end case," +
"body,buffer,bus,case,component,configuration,constant,disconnect,downto,else,elsif,end,end block,end case," +
"end component,end for,end generate,end if,end loop,end process,end record,end units,entity,exit,file,for," +
"function,generate,generic,generic map,group,guarded,if,impure,in,inertial,inout,is,label,library,linkage," +
"literal,loop,map,mod,nand,new,next,nor,null,of,on,open,or,others,out,package,package body,port,port map," +
Expand Down
Loading