##// END OF EJS Templates
update CodeMirror2 to 2.32
Matthias BUSSONNIER -
Show More
@@ -0,0 +1,453
1 <!doctype html>
2 <html>
3 <head>
4 <title>CodeMirror</title>
5 <link rel="stylesheet" type="text/css" href="http://fonts.googleapis.com/css?family=Droid+Sans|Droid+Sans:bold"/>
6 <link rel="stylesheet" type="text/css" href="doc/docs.css"/>
7 <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
8 <link rel="alternate" href="http://twitter.com/statuses/user_timeline/242283288.rss" type="application/rss+xml"/>
9 </head>
10 <body style="margin-top: 9em">
11
12 <div style="background: #eee; border-bottom: 2px solid #df0019; position: absolute; left: 0; top: 0; right: 0; padding: 18px 0;">
13 <div style="max-width: 64.3em; margin: 0 auto;">
14 <a href="http://www.pledgie.com/campaigns/17784">
15 <img style="width: 149px; height: 37px; vertical-align: bottom" alt='Click here to lend your support to: Fund CodeMirror development and make a donation at www.pledgie.com !' src='http://www.pledgie.com/campaigns/17784.png?skin_name=chrome' border=0/>
16 </a> &nbsp; <span style="font-size: 1.23em; font-weight: bold;">Please check out our development fundraiser.
17 </div>
18 </div>
19
20 <h1><span class="logo-braces">{ }</span> <a href="http://codemirror.net/">CodeMirror</a></h1>
21
22 <pre class="grey">
23 <img src="doc/baboon.png" class="logo" alt="logo"/>/* In-browser code editing
24 made bearable */
25 </pre>
26
27 <div class="clear"><div class="left blk">
28
29 <p style="margin-top: 0">CodeMirror is a JavaScript component that
30 provides a code editor in the browser. When a mode is available for
31 the language you are coding in, it will color your code, and
32 optionally help with indentation.</p>
33
34 <p>A <a href="doc/manual.html">rich programming API</a> and a CSS
35 theming system are available for customizing CodeMirror to fit your
36 application, and extending it with new functionality.</p>
37
38 <div class="clear"><div class="left1 blk">
39
40 <h2 style="margin-top: 0">Supported modes:</h2>
41
42 <ul>
43 <li><a href="mode/clike/index.html">C, C++, C#</a></li>
44 <li><a href="mode/clojure/index.html">Clojure</a></li>
45 <li><a href="mode/coffeescript/index.html">CoffeeScript</a></li>
46 <li><a href="mode/css/index.html">CSS</a></li>
47 <li><a href="mode/diff/index.html">diff</a></li>
48 <li><a href="mode/ecl/index.html">ECL</a></li>
49 <li><a href="mode/erlang/index.html">Erlang</a></li>
50 <li><a href="mode/go/index.html">Go</a></li>
51 <li><a href="mode/groovy/index.html">Groovy</a></li>
52 <li><a href="mode/haskell/index.html">Haskell</a></li>
53 <li><a href="mode/haxe/index.html">Haxe</a></li>
54 <li><a href="mode/htmlembedded/index.html">HTML embedded scripts</a></li>
55 <li><a href="mode/htmlmixed/index.html">HTML mixed-mode</a></li>
56 <li><a href="mode/clike/index.html">Java</a></li>
57 <li><a href="mode/javascript/index.html">JavaScript</a></li>
58 <li><a href="mode/jinja2/index.html">Jinja2</a></li>
59 <li><a href="mode/less/index.html">LESS</a></li>
60 <li><a href="mode/lua/index.html">Lua</a></li>
61 <li><a href="mode/markdown/index.html">Markdown</a> (<a href="mode/gfm/index.html">Github-flavour</a>)</li>
62 <li><a href="mode/mysql/index.html">MySQL</a></li>
63 <li><a href="mode/ntriples/index.html">NTriples</a></li>
64 <li><a href="mode/ocaml/index.html">OCaml</a></li>
65 <li><a href="mode/pascal/index.html">Pascal</a></li>
66 <li><a href="mode/perl/index.html">Perl</a></li>
67 <li><a href="mode/php/index.html">PHP</a></li>
68 <li><a href="mode/pig/index.html">Pig Latin</a></li>
69 <li><a href="mode/plsql/index.html">PL/SQL</a></li>
70 <li><a href="mode/properties/index.html">Properties files</a></li>
71 <li><a href="mode/python/index.html">Python</a></li>
72 <li><a href="mode/r/index.html">R</a></li>
73 <li>RPM <a href="mode/rpm/spec/index.html">spec</a> and <a href="mode/rpm/changes/index.html">changelog</a></li>
74 <li><a href="mode/rst/index.html">reStructuredText</a></li>
75 <li><a href="mode/ruby/index.html">Ruby</a></li>
76 <li><a href="mode/rust/index.html">Rust</a></li>
77 <li><a href="mode/clike/scala.html">Scala</a></li>
78 <li><a href="mode/scheme/index.html">Scheme</a></li>
79 <li><a href="mode/shell/index.html">Shell</a></li>
80 <li><a href="mode/smalltalk/index.html">Smalltalk</a></li>
81 <li><a href="mode/smarty/index.html">Smarty</a></li>
82 <li><a href="mode/sparql/index.html">SPARQL</a></li>
83 <li><a href="mode/stex/index.html">sTeX, LaTeX</a></li>
84 <li><a href="mode/tiddlywiki/index.html">Tiddlywiki</a></li>
85 <li><a href="mode/tiki/index.html">Tiki wiki</a></li>
86 <li><a href="mode/vb/index.html">VB.NET</a></li>
87 <li><a href="mode/vbscript/index.html">VBScript</a></li>
88 <li><a href="mode/velocity/index.html">Velocity</a></li>
89 <li><a href="mode/verilog/index.html">Verilog</a></li>
90 <li><a href="mode/xml/index.html">XML/HTML</a></li>
91 <li><a href="mode/xquery/index.html">XQuery</a></li>
92 <li><a href="mode/yaml/index.html">YAML</a></li>
93 </ul>
94
95 </div><div class="left2 blk">
96
97 <h2 style="margin-top: 0">Usage demos:</h2>
98
99 <ul>
100 <li><a href="demo/complete.html">Autocompletion</a> (<a href="demo/xmlcomplete.html">XML</a>)</li>
101 <li><a href="demo/search.html">Search/replace</a></li>
102 <li><a href="demo/folding.html">Code folding</a></li>
103 <li><a href="demo/mustache.html">Mode overlays</a></li>
104 <li><a href="demo/multiplex.html">Mode multiplexer</a></li>
105 <li><a href="demo/preview.html">HTML editor with preview</a></li>
106 <li><a href="demo/resize.html">Auto-resizing editor</a></li>
107 <li><a href="demo/marker.html">Setting breakpoints</a></li>
108 <li><a href="demo/activeline.html">Highlighting the current line</a></li>
109 <li><a href="demo/matchhighlighter.html">Highlighting selection matches</a></li>
110 <li><a href="demo/theme.html">Theming</a></li>
111 <li><a href="demo/runmode.html">Stand-alone highlighting</a></li>
112 <li><a href="demo/fullscreen.html">Full-screen editing</a></li>
113 <li><a href="demo/changemode.html">Mode auto-changing</a></li>
114 <li><a href="demo/visibletabs.html">Visible tabs</a></li>
115 <li><a href="demo/formatting.html">Autoformatting of code</a></li>
116 <li><a href="demo/emacs.html">Emacs keybindings</a></li>
117 <li><a href="demo/vim.html">Vim keybindings</a></li>
118 <li><a href="demo/closetag.html">Automatic xml tag closing</a></li>
119 <li><a href="demo/loadmode.html">Lazy mode loading</a></li>
120 </ul>
121
122 <h2>Real-world uses:</h2>
123
124 <ul>
125 <li><a href="http://jsbin.com">jsbin.com</a> (JS playground)</li>
126 <li><a href="http://www.chris-granger.com/2012/04/12/light-table---a-new-ide-concept/">Light Table</a> (experimental IDE)</li>
127 <li><a href="http://brackets.io">Adobe Brackets</a> (code editor)</li>
128 <li><a href="http://www.mergely.com/">Mergely</a> (interactive diffing)</li>
129 <li><a href="https://script.google.com/">Google Apps Script</a></li>
130 <li><a href="http://eloquentjavascript.net/chapter1.html">Eloquent JavaScript</a> (book)</li>
131 <li><a href="http://media.chikuyonok.ru/codemirror2/">Zen Coding</a> (fast XML editing)</li>
132 <li><a href="http://paperjs.org/">Paper.js</a> (graphics scripting)</li>
133 <li><a href="http://tour.golang.org">Go language tour</a></li>
134 <li><a href="http://enjalot.com/tributary/2636296/sinwaves.js">Tributary</a> (augmented editing)</li>
135 <li><a href="http://prose.io/">Prose.io</a> (github content editor)</li>
136 <li><a href="http://www.wescheme.org/">WeScheme</a> (learning tool)</li>
137 <li><a href="http://webglplayground.net/">WebGL playground</a></li>
138 <li><a href="http://ql.io/">ql.io</a> (http API query helper)</li>
139 <li><a href="http://elm-lang.org/Examples.elm">Elm language examples</a></li>
140 <li><a href="https://thefiletree.com">The File Tree</a> (collab editor)</li>
141 <li><a href="http://bluegriffon.org/">BlueGriffon</a> (HTML editor)</li>
142 <li><a href="http://www.jshint.com/">JSHint</a> (JS linter)</li>
143 <li><a href="http://kl1p.com/cmtest/1">kl1p</a> (paste service)</li>
144 <li><a href="http://sqlfiddle.com">SQLFiddle</a> (SQL playground)</li>
145 <li><a href="http://try.haxe.org">Try Haxe</a> (Haxe Playground) </li>
146 <li><a href="http://cssdeck.com/">CSSDeck</a> (CSS showcase)</li>
147 <li><a href="http://www.ckwnc.com/">CKWNC</a> (UML editor)</li>
148 <li><a href="http://www.sketchpatch.net/labs/livecodelabIntro.html">sketchPatch Livecodelab</a></li>
149 </ul>
150
151 </div></div>
152
153 <h2 id="code">Getting the code</h2>
154
155 <p>All of CodeMirror is released under a <a
156 href="LICENSE">MIT-style</a> license. To get it, you can download
157 the <a href="http://codemirror.net/codemirror.zip">latest
158 release</a> or the current <a
159 href="http://codemirror.net/codemirror2-latest.zip">development
160 snapshot</a> as zip files. To create a custom minified script file,
161 you can use the <a href="doc/compress.html">compression API</a>.</p>
162
163 <p>We use <a href="http://git-scm.com/">git</a> for version control.
164 The main repository can be fetched in this way:</p>
165
166 <pre class="code">git clone http://marijnhaverbeke.nl/git/codemirror2</pre>
167
168 <p>CodeMirror can also be found on GitHub at <a
169 href="http://github.com/marijnh/CodeMirror2">marijnh/CodeMirror2</a>.
170 If you plan to hack on the code and contribute patches, the best way
171 to do it is to create a GitHub fork, and send pull requests.</p>
172
173 <h2 id="documention">Documentation</h2>
174
175 <p>The <a href="doc/manual.html">manual</a> is your first stop for
176 learning how to use this library. It starts with a quick explanation
177 of how to use the editor, and then describes the API in detail.</p>
178
179 <p>For those who want to learn more about the code, there is
180 an <a href="doc/internals.html">overview of the internals</a> available.
181 The <a href="http://github.com/marijnh/CodeMirror2">source code</a>
182 itself is, for the most part, also well commented.</p>
183
184 <h2 id="support">Support and bug reports</h2>
185
186 <p>There is
187 a <a href="http://groups.google.com/group/codemirror">Google
188 group</a> (a sort of mailing list/newsgroup thing) for discussion
189 and news related to CodeMirror. When reporting a bug,
190 <a href="doc/reporting.html">read this first</a>. If you have
191 a <a href="http://github.com">github</a> account,
192 simply <a href="http://github.com/marijnh/CodeMirror2/issues">open
193 an issue there</a>. Otherwise, post something to
194 the <a href="http://groups.google.com/group/codemirror">group</a>,
195 or e-mail me directly: <a href="mailto:marijnh@gmail.com">Marijn
196 Haverbeke</a>.</p>
197
198 <h2 id="supported">Supported browsers</h2>
199
200 <p>The following browsers are able to run CodeMirror:</p>
201
202 <ul>
203 <li>Firefox 2 or higher</li>
204 <li>Chrome, any version</li>
205 <li>Safari 3 or higher</li>
206 <li>Opera 9 or higher (with some key-handling problems on OS X)</li>
207 <li>Internet Explorer 7 or higher in standards mode<br>
208 <em>(So not quirks mode. But quasi-standards mode with a
209 transitional doctype is also flaky. <code>&lt;!doctype
210 html></code> is recommended.)</em></li>
211 </ul>
212
213 <p>I am not actively testing against every new browser release, and
214 vendors have a habit of introducing bugs all the time, so I am
215 relying on the community to tell me when something breaks.
216 See <a href="#support">here</a> for information on how to contact
217 me.</p>
218
219 <h2 id="commercial">Commercial support</h2>
220
221 <p>CodeMirror is developed and maintained by me, Marijn Haverbeke,
222 in my own time. If your company is getting value out of CodeMirror,
223 please consider purchasing a support contract.</p>
224
225 <ul>
226 <li>You'll be funding further work on CodeMirror.</li>
227 <li>You ensure that you get a quick response when you have a
228 problem, even when I am otherwise busy.</li>
229 </ul>
230
231 <p>CodeMirror support contracts exist in two
232 forms—<strong>basic</strong> at €100 per month,
233 and <strong>premium</strong> at €500 per
234 month. <a href="mailto:marijnh@gmail.com">Contact me</a> for further
235 information.</p>
236
237 </div>
238
239 <div class="right blk">
240
241 <a href="http://codemirror.net/codemirror.zip" class="download">Download the latest release</a>
242
243 <h2>Support CodeMirror</h2>
244
245 <ul>
246 <li>Donate
247 (<span onclick="document.getElementById('paypal').submit();"
248 class="quasilink">Paypal</span>
249 or <span onclick="document.getElementById('bankinfo').style.display = 'block';"
250 class="quasilink">bank</span>)</li>
251 <li>Purchase <a href="#commercial">commercial support</a></li>
252 </ul>
253
254 <p id="bankinfo" style="display: none;">
255 Bank: <i>Rabobank</i><br/>
256 Country: <i>Netherlands</i><br/>
257 SWIFT: <i>RABONL2U</i><br/>
258 Account: <i>147850770</i><br/>
259 Name: <i>Marijn Haverbeke</i><br/>
260 IBAN: <i>NL26 RABO 0147 8507 70</i>
261 </p>
262
263 <h2>Reading material</h2>
264
265 <ul>
266 <li><a href="doc/manual.html">User manual</a></li>
267 <li><a href="http://github.com/marijnh/CodeMirror2">Browse the code</a></li>
268 </ul>
269
270 <h2 id=releases>Releases</h2>
271
272 <p class="rel">23-07-2012: <a href="http://codemirror.net/codemirror-2.32.zip">Version 2.32</a>:</p>
273
274 <p class="rel-note">Emergency fix for a bug where an editor with
275 line wrapping on IE will break when there is <em>no</em>
276 scrollbar.</p>
277
278 <p class="rel">20-07-2012: <a href="http://codemirror.net/codemirror-2.31.zip">Version 2.31</a>:</p>
279
280 <ul class="rel-note">
281 <li>New modes: <a href="mode/ocaml/index.html">OCaml</a>, <a href="mode/haxe/index.html">Haxe</a>, and <a href="mode/vb/index.html">VB.NET</a>.</li>
282 <li>Several fixes to the new scrolling model.</li>
283 <li>Add a <a href="doc/manual.html#setSize"><code>setSize</code></a> method for programmatic resizing.</li>
284 <li>Add <a href="doc/manual.html#getHistory"><code>getHistory</code></a> and <a href="doc/manual.html#setHistory"><code>setHistory</code></a> methods.</li>
285 <li>Allow custom line separator string in <a href="doc/manual.html#getValue"><code>getValue</code></a> and <a href="doc/manual.html#getRange"><code>getRange</code></a>.</li>
286 <li>Support double- and triple-click drag, double-clicking whitespace.</li>
287 <li>And more... <a href="https://github.com/marijnh/CodeMirror2/compare/v2.3...v2.31">(all patches)</a></li>
288 </ul>
289
290 <p class="rel">22-06-2012: <a href="http://codemirror.net/codemirror-2.3.zip">Version 2.3</a>:</p>
291
292 <ul class="rel-note">
293 <li><strong>New scrollbar implementation</strong>. Should flicker less. Changes DOM structure of the editor.</li>
294 <li>New theme: <a href="demo/theme.html?vibrant-ink">vibrant-ink</a>.</li>
295 <li>Many extensions to the VIM keymap (including text objects).</li>
296 <li>Add <a href="demo/multiplex.html">mode-multiplexing</a> utility script.</li>
297 <li>Fix bug where right-click paste works in read-only mode.</li>
298 <li>Add a <a href="doc/manual.html#getScrollInfo"><code>getScrollInfo</code></a> method.</li>
299 <li>Lots of other <a href="https://github.com/marijnh/CodeMirror2/compare/v2.25...v2.3">fixes</a>.</li>
300 </ul>
301
302 <p class="rel">23-05-2012: <a href="http://codemirror.net/codemirror-2.25.zip">Version 2.25</a>:</p>
303
304 <ul class="rel-note">
305 <li>New mode: <a href="mode/erlang/index.html">Erlang</a>.</li>
306 <li><strong>Remove xmlpure mode</strong> (use <a href="mode/xml/index.html">xml.js</a>).</li>
307 <li>Fix line-wrapping in Opera.</li>
308 <li>Fix X Windows middle-click paste in Chrome.</li>
309 <li>Fix bug that broke pasting of huge documents.</li>
310 <li>Fix backspace and tab key repeat in Opera.</li>
311 </ul>
312
313 <p class="rel">23-04-2012: <a href="http://codemirror.net/codemirror-2.24.zip">Version 2.24</a>:</p>
314
315 <ul class="rel-note">
316 <li><strong>Drop support for Internet Explorer 6</strong>.</li>
317 <li>New
318 modes: <a href="mode/shell/index.html">Shell</a>, <a href="mode/tiki/index.html">Tiki
319 wiki</a>, <a href="mode/pig/index.html">Pig Latin</a>.</li>
320 <li>New themes: <a href="demo/theme.html?ambiance">Ambiance</a>, <a href="demo/theme.html?blackboard">Blackboard</a>.</li>
321 <li>More control over drag/drop
322 with <a href="doc/manual.html#option_dragDrop"><code>dragDrop</code></a>
323 and <a href="doc/manual.html#option_onDragEvent"><code>onDragEvent</code></a>
324 options.</li>
325 <li>Make HTML mode a bit less pedantic.</li>
326 <li>Add <a href="doc/manual.html#compoundChange"><code>compoundChange</code></a> API method.</li>
327 <li>Several fixes in undo history and line hiding.</li>
328 <li>Remove (broken) support for <code>catchall</code> in key maps,
329 add <code>nofallthrough</code> boolean field instead.</li>
330 </ul>
331
332 <p class="rel">26-03-2012: <a href="http://codemirror.net/codemirror-2.23.zip">Version 2.23</a>:</p>
333
334 <ul class="rel-note">
335 <li>Change <strong>default binding for tab</strong> <a href="javascript:void(document.getElementById('tabbinding').style.display='')">[more]</a>
336 <div style="display: none" id=tabbinding>
337 Starting in 2.23, these bindings are default:
338 <ul><li>Tab: Insert tab character</li>
339 <li>Shift-tab: Reset line indentation to default</li>
340 <li>Ctrl/Cmd-[: Reduce line indentation (old tab behaviour)</li>
341 <li>Ctrl/Cmd-]: Increase line indentation (old shift-tab behaviour)</li>
342 </ul>
343 </div>
344 </li>
345 <li>New modes: <a href="mode/xquery/index.html">XQuery</a> and <a href="mode/vbscript/index.html">VBScript</a>.</li>
346 <li>Two new themes: <a href="mode/less/index.html">lesser-dark</a> and <a href="mode/xquery/index.html">xq-dark</a>.</li>
347 <li>Differentiate between background and text styles in <a href="doc/manual.html#setLineClass"><code>setLineClass</code></a>.</li>
348 <li>Fix drag-and-drop in IE9+.</li>
349 <li>Extend <a href="doc/manual.html#charCoords"><code>charCoords</code></a>
350 and <a href="doc/manual.html#cursorCoords"><code>cursorCoords</code></a> with a <code>mode</code> argument.</li>
351 <li>Add <a href="doc/manual.html#option_autofocus"><code>autofocus</code></a> option.</li>
352 <li>Add <a href="doc/manual.html#findMarksAt"><code>findMarksAt</code></a> method.</li>
353 </ul>
354
355 <p class="rel">27-02-2012: <a href="http://codemirror.net/codemirror-2.22.zip">Version 2.22</a>:</p>
356
357 <ul class="rel-note">
358 <li>Allow <a href="doc/manual.html#keymaps">key handlers</a> to pass up events, allow binding characters.</li>
359 <li>Add <a href="doc/manual.html#option_autoClearEmptyLines"><code>autoClearEmptyLines</code></a> option.</li>
360 <li>Properly use tab stops when rendering tabs.</li>
361 <li>Make PHP mode more robust.</li>
362 <li>Support indentation blocks in <a href="doc/manual.html#util_foldcode">code folder</a>.</li>
363 <li>Add a script for <a href="doc/manual.html#util_match-highlighter">highlighting instances of the selection</a>.</li>
364 <li>New <a href="mode/properties/index.html">.properties</a> mode.</li>
365 <li>Fix many bugs.</li>
366 </ul>
367
368 <p class="rel">27-01-2012: <a href="http://codemirror.net/codemirror-2.21.zip">Version 2.21</a>:</p>
369
370 <ul class="rel-note">
371 <li>Added <a href="mode/less/index.html">LESS</a>, <a href="mode/mysql/index.html">MySQL</a>,
372 <a href="mode/go/index.html">Go</a>, and <a href="mode/verilog/index.html">Verilog</a> modes.</li>
373 <li>Add <a href="doc/manual.html#option_smartIndent"><code>smartIndent</code></a>
374 option.</li>
375 <li>Support a cursor in <a href="doc/manual.html#option_readOnly"><code>readOnly</code></a>-mode.</li>
376 <li>Support assigning multiple styles to a token.</li>
377 <li>Use a new approach to drawing the selection.</li>
378 <li>Add <a href="doc/manual.html#scrollTo"><code>scrollTo</code></a> method.</li>
379 <li>Allow undo/redo events to span non-adjacent lines.</li>
380 <li>Lots and lots of bugfixes.</li>
381 </ul>
382
383 <p class="rel">20-12-2011: <a href="http://codemirror.net/codemirror-2.2.zip">Version 2.2</a>:</p>
384
385 <ul class="rel-note">
386 <li>Slightly incompatible API changes. Read <a href="doc/upgrade_v2.2.html">this</a>.</li>
387 <li>New approach
388 to <a href="doc/manual.html#option_extraKeys">binding</a> keys,
389 support for <a href="doc/manual.html#option_keyMap">custom
390 bindings</a>.</li>
391 <li>Support for overwrite (insert).</li>
392 <li><a href="doc/manual.html#option_tabSize">Custom-width</a>
393 and <a href="demo/visibletabs.html">stylable</a> tabs.</li>
394 <li>Moved more code into <a href="doc/manual.html#addons">add-on scripts</a>.</li>
395 <li>Support for sane vertical cursor movement in wrapped lines.</li>
396 <li>More reliable handling of
397 editing <a href="doc/manual.html#markText">marked text</a>.</li>
398 <li>Add minimal <a href="demo/emacs.html">emacs</a>
399 and <a href="demo/vim.html">vim</a> bindings.</li>
400 <li>Rename <code>coordsFromIndex</code>
401 to <a href="doc/manual.html#posFromIndex"><code>posFromIndex</code></a>,
402 add <a href="doc/manual.html#indexFromPos"><code>indexFromPos</code></a>
403 method.</li>
404 </ul>
405
406 <p class="rel">21-11-2011: <a href="http://codemirror.net/codemirror-2.18.zip">Version 2.18</a>:</p>
407 <p class="rel-note">Fixes <code>TextMarker.clear</code>, which is broken in 2.17.</p>
408
409 <p class="rel">21-11-2011: <a href="http://codemirror.net/codemirror-2.17.zip">Version 2.17</a>:</p>
410 <ul class="rel-note">
411 <li>Add support for <a href="doc/manual.html#option_lineWrapping">line
412 wrapping</a> and <a href="doc/manual.html#hideLine">code
413 folding</a>.</li>
414 <li>Add <a href="mode/gfm/index.html">Github-style Markdown</a> mode.</li>
415 <li>Add <a href="theme/monokai.css">Monokai</a>
416 and <a href="theme/rubyblue.css">Rubyblue</a> themes.</li>
417 <li>Add <a href="doc/manual.html#setBookmark"><code>setBookmark</code></a> method.</li>
418 <li>Move some of the demo code into reusable components
419 under <a href="lib/util/"><code>lib/util</code></a>.</li>
420 <li>Make screen-coord-finding code faster and more reliable.</li>
421 <li>Fix drag-and-drop in Firefox.</li>
422 <li>Improve support for IME.</li>
423 <li>Speed up content rendering.</li>
424 <li>Fix browser's built-in search in Webkit.</li>
425 <li>Make double- and triple-click work in IE.</li>
426 <li>Various fixes to modes.</li>
427 </ul>
428
429 <p class="rel">27-10-2011: <a href="http://codemirror.net/codemirror-2.16.zip">Version 2.16</a>:</p>
430 <ul class="rel-note">
431 <li>Add <a href="mode/perl/index.html">Perl</a>, <a href="mode/rust/index.html">Rust</a>, <a href="mode/tiddlywiki/index.html">TiddlyWiki</a>, and <a href="mode/groovy/index.html">Groovy</a> modes.</li>
432 <li>Dragging text inside the editor now moves, rather than copies.</li>
433 <li>Add a <a href="doc/manual.html#coordsFromIndex"><code>coordsFromIndex</code></a> method.</li>
434 <li><strong>API change</strong>: <code>setValue</code> now no longer clears history. Use <a href="doc/manual.html#clearHistory"><code>clearHistory</code></a> for that.</li>
435 <li><strong>API change</strong>: <a href="doc/manual.html#markText"><code>markText</code></a> now
436 returns an object with <code>clear</code> and <code>find</code>
437 methods. Marked text is now more robust when edited.</li>
438 <li>Fix editing code with tabs in Internet Explorer.</li>
439 </ul>
440
441 <p><a href="doc/oldrelease.html">Older releases...</a></p>
442
443 </div></div>
444
445 <div style="height: 2em">&nbsp;</div>
446
447 <form action="https://www.paypal.com/cgi-bin/webscr" method="post" id="paypal">
448 <input type="hidden" name="cmd" value="_s-xclick"/>
449 <input type="hidden" name="hosted_button_id" value="3FVHS5FGUY7CC"/>
450 </form>
451
452 </body>
453 </html>
@@ -0,0 +1,29
1 // TODO number prefixes
2 (function() {
3 // Really primitive kill-ring implementation.
4 var killRing = [];
5 function addToRing(str) {
6 killRing.push(str);
7 if (killRing.length > 50) killRing.shift();
8 }
9 function getFromRing() { return killRing[killRing.length - 1] || ""; }
10 function popFromRing() { if (killRing.length > 1) killRing.pop(); return getFromRing(); }
11
12 CodeMirror.keyMap.emacs = {
13 "Ctrl-X": function(cm) {cm.setOption("keyMap", "emacs-Ctrl-X");},
14 "Ctrl-W": function(cm) {addToRing(cm.getSelection()); cm.replaceSelection("");},
15 "Ctrl-Alt-W": function(cm) {addToRing(cm.getSelection()); cm.replaceSelection("");},
16 "Alt-W": function(cm) {addToRing(cm.getSelection());},
17 "Ctrl-Y": function(cm) {cm.replaceSelection(getFromRing());},
18 "Alt-Y": function(cm) {cm.replaceSelection(popFromRing());},
19 "Ctrl-/": "undo", "Shift-Ctrl--": "undo", "Shift-Alt-,": "goDocStart", "Shift-Alt-.": "goDocEnd",
20 "Ctrl-S": "findNext", "Ctrl-R": "findPrev", "Ctrl-G": "clearSearch", "Shift-Alt-5": "replace",
21 "Ctrl-Z": "undo", "Cmd-Z": "undo", "Alt-/": "autocomplete",
22 fallthrough: ["basic", "emacsy"]
23 };
24
25 CodeMirror.keyMap["emacs-Ctrl-X"] = {
26 "Ctrl-S": "save", "Ctrl-W": "save", "S": "saveAll", "F": "open", "U": "undo", "K": "close",
27 auto: "emacs", nofallthrough: true
28 };
29 })();
This diff has been collapsed as it changes many lines, (785 lines changed) Show them Hide them
@@ -0,0 +1,785
1 // Supported keybindings:
2 //
3 // Cursor movement:
4 // h, j, k, l
5 // e, E, w, W, b, B
6 // Ctrl-f, Ctrl-b
7 // Ctrl-n, Ctrl-p
8 // $, ^, 0
9 // G
10 // ge, gE
11 // gg
12 // f<char>, F<char>, t<char>, T<char>
13 // Ctrl-o, Ctrl-i TODO (FIXME - Ctrl-O wont work in Chrome)
14 // /, ?, n, N TODO (does not work)
15 // #, * TODO
16 //
17 // Entering insert mode:
18 // i, I, a, A, o, O
19 // s
20 // ce, cb (without support for number of actions like c3e - TODO)
21 // cc
22 // S, C TODO
23 // cf<char>, cF<char>, ct<char>, cT<char>
24 //
25 // Deleting text:
26 // x, X
27 // J
28 // dd, D
29 // de, db (without support for number of actions like d3e - TODO)
30 // df<char>, dF<char>, dt<char>, dT<char>
31 //
32 // Yanking and pasting:
33 // yy, Y
34 // p, P
35 // p'<char> TODO - test
36 // y'<char> TODO - test
37 // m<char> TODO - test
38 //
39 // Changing text in place:
40 // ~
41 // r<char>
42 //
43 // Visual mode:
44 // v, V TODO
45 //
46 // Misc:
47 // . TODO
48 //
49
50 (function() {
51 var count = "";
52 var sdir = "f";
53 var buf = "";
54 var yank = 0;
55 var mark = [];
56 var reptTimes = 0;
57 function emptyBuffer() { buf = ""; }
58 function pushInBuffer(str) { buf += str; }
59 function pushCountDigit(digit) { return function(cm) {count += digit;}; }
60 function popCount() { var i = parseInt(count, 10); count = ""; return i || 1; }
61 function iterTimes(func) {
62 for (var i = 0, c = popCount(); i < c; ++i) func(i, i == c - 1);
63 }
64 function countTimes(func) {
65 if (typeof func == "string") func = CodeMirror.commands[func];
66 return function(cm) { iterTimes(function () { func(cm); }); };
67 }
68
69 function iterObj(o, f) {
70 for (var prop in o) if (o.hasOwnProperty(prop)) f(prop, o[prop]);
71 }
72 function iterList(l, f) {
73 for (var i in l) f(l[i]);
74 }
75 function toLetter(ch) {
76 // T -> t, Shift-T -> T, '*' -> *, "Space" -> " "
77 if (ch.slice(0, 6) == "Shift-") {
78 return ch.slice(0, 1);
79 } else {
80 if (ch == "Space") return " ";
81 if (ch.length == 3 && ch[0] == "'" && ch[2] == "'") return ch[1];
82 return ch.toLowerCase();
83 }
84 }
85 var SPECIAL_SYMBOLS = "~`!@#$%^&*()_-+=[{}]\\|/?.,<>:;\"\'1234567890";
86 function toCombo(ch) {
87 // t -> T, T -> Shift-T, * -> '*', " " -> "Space"
88 if (ch == " ") return "Space";
89 var specialIdx = SPECIAL_SYMBOLS.indexOf(ch);
90 if (specialIdx != -1) return "'" + ch + "'";
91 if (ch.toLowerCase() == ch) return ch.toUpperCase();
92 return "Shift-" + ch.toUpperCase();
93 }
94
95 var word = [/\w/, /[^\w\s]/], bigWord = [/\S/];
96 function findWord(line, pos, dir, regexps) {
97 var stop = 0, next = -1;
98 if (dir > 0) { stop = line.length; next = 0; }
99 var start = stop, end = stop;
100 // Find bounds of next one.
101 outer: for (; pos != stop; pos += dir) {
102 for (var i = 0; i < regexps.length; ++i) {
103 if (regexps[i].test(line.charAt(pos + next))) {
104 start = pos;
105 for (; pos != stop; pos += dir) {
106 if (!regexps[i].test(line.charAt(pos + next))) break;
107 }
108 end = pos;
109 break outer;
110 }
111 }
112 }
113 return {from: Math.min(start, end), to: Math.max(start, end)};
114 }
115 function moveToWord(cm, regexps, dir, times, where) {
116 var cur = cm.getCursor();
117
118 for (var i = 0; i < times; i++) {
119 var line = cm.getLine(cur.line), startCh = cur.ch, word;
120 while (true) {
121 // If we're at start/end of line, start on prev/next respectivly
122 if (cur.ch == line.length && dir > 0) {
123 cur.line++;
124 cur.ch = 0;
125 line = cm.getLine(cur.line);
126 } else if (cur.ch == 0 && dir < 0) {
127 cur.line--;
128 cur.ch = line.length;
129 line = cm.getLine(cur.line);
130 }
131 if (!line) break;
132
133 // On to the actual searching
134 word = findWord(line, cur.ch, dir, regexps);
135 cur.ch = word[where == "end" ? "to" : "from"];
136 if (startCh == cur.ch && word.from != word.to) cur.ch = word[dir < 0 ? "from" : "to"];
137 else break;
138 }
139 }
140 return cur;
141 }
142 function joinLineNext(cm) {
143 var cur = cm.getCursor(), ch = cur.ch, line = cm.getLine(cur.line);
144 CodeMirror.commands.goLineEnd(cm);
145 if (cur.line != cm.lineCount()) {
146 CodeMirror.commands.goLineEnd(cm);
147 cm.replaceSelection(" ", "end");
148 CodeMirror.commands.delCharRight(cm);
149 }
150 }
151 function delTillMark(cm, cHar) {
152 var i = mark[cHar];
153 if (i === undefined) {
154 // console.log("Mark not set"); // TODO - show in status bar
155 return;
156 }
157 var l = cm.getCursor().line, start = i > l ? l : i, end = i > l ? i : l;
158 cm.setCursor(start);
159 for (var c = start; c <= end; c++) {
160 pushInBuffer("\n"+cm.getLine(start));
161 cm.removeLine(start);
162 }
163 }
164 function yankTillMark(cm, cHar) {
165 var i = mark[cHar];
166 if (i === undefined) {
167 // console.log("Mark not set"); // TODO - show in status bar
168 return;
169 }
170 var l = cm.getCursor().line, start = i > l ? l : i, end = i > l ? i : l;
171 for (var c = start; c <= end; c++) {
172 pushInBuffer("\n"+cm.getLine(c));
173 }
174 cm.setCursor(start);
175 }
176 function goLineStartText(cm) {
177 // Go to the start of the line where the text begins, or the end for whitespace-only lines
178 var cur = cm.getCursor(), firstNonWS = cm.getLine(cur.line).search(/\S/);
179 cm.setCursor(cur.line, firstNonWS == -1 ? line.length : firstNonWS, true);
180 }
181
182 function charIdxInLine(cm, cHar, motion_options) {
183 // Search for cHar in line.
184 // motion_options: {forward, inclusive}
185 // If inclusive = true, include it too.
186 // If forward = true, search forward, else search backwards.
187 // If char is not found on this line, do nothing
188 var cur = cm.getCursor(), line = cm.getLine(cur.line), idx;
189 var ch = toLetter(cHar), mo = motion_options;
190 if (mo.forward) {
191 idx = line.indexOf(ch, cur.ch + 1);
192 if (idx != -1 && mo.inclusive) idx += 1;
193 } else {
194 idx = line.lastIndexOf(ch, cur.ch);
195 if (idx != -1 && !mo.inclusive) idx += 1;
196 }
197 return idx;
198 }
199
200 function moveTillChar(cm, cHar, motion_options) {
201 // Move to cHar in line, as found by charIdxInLine.
202 var idx = charIdxInLine(cm, cHar, motion_options), cur = cm.getCursor();
203 if (idx != -1) cm.setCursor({line: cur.line, ch: idx});
204 }
205
206 function delTillChar(cm, cHar, motion_options) {
207 // delete text in this line, untill cHar is met,
208 // as found by charIdxInLine.
209 // If char is not found on this line, do nothing
210 var idx = charIdxInLine(cm, cHar, motion_options);
211 var cur = cm.getCursor();
212 if (idx !== -1) {
213 if (motion_options.forward) {
214 cm.replaceRange("", {line: cur.line, ch: cur.ch}, {line: cur.line, ch: idx});
215 } else {
216 cm.replaceRange("", {line: cur.line, ch: idx}, {line: cur.line, ch: cur.ch});
217 }
218 }
219 }
220
221 function enterInsertMode(cm) {
222 // enter insert mode: switch mode and cursor
223 popCount();
224 cm.setOption("keyMap", "vim-insert");
225 }
226
227 function dialog(cm, text, shortText, f) {
228 if (cm.openDialog) cm.openDialog(text, f);
229 else f(prompt(shortText, ""));
230 }
231 function showAlert(cm, text) {
232 if (cm.openDialog) cm.openDialog(CodeMirror.htmlEscape(text) + " <button type=button>OK</button>");
233 else alert(text);
234 }
235
236 // main keymap
237 var map = CodeMirror.keyMap.vim = {
238 // Pipe (|); TODO: should be *screen* chars, so need a util function to turn tabs into spaces?
239 "'|'": function(cm) {
240 cm.setCursor(cm.getCursor().line, popCount() - 1, true);
241 },
242 "A": function(cm) {
243 cm.setCursor(cm.getCursor().line, cm.getCursor().ch+1, true);
244 enterInsertMode(cm);
245 },
246 "Shift-A": function(cm) { CodeMirror.commands.goLineEnd(cm); enterInsertMode(cm);},
247 "I": function(cm) { enterInsertMode(cm);},
248 "Shift-I": function(cm) { goLineStartText(cm); enterInsertMode(cm);},
249 "O": function(cm) {
250 CodeMirror.commands.goLineEnd(cm);
251 CodeMirror.commands.newlineAndIndent(cm);
252 enterInsertMode(cm);
253 },
254 "Shift-O": function(cm) {
255 CodeMirror.commands.goLineStart(cm);
256 cm.replaceSelection("\n", "start");
257 cm.indentLine(cm.getCursor().line);
258 enterInsertMode(cm);
259 },
260 "G": function(cm) { cm.setOption("keyMap", "vim-prefix-g");},
261 "Shift-D": function(cm) {
262 // commented out verions works, but I left original, cause maybe
263 // I don't know vim enouth to see what it does
264 /* var cur = cm.getCursor();
265 var f = {line: cur.line, ch: cur.ch}, t = {line: cur.line};
266 pushInBuffer(cm.getRange(f, t));
267 */
268 emptyBuffer();
269 mark["Shift-D"] = cm.getCursor(false).line;
270 cm.setCursor(cm.getCursor(true).line);
271 delTillMark(cm,"Shift-D"); mark = [];
272 },
273
274 "S": function (cm) {
275 countTimes(function (_cm) {
276 CodeMirror.commands.delCharRight(_cm);
277 })(cm);
278 enterInsertMode(cm);
279 },
280 "M": function(cm) {cm.setOption("keyMap", "vim-prefix-m"); mark = [];},
281 "Y": function(cm) {cm.setOption("keyMap", "vim-prefix-y"); emptyBuffer(); yank = 0;},
282 "Shift-Y": function(cm) {
283 emptyBuffer();
284 mark["Shift-D"] = cm.getCursor(false).line;
285 cm.setCursor(cm.getCursor(true).line);
286 yankTillMark(cm,"Shift-D"); mark = [];
287 },
288 "/": function(cm) {var f = CodeMirror.commands.find; f && f(cm); sdir = "f";},
289 "'?'": function(cm) {
290 var f = CodeMirror.commands.find;
291 if (f) { f(cm); CodeMirror.commands.findPrev(cm); sdir = "r"; }
292 },
293 "N": function(cm) {
294 var fn = CodeMirror.commands.findNext;
295 if (fn) sdir != "r" ? fn(cm) : CodeMirror.commands.findPrev(cm);
296 },
297 "Shift-N": function(cm) {
298 var fn = CodeMirror.commands.findNext;
299 if (fn) sdir != "r" ? CodeMirror.commands.findPrev(cm) : fn.findNext(cm);
300 },
301 "Shift-G": function(cm) {
302 count == "" ? cm.setCursor(cm.lineCount()) : cm.setCursor(parseInt(count, 10)-1);
303 popCount();
304 CodeMirror.commands.goLineStart(cm);
305 },
306 "':'": function(cm) {
307 var exModeDialog = ': <input type="text" style="width: 90%"/>';
308 dialog(cm, exModeDialog, ':', function(command) {
309 if (command.match(/^\d+$/)) {
310 cm.setCursor(command - 1, cm.getCursor().ch);
311 } else {
312 showAlert(cm, "Bad command: " + command);
313 }
314 });
315 },
316 nofallthrough: true, style: "fat-cursor"
317 };
318
319 // standard mode switching
320 iterList(["d", "t", "T", "f", "F", "c", "r"],
321 function (ch) {
322 CodeMirror.keyMap.vim[toCombo(ch)] = function (cm) {
323 cm.setOption("keyMap", "vim-prefix-" + ch);
324 emptyBuffer();
325 };
326 });
327
328 function addCountBindings(keyMap) {
329 // Add bindings for number keys
330 keyMap["0"] = function(cm) {
331 count.length > 0 ? pushCountDigit("0")(cm) : CodeMirror.commands.goLineStart(cm);
332 };
333 for (var i = 1; i < 10; ++i) keyMap[i] = pushCountDigit(i);
334 }
335 addCountBindings(CodeMirror.keyMap.vim);
336
337 // main num keymap
338 // Add bindings that are influenced by number keys
339 iterObj({
340 "Left": "goColumnLeft", "Right": "goColumnRight",
341 "Down": "goLineDown", "Up": "goLineUp", "Backspace": "goCharLeft",
342 "Space": "goCharRight",
343 "X": function(cm) {CodeMirror.commands.delCharRight(cm);},
344 "P": function(cm) {
345 var cur = cm.getCursor().line;
346 if (buf!= "") {
347 if (buf[0] == "\n") CodeMirror.commands.goLineEnd(cm);
348 cm.replaceRange(buf, cm.getCursor());
349 }
350 },
351 "Shift-X": function(cm) {CodeMirror.commands.delCharLeft(cm);},
352 "Shift-J": function(cm) {joinLineNext(cm);},
353 "Shift-P": function(cm) {
354 var cur = cm.getCursor().line;
355 if (buf!= "") {
356 CodeMirror.commands.goLineUp(cm);
357 CodeMirror.commands.goLineEnd(cm);
358 cm.replaceSelection(buf, "end");
359 }
360 cm.setCursor(cur+1);
361 },
362 "'~'": function(cm) {
363 var cur = cm.getCursor(), cHar = cm.getRange({line: cur.line, ch: cur.ch}, {line: cur.line, ch: cur.ch+1});
364 cHar = cHar != cHar.toLowerCase() ? cHar.toLowerCase() : cHar.toUpperCase();
365 cm.replaceRange(cHar, {line: cur.line, ch: cur.ch}, {line: cur.line, ch: cur.ch+1});
366 cm.setCursor(cur.line, cur.ch+1);
367 },
368 "Ctrl-B": function(cm) {CodeMirror.commands.goPageUp(cm);},
369 "Ctrl-F": function(cm) {CodeMirror.commands.goPageDown(cm);},
370 "Ctrl-P": "goLineUp", "Ctrl-N": "goLineDown",
371 "U": "undo", "Ctrl-R": "redo"
372 }, function(key, cmd) { map[key] = countTimes(cmd); });
373
374 // empty key maps
375 iterList([
376 "vim-prefix-d'",
377 "vim-prefix-y'",
378 "vim-prefix-df",
379 "vim-prefix-dF",
380 "vim-prefix-dt",
381 "vim-prefix-dT",
382 "vim-prefix-c",
383 "vim-prefix-cf",
384 "vim-prefix-cF",
385 "vim-prefix-ct",
386 "vim-prefix-cT",
387 "vim-prefix-",
388 "vim-prefix-f",
389 "vim-prefix-F",
390 "vim-prefix-t",
391 "vim-prefix-T",
392 "vim-prefix-r",
393 "vim-prefix-m"
394 ],
395 function (prefix) {
396 CodeMirror.keyMap[prefix] = {
397 auto: "vim",
398 nofallthrough: true,
399 style: "fat-cursor"
400 };
401 });
402
403 CodeMirror.keyMap["vim-prefix-g"] = {
404 "E": countTimes(function(cm) { cm.setCursor(moveToWord(cm, word, -1, 1, "start"));}),
405 "Shift-E": countTimes(function(cm) { cm.setCursor(moveToWord(cm, bigWord, -1, 1, "start"));}),
406 "G": function (cm) { cm.setCursor({line: 0, ch: cm.getCursor().ch});},
407 auto: "vim", nofallthrough: true, style: "fat-cursor"
408 };
409
410 CodeMirror.keyMap["vim-prefix-d"] = {
411 "D": countTimes(function(cm) {
412 pushInBuffer("\n"+cm.getLine(cm.getCursor().line));
413 cm.removeLine(cm.getCursor().line);
414 cm.setOption("keyMap", "vim");
415 }),
416 "'": function(cm) {
417 cm.setOption("keyMap", "vim-prefix-d'");
418 emptyBuffer();
419 },
420 "B": function(cm) {
421 var cur = cm.getCursor();
422 var line = cm.getLine(cur.line);
423 var index = line.lastIndexOf(" ", cur.ch);
424
425 pushInBuffer(line.substring(index, cur.ch));
426 cm.replaceRange("", {line: cur.line, ch: index}, cur);
427 cm.setOption("keyMap", "vim");
428 },
429 nofallthrough: true, style: "fat-cursor"
430 };
431 // FIXME - does not work for bindings like "d3e"
432 addCountBindings(CodeMirror.keyMap["vim-prefix-d"]);
433
434 CodeMirror.keyMap["vim-prefix-c"] = {
435 "B": function (cm) {
436 countTimes("delWordLeft")(cm);
437 enterInsertMode(cm);
438 },
439 "C": function (cm) {
440 iterTimes(function (i, last) {
441 CodeMirror.commands.deleteLine(cm);
442 if (i) {
443 CodeMirror.commands.delCharRight(cm);
444 if (last) CodeMirror.commands.deleteLine(cm);
445 }
446 });
447 enterInsertMode(cm);
448 },
449 nofallthrough: true, style: "fat-cursor"
450 };
451
452 iterList(["vim-prefix-d", "vim-prefix-c", "vim-prefix-"], function (prefix) {
453 iterList(["f", "F", "T", "t"],
454 function (ch) {
455 CodeMirror.keyMap[prefix][toCombo(ch)] = function (cm) {
456 cm.setOption("keyMap", prefix + ch);
457 emptyBuffer();
458 };
459 });
460 });
461
462 var MOTION_OPTIONS = {
463 "t": {inclusive: false, forward: true},
464 "f": {inclusive: true, forward: true},
465 "T": {inclusive: false, forward: false},
466 "F": {inclusive: true, forward: false}
467 };
468
469 function setupPrefixBindingForKey(m) {
470 CodeMirror.keyMap["vim-prefix-m"][m] = function(cm) {
471 mark[m] = cm.getCursor().line;
472 };
473 CodeMirror.keyMap["vim-prefix-d'"][m] = function(cm) {
474 delTillMark(cm,m);
475 };
476 CodeMirror.keyMap["vim-prefix-y'"][m] = function(cm) {
477 yankTillMark(cm,m);
478 };
479 CodeMirror.keyMap["vim-prefix-r"][m] = function (cm) {
480 var cur = cm.getCursor();
481 cm.replaceRange(toLetter(m),
482 {line: cur.line, ch: cur.ch},
483 {line: cur.line, ch: cur.ch + 1});
484 CodeMirror.commands.goColumnLeft(cm);
485 };
486 // all commands, related to motions till char in line
487 iterObj(MOTION_OPTIONS, function (ch, options) {
488 CodeMirror.keyMap["vim-prefix-" + ch][m] = function(cm) {
489 moveTillChar(cm, m, options);
490 };
491 CodeMirror.keyMap["vim-prefix-d" + ch][m] = function(cm) {
492 delTillChar(cm, m, options);
493 };
494 CodeMirror.keyMap["vim-prefix-c" + ch][m] = function(cm) {
495 delTillChar(cm, m, options);
496 enterInsertMode(cm);
497 };
498 });
499 }
500 for (var i = 65; i < 65 + 26; i++) { // uppercase alphabet char codes
501 var ch = String.fromCharCode(i);
502 setupPrefixBindingForKey(toCombo(ch));
503 setupPrefixBindingForKey(toCombo(ch.toLowerCase()));
504 }
505 iterList(SPECIAL_SYMBOLS, function (ch) {
506 setupPrefixBindingForKey(toCombo(ch));
507 });
508 setupPrefixBindingForKey("Space");
509
510 CodeMirror.keyMap["vim-prefix-y"] = {
511 "Y": countTimes(function(cm) { pushInBuffer("\n"+cm.getLine(cm.getCursor().line+yank)); yank++; }),
512 "'": function(cm) {cm.setOption("keyMap", "vim-prefix-y'"); emptyBuffer();},
513 nofallthrough: true, style: "fat-cursor"
514 };
515
516 CodeMirror.keyMap["vim-insert"] = {
517 // TODO: override navigation keys so that Esc will cancel automatic indentation from o, O, i_<CR>
518 "Esc": function(cm) {
519 cm.setCursor(cm.getCursor().line, cm.getCursor().ch-1, true);
520 cm.setOption("keyMap", "vim");
521 },
522 "Ctrl-N": "autocomplete",
523 "Ctrl-P": "autocomplete",
524 fallthrough: ["default"]
525 };
526
527 function findMatchedSymbol(cm, cur, symb) {
528 var line = cur.line;
529 var symb = symb ? symb : cm.getLine(line)[cur.ch];
530
531 // Are we at the opening or closing char
532 var forwards = ['(', '[', '{'].indexOf(symb) != -1;
533
534 var reverseSymb = (function(sym) {
535 switch (sym) {
536 case '(' : return ')';
537 case '[' : return ']';
538 case '{' : return '}';
539 case ')' : return '(';
540 case ']' : return '[';
541 case '}' : return '{';
542 default : return null;
543 }
544 })(symb);
545
546 // Couldn't find a matching symbol, abort
547 if (reverseSymb == null) return cur;
548
549 // Tracking our imbalance in open/closing symbols. An opening symbol wii be
550 // the first thing we pick up if moving forward, this isn't true moving backwards
551 var disBal = forwards ? 0 : 1;
552
553 while (true) {
554 if (line == cur.line) {
555 // First pass, do some special stuff
556 var currLine = forwards ? cm.getLine(line).substr(cur.ch).split('') : cm.getLine(line).substr(0,cur.ch).split('').reverse();
557 } else {
558 var currLine = forwards ? cm.getLine(line).split('') : cm.getLine(line).split('').reverse();
559 }
560
561 for (var index = 0; index < currLine.length; index++) {
562 if (currLine[index] == symb) disBal++;
563 else if (currLine[index] == reverseSymb) disBal--;
564
565 if (disBal == 0) {
566 if (forwards && cur.line == line) return {line: line, ch: index + cur.ch};
567 else if (forwards) return {line: line, ch: index};
568 else return {line: line, ch: currLine.length - index - 1 };
569 }
570 }
571
572 if (forwards) line++;
573 else line--;
574 }
575 }
576
577 function selectCompanionObject(cm, revSymb, inclusive) {
578 var cur = cm.getCursor();
579
580 var end = findMatchedSymbol(cm, cur, revSymb);
581 var start = findMatchedSymbol(cm, end);
582 start.ch += inclusive ? 1 : 0;
583 end.ch += inclusive ? 0 : 1;
584
585 return {start: start, end: end};
586 }
587
588 // These are our motion commands to be used for navigation and selection with
589 // certian other commands. All should return a cursor object.
590 var motionList = ['B', 'E', 'J', 'K', 'H', 'L', 'W', 'Shift-W', "'^'", "'$'", "'%'", 'Esc'];
591
592 motions = {
593 'B': function(cm, times) { return moveToWord(cm, word, -1, times); },
594 'Shift-B': function(cm, times) { return moveToWord(cm, bigWord, -1, times); },
595 'E': function(cm, times) { return moveToWord(cm, word, 1, times, 'end'); },
596 'Shift-E': function(cm, times) { return moveToWord(cm, bigWord, 1, times, 'end'); },
597 'J': function(cm, times) {
598 var cur = cm.getCursor();
599 return {line: cur.line+times, ch : cur.ch};
600 },
601
602 'K': function(cm, times) {
603 var cur = cm.getCursor();
604 return {line: cur.line-times, ch: cur.ch};
605 },
606
607 'H': function(cm, times) {
608 var cur = cm.getCursor();
609 return {line: cur.line, ch: cur.ch-times};
610 },
611
612 'L': function(cm, times) {
613 var cur = cm.getCursor();
614 return {line: cur.line, ch: cur.ch+times};
615 },
616 'W': function(cm, times) { return moveToWord(cm, word, 1, times); },
617 'Shift-W': function(cm, times) { return moveToWord(cm, bigWord, 1, times); },
618 "'^'": function(cm, times) {
619 var cur = cm.getCursor();
620 var line = cm.getLine(cur.line).split('');
621
622 // Empty line :o
623 if (line.length == 0) return cur;
624
625 for (var index = 0; index < line.length; index++) {
626 if (line[index].match(/[^\s]/)) return {line: cur.line, ch: index};
627 }
628 },
629 "'$'": function(cm) {
630 var cur = cm.getCursor();
631 var line = cm.getLine(cur.line);
632 return {line: cur.line, ch: line.length};
633 },
634 "'%'": function(cm) { return findMatchedSymbol(cm, cm.getCursor()); },
635 "Esc" : function(cm) {
636 cm.setOption('vim');
637 reptTimes = 0;
638
639 return cm.getCursor();
640 }
641 };
642
643 // Map our movement actions each operator and non-operational movement
644 motionList.forEach(function(key, index, array) {
645 CodeMirror.keyMap['vim-prefix-d'][key] = function(cm) {
646 // Get our selected range
647 var start = cm.getCursor();
648 var end = motions[key](cm, reptTimes ? reptTimes : 1);
649
650 // Set swap var if range is of negative length
651 if ((start.line > end.line) || (start.line == end.line && start.ch > end.ch)) var swap = true;
652
653 // Take action, switching start and end if swap var is set
654 pushInBuffer(cm.getRange(swap ? end : start, swap ? start : end));
655 cm.replaceRange("", swap ? end : start, swap ? start : end);
656
657 // And clean up
658 reptTimes = 0;
659 cm.setOption("keyMap", "vim");
660 };
661
662 CodeMirror.keyMap['vim-prefix-c'][key] = function(cm) {
663 var start = cm.getCursor();
664 var end = motions[key](cm, reptTimes ? reptTimes : 1);
665
666 if ((start.line > end.line) || (start.line == end.line && start.ch > end.ch)) var swap = true;
667 pushInBuffer(cm.getRange(swap ? end : start, swap ? start : end));
668 cm.replaceRange("", swap ? end : start, swap ? start : end);
669
670 reptTimes = 0;
671 cm.setOption('keyMap', 'vim-insert');
672 };
673
674 CodeMirror.keyMap['vim-prefix-y'][key] = function(cm) {
675 var start = cm.getCursor();
676 var end = motions[key](cm, reptTimes ? reptTimes : 1);
677
678 if ((start.line > end.line) || (start.line == end.line && start.ch > end.ch)) var swap = true;
679 pushInBuffer(cm.getRange(swap ? end : start, swap ? start : end));
680
681 reptTimes = 0;
682 cm.setOption("keyMap", "vim");
683 };
684
685 CodeMirror.keyMap['vim'][key] = function(cm) {
686 var cur = motions[key](cm, reptTimes ? reptTimes : 1);
687 cm.setCursor(cur.line, cur.ch);
688
689 reptTimes = 0;
690 };
691 });
692
693 var nums = [1,2,3,4,5,6,7,8,9];
694 nums.forEach(function(key, index, array) {
695 CodeMirror.keyMap['vim'][key] = function (cm) {
696 reptTimes = (reptTimes * 10) + key;
697 };
698 CodeMirror.keyMap['vim-prefix-d'][key] = function (cm) {
699 reptTimes = (reptTimes * 10) + key;
700 };
701 CodeMirror.keyMap['vim-prefix-y'][key] = function (cm) {
702 reptTimes = (reptTimes * 10) + key;
703 };
704 CodeMirror.keyMap['vim-prefix-c'][key] = function (cm) {
705 reptTimes = (reptTimes * 10) + key;
706 };
707 });
708
709 // Create our keymaps for each operator and make xa and xi where x is an operator
710 // change to the corrosponding keymap
711 var operators = ['d', 'y', 'c'];
712 operators.forEach(function(key, index, array) {
713 CodeMirror.keyMap['vim-prefix-'+key+'a'] = {
714 auto: 'vim', nofallthrough: true, style: "fat-cursor"
715 };
716 CodeMirror.keyMap['vim-prefix-'+key+'i'] = {
717 auto: 'vim', nofallthrough: true, style: "fat-cursor"
718 };
719
720 CodeMirror.keyMap['vim-prefix-'+key]['A'] = function(cm) {
721 reptTimes = 0;
722 cm.setOption('keyMap', 'vim-prefix-' + key + 'a');
723 };
724
725 CodeMirror.keyMap['vim-prefix-'+key]['I'] = function(cm) {
726 reptTimes = 0;
727 cm.setOption('keyMap', 'vim-prefix-' + key + 'i');
728 };
729 });
730
731 function regexLastIndexOf(string, pattern, startIndex) {
732 for (var i = startIndex == null ? string.length : startIndex; i >= 0; --i)
733 if (pattern.test(string.charAt(i))) return i;
734 return -1;
735 }
736
737 // Create our text object functions. They work similar to motions but they
738 // return a start cursor as well
739 var textObjectList = ['W', 'Shift-[', 'Shift-9', '['];
740 var textObjects = {
741 'W': function(cm, inclusive) {
742 var cur = cm.getCursor();
743 var line = cm.getLine(cur.line);
744
745 var line_to_char = new String(line.substring(0, cur.ch));
746 var start = regexLastIndexOf(line_to_char, /[^a-zA-Z0-9]/) + 1;
747 var end = motions["E"](cm, 1) ;
748
749 end.ch += inclusive ? 1 : 0 ;
750 return {start: {line: cur.line, ch: start}, end: end };
751 },
752 'Shift-[': function(cm, inclusive) { return selectCompanionObject(cm, '}', inclusive); },
753 'Shift-9': function(cm, inclusive) { return selectCompanionObject(cm, ')', inclusive); },
754 '[': function(cm, inclusive) { return selectCompanionObject(cm, ']', inclusive); }
755 };
756
757 // One function to handle all operation upon text objects. Kinda funky but it works
758 // better than rewriting this code six times
759 function textObjectManipulation(cm, object, remove, insert, inclusive) {
760 // Object is the text object, delete object if remove is true, enter insert
761 // mode if insert is true, inclusive is the difference between a and i
762 var tmp = textObjects[object](cm, inclusive);
763 var start = tmp.start;
764 var end = tmp.end;
765
766 if ((start.line > end.line) || (start.line == end.line && start.ch > end.ch)) var swap = true ;
767
768 pushInBuffer(cm.getRange(swap ? end : start, swap ? start : end));
769 if (remove) cm.replaceRange("", swap ? end : start, swap ? start : end);
770 if (insert) cm.setOption('keyMap', 'vim-insert');
771 }
772
773 // And finally build the keymaps up from the text objects
774 for (var i = 0; i < textObjectList.length; ++i) {
775 var object = textObjectList[i];
776 (function(object) {
777 CodeMirror.keyMap['vim-prefix-di'][object] = function(cm) { textObjectManipulation(cm, object, true, false, false); };
778 CodeMirror.keyMap['vim-prefix-da'][object] = function(cm) { textObjectManipulation(cm, object, true, false, true); };
779 CodeMirror.keyMap['vim-prefix-yi'][object] = function(cm) { textObjectManipulation(cm, object, false, false, false); };
780 CodeMirror.keyMap['vim-prefix-ya'][object] = function(cm) { textObjectManipulation(cm, object, false, false, true); };
781 CodeMirror.keyMap['vim-prefix-ci'][object] = function(cm) { textObjectManipulation(cm, object, true, true, false); };
782 CodeMirror.keyMap['vim-prefix-ca'][object] = function(cm) { textObjectManipulation(cm, object, true, true, true); };
783 })(object)
784 }
785 })();
@@ -0,0 +1,164
1 /**
2 * Tag-closer extension for CodeMirror.
3 *
4 * This extension adds a "closeTag" utility function that can be used with key bindings to
5 * insert a matching end tag after the ">" character of a start tag has been typed. It can
6 * also complete "</" if a matching start tag is found. It will correctly ignore signal
7 * characters for empty tags, comments, CDATA, etc.
8 *
9 * The function depends on internal parser state to identify tags. It is compatible with the
10 * following CodeMirror modes and will ignore all others:
11 * - htmlmixed
12 * - xml
13 *
14 * See demos/closetag.html for a usage example.
15 *
16 * @author Nathan Williams <nathan@nlwillia.net>
17 * Contributed under the same license terms as CodeMirror.
18 */
19 (function() {
20 /** Option that allows tag closing behavior to be toggled. Default is true. */
21 CodeMirror.defaults['closeTagEnabled'] = true;
22
23 /** Array of tag names to add indentation after the start tag for. Default is the list of block-level html tags. */
24 CodeMirror.defaults['closeTagIndent'] = ['applet', 'blockquote', 'body', 'button', 'div', 'dl', 'fieldset', 'form', 'frameset', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'html', 'iframe', 'layer', 'legend', 'object', 'ol', 'p', 'select', 'table', 'ul'];
25
26 /** Array of tag names where an end tag is forbidden. */
27 CodeMirror.defaults['closeTagVoid'] = ['area', 'base', 'br', 'col', 'command', 'embed', 'hr', 'img', 'input', 'keygen', 'link', 'meta', 'param', 'source', 'track', 'wbr'];
28
29 /**
30 * Call during key processing to close tags. Handles the key event if the tag is closed, otherwise throws CodeMirror.Pass.
31 * - cm: The editor instance.
32 * - ch: The character being processed.
33 * - indent: Optional. An array of tag names to indent when closing. Omit or pass true to use the default indentation tag list defined in the 'closeTagIndent' option.
34 * Pass false to disable indentation. Pass an array to override the default list of tag names.
35 * - vd: Optional. An array of tag names that should not be closed. Omit to use the default void (end tag forbidden) tag list defined in the 'closeTagVoid' option. Ignored in xml mode.
36 */
37 CodeMirror.defineExtension("closeTag", function(cm, ch, indent, vd) {
38 if (!cm.getOption('closeTagEnabled')) {
39 throw CodeMirror.Pass;
40 }
41
42 var mode = cm.getOption('mode');
43
44 if (mode == 'text/html' || mode == 'xml') {
45
46 /*
47 * Relevant structure of token:
48 *
49 * htmlmixed
50 * className
51 * state
52 * htmlState
53 * type
54 * tagName
55 * context
56 * tagName
57 * mode
58 *
59 * xml
60 * className
61 * state
62 * tagName
63 * type
64 */
65
66 var pos = cm.getCursor();
67 var tok = cm.getTokenAt(pos);
68 var state = tok.state;
69
70 if (state.mode && state.mode != 'html') {
71 throw CodeMirror.Pass; // With htmlmixed, we only care about the html sub-mode.
72 }
73
74 if (ch == '>') {
75 var type = state.htmlState ? state.htmlState.type : state.type; // htmlmixed : xml
76
77 if (tok.className == 'tag' && type == 'closeTag') {
78 throw CodeMirror.Pass; // Don't process the '>' at the end of an end-tag.
79 }
80
81 cm.replaceSelection('>'); // Mode state won't update until we finish the tag.
82 pos = {line: pos.line, ch: pos.ch + 1};
83 cm.setCursor(pos);
84
85 tok = cm.getTokenAt(cm.getCursor());
86 state = tok.state;
87 type = state.htmlState ? state.htmlState.type : state.type; // htmlmixed : xml
88
89 if (tok.className == 'tag' && type != 'selfcloseTag') {
90 var tagName = state.htmlState ? state.htmlState.tagName : state.tagName; // htmlmixed : xml
91 if (tagName.length > 0 && shouldClose(cm, vd, tagName)) {
92 insertEndTag(cm, indent, pos, tagName);
93 }
94 return;
95 }
96
97 // Undo the '>' insert and allow cm to handle the key instead.
98 cm.setSelection({line: pos.line, ch: pos.ch - 1}, pos);
99 cm.replaceSelection("");
100
101 } else if (ch == '/') {
102 if (tok.className == 'tag' && tok.string == '<') {
103 var tagName = state.htmlState ? (state.htmlState.context ? state.htmlState.context.tagName : '') : (state.context ? state.context.tagName : ''); // htmlmixed : xml
104 if (tagName.length > 0) {
105 completeEndTag(cm, pos, tagName);
106 return;
107 }
108 }
109 }
110
111 }
112
113 throw CodeMirror.Pass; // Bubble if not handled
114 });
115
116 function insertEndTag(cm, indent, pos, tagName) {
117 if (shouldIndent(cm, indent, tagName)) {
118 cm.replaceSelection('\n\n</' + tagName + '>', 'end');
119 cm.indentLine(pos.line + 1);
120 cm.indentLine(pos.line + 2);
121 cm.setCursor({line: pos.line + 1, ch: cm.getLine(pos.line + 1).length});
122 } else {
123 cm.replaceSelection('</' + tagName + '>');
124 cm.setCursor(pos);
125 }
126 }
127
128 function shouldIndent(cm, indent, tagName) {
129 if (typeof indent == 'undefined' || indent == null || indent == true) {
130 indent = cm.getOption('closeTagIndent');
131 }
132 if (!indent) {
133 indent = [];
134 }
135 return indexOf(indent, tagName.toLowerCase()) != -1;
136 }
137
138 function shouldClose(cm, vd, tagName) {
139 if (cm.getOption('mode') == 'xml') {
140 return true; // always close xml tags
141 }
142 if (typeof vd == 'undefined' || vd == null) {
143 vd = cm.getOption('closeTagVoid');
144 }
145 if (!vd) {
146 vd = [];
147 }
148 return indexOf(vd, tagName.toLowerCase()) == -1;
149 }
150
151 // C&P from codemirror.js...would be nice if this were visible to utilities.
152 function indexOf(collection, elt) {
153 if (collection.indexOf) return collection.indexOf(elt);
154 for (var i = 0, e = collection.length; i < e; ++i)
155 if (collection[i] == elt) return i;
156 return -1;
157 }
158
159 function completeEndTag(cm, pos, tagName) {
160 cm.replaceSelection('/' + tagName + '>');
161 cm.setCursor({line: pos.line, ch: pos.ch + tagName.length + 2 });
162 }
163
164 })();
@@ -0,0 +1,51
1 (function() {
2 if (!CodeMirror.modeURL) CodeMirror.modeURL = "../mode/%N/%N.js";
3
4 var loading = {};
5 function splitCallback(cont, n) {
6 var countDown = n;
7 return function() { if (--countDown == 0) cont(); }
8 }
9 function ensureDeps(mode, cont) {
10 var deps = CodeMirror.modes[mode].dependencies;
11 if (!deps) return cont();
12 var missing = [];
13 for (var i = 0; i < deps.length; ++i) {
14 if (!CodeMirror.modes.hasOwnProperty(deps[i]))
15 missing.push(deps[i]);
16 }
17 if (!missing.length) return cont();
18 var split = splitCallback(cont, missing.length);
19 for (var i = 0; i < missing.length; ++i)
20 CodeMirror.requireMode(missing[i], split);
21 }
22
23 CodeMirror.requireMode = function(mode, cont) {
24 if (typeof mode != "string") mode = mode.name;
25 if (CodeMirror.modes.hasOwnProperty(mode)) return ensureDeps(mode, cont);
26 if (loading.hasOwnProperty(mode)) return loading[mode].push(cont);
27
28 var script = document.createElement("script");
29 script.src = CodeMirror.modeURL.replace(/%N/g, mode);
30 var others = document.getElementsByTagName("script")[0];
31 others.parentNode.insertBefore(script, others);
32 var list = loading[mode] = [cont];
33 var count = 0, poll = setInterval(function() {
34 if (++count > 100) return clearInterval(poll);
35 if (CodeMirror.modes.hasOwnProperty(mode)) {
36 clearInterval(poll);
37 loading[mode] = null;
38 ensureDeps(mode, function() {
39 for (var i = 0; i < list.length; ++i) list[i]();
40 });
41 }
42 }, 200);
43 };
44
45 CodeMirror.autoLoadMode = function(instance, mode) {
46 if (!CodeMirror.modes.hasOwnProperty(mode))
47 CodeMirror.requireMode(mode, function() {
48 instance.setOption("mode", instance.getOption("mode"));
49 });
50 };
51 }());
@@ -0,0 +1,44
1 // Define match-highlighter commands. Depends on searchcursor.js
2 // Use by attaching the following function call to the onCursorActivity event:
3 //myCodeMirror.matchHighlight(minChars);
4 // And including a special span.CodeMirror-matchhighlight css class (also optionally a separate one for .CodeMirror-focused -- see demo matchhighlighter.html)
5
6 (function() {
7 var DEFAULT_MIN_CHARS = 2;
8
9 function MatchHighlightState() {
10 this.marked = [];
11 }
12 function getMatchHighlightState(cm) {
13 return cm._matchHighlightState || (cm._matchHighlightState = new MatchHighlightState());
14 }
15
16 function clearMarks(cm) {
17 var state = getMatchHighlightState(cm);
18 for (var i = 0; i < state.marked.length; ++i)
19 state.marked[i].clear();
20 state.marked = [];
21 }
22
23 function markDocument(cm, className, minChars) {
24 clearMarks(cm);
25 minChars = (typeof minChars !== 'undefined' ? minChars : DEFAULT_MIN_CHARS);
26 if (cm.somethingSelected() && cm.getSelection().replace(/^\s+|\s+$/g, "").length >= minChars) {
27 var state = getMatchHighlightState(cm);
28 var query = cm.getSelection();
29 cm.operation(function() {
30 if (cm.lineCount() < 2000) { // This is too expensive on big documents.
31 for (var cursor = cm.getSearchCursor(query); cursor.findNext();) {
32 //Only apply matchhighlight to the matches other than the one actually selected
33 if (!(cursor.from().line === cm.getCursor(true).line && cursor.from().ch === cm.getCursor(true).ch))
34 state.marked.push(cm.markText(cursor.from(), cursor.to(), className));
35 }
36 }
37 });
38 }
39 }
40
41 CodeMirror.defineExtension("matchHighlight", function(className, minChars) {
42 markDocument(this, className, minChars);
43 });
44 })();
@@ -0,0 +1,81
1 CodeMirror.multiplexingMode = function(outer /*, others */) {
2 // Others should be {open, close, mode [, delimStyle]} objects
3 var others = Array.prototype.slice.call(arguments, 1);
4 var n_others = others.length;
5
6 function indexOf(string, pattern, from) {
7 if (typeof pattern == "string") return string.indexOf(pattern, from);
8 var m = pattern.exec(from ? string.slice(from) : string);
9 return m ? m.index + from : -1;
10 }
11
12 return {
13 startState: function() {
14 return {
15 outer: CodeMirror.startState(outer),
16 innerActive: null,
17 inner: null
18 };
19 },
20
21 copyState: function(state) {
22 return {
23 outer: CodeMirror.copyState(outer, state.outer),
24 innerActive: state.innerActive,
25 inner: state.innerActive && CodeMirror.copyState(state.innerActive.mode, state.inner)
26 };
27 },
28
29 token: function(stream, state) {
30 if (!state.innerActive) {
31 var cutOff = Infinity, oldContent = stream.string;
32 for (var i = 0; i < n_others; ++i) {
33 var other = others[i];
34 var found = indexOf(oldContent, other.open, stream.pos);
35 if (found == stream.pos) {
36 stream.match(other.open);
37 state.innerActive = other;
38 state.inner = CodeMirror.startState(other.mode, outer.indent(state.outer, ""));
39 return other.delimStyle;
40 } else if (found != -1 && found < cutOff) {
41 cutOff = found;
42 }
43 }
44 if (cutOff != Infinity) stream.string = oldContent.slice(0, cutOff);
45 var outerToken = outer.token(stream, state.outer);
46 if (cutOff != Infinity) stream.string = oldContent;
47 return outerToken;
48 } else {
49 var curInner = state.innerActive, oldContent = stream.string;
50 var found = indexOf(oldContent, curInner.close, stream.pos);
51 if (found == stream.pos) {
52 stream.match(curInner.close);
53 state.innerActive = state.inner = null;
54 return curInner.delimStyle;
55 }
56 if (found > -1) stream.string = oldContent.slice(0, found);
57 var innerToken = curInner.mode.token(stream, state.inner);
58 if (found > -1) stream.string = oldContent;
59 var cur = stream.current(), found = cur.indexOf(curInner.close);
60 if (found > -1) stream.backUp(cur.length - found);
61 return innerToken;
62 }
63 },
64
65 indent: function(state, textAfter) {
66 var mode = state.innerActive ? state.innerActive.mode : outer;
67 if (!mode.indent) return CodeMirror.Pass;
68 return mode.indent(state.innerActive ? state.inner : state.outer, textAfter);
69 },
70
71 compareStates: function(a, b) {
72 if (a.innerActive != b.innerActive) return false;
73 var mode = a.innerActive || outer;
74 if (!mode.compareStates) return CodeMirror.Pass;
75 return mode.compareStates(a.innerActive ? a.inner : a.outer,
76 b.innerActive ? b.inner : b.outer);
77 },
78
79 electricChars: outer.electricChars
80 };
81 };
@@ -0,0 +1,123
1 (function () {
2 function forEach(arr, f) {
3 for (var i = 0, e = arr.length; i < e; ++i) f(arr[i]);
4 }
5
6 function arrayContains(arr, item) {
7 if (!Array.prototype.indexOf) {
8 var i = arr.length;
9 while (i--) {
10 if (arr[i] === item) {
11 return true;
12 }
13 }
14 return false;
15 }
16 return arr.indexOf(item) != -1;
17 }
18
19 function scriptHint(editor, keywords, getToken) {
20 // Find the token at the cursor
21 var cur = editor.getCursor(), token = getToken(editor, cur), tprop = token;
22 // If it's not a 'word-style' token, ignore the token.
23
24 if (!/^[\w$_]*$/.test(token.string)) {
25 token = tprop = {start: cur.ch, end: cur.ch, string: "", state: token.state,
26 className: token.string == ":" ? "pig-type" : null};
27 }
28
29 if (!context) var context = [];
30 context.push(tprop);
31
32 var completionList = getCompletions(token, context);
33 completionList = completionList.sort();
34 //prevent autocomplete for last word, instead show dropdown with one word
35 if(completionList.length == 1) {
36 completionList.push(" ");
37 }
38
39 return {list: completionList,
40 from: {line: cur.line, ch: token.start},
41 to: {line: cur.line, ch: token.end}};
42 }
43
44 CodeMirror.pigHint = function(editor) {
45 return scriptHint(editor, pigKeywordsU, function (e, cur) {return e.getTokenAt(cur);});
46 }
47
48 function toTitleCase(str) {
49 return str.replace(/(?:^|\s)\w/g, function(match) {
50 return match.toUpperCase();
51 });
52 }
53
54 var pigKeywords = "VOID IMPORT RETURNS DEFINE LOAD FILTER FOREACH ORDER CUBE DISTINCT COGROUP "
55 + "JOIN CROSS UNION SPLIT INTO IF OTHERWISE ALL AS BY USING INNER OUTER ONSCHEMA PARALLEL "
56 + "PARTITION GROUP AND OR NOT GENERATE FLATTEN ASC DESC IS STREAM THROUGH STORE MAPREDUCE "
57 + "SHIP CACHE INPUT OUTPUT STDERROR STDIN STDOUT LIMIT SAMPLE LEFT RIGHT FULL EQ GT LT GTE LTE "
58 + "NEQ MATCHES TRUE FALSE";
59 var pigKeywordsU = pigKeywords.split(" ");
60 var pigKeywordsL = pigKeywords.toLowerCase().split(" ");
61
62 var pigTypes = "BOOLEAN INT LONG FLOAT DOUBLE CHARARRAY BYTEARRAY BAG TUPLE MAP";
63 var pigTypesU = pigTypes.split(" ");
64 var pigTypesL = pigTypes.toLowerCase().split(" ");
65
66 var pigBuiltins = "ABS ACOS ARITY ASIN ATAN AVG BAGSIZE BINSTORAGE BLOOM BUILDBLOOM CBRT CEIL "
67 + "CONCAT COR COS COSH COUNT COUNT_STAR COV CONSTANTSIZE CUBEDIMENSIONS DIFF DISTINCT DOUBLEABS "
68 + "DOUBLEAVG DOUBLEBASE DOUBLEMAX DOUBLEMIN DOUBLEROUND DOUBLESUM EXP FLOOR FLOATABS FLOATAVG "
69 + "FLOATMAX FLOATMIN FLOATROUND FLOATSUM GENERICINVOKER INDEXOF INTABS INTAVG INTMAX INTMIN "
70 + "INTSUM INVOKEFORDOUBLE INVOKEFORFLOAT INVOKEFORINT INVOKEFORLONG INVOKEFORSTRING INVOKER "
71 + "ISEMPTY JSONLOADER JSONMETADATA JSONSTORAGE LAST_INDEX_OF LCFIRST LOG LOG10 LOWER LONGABS "
72 + "LONGAVG LONGMAX LONGMIN LONGSUM MAX MIN MAPSIZE MONITOREDUDF NONDETERMINISTIC OUTPUTSCHEMA "
73 + "PIGSTORAGE PIGSTREAMING RANDOM REGEX_EXTRACT REGEX_EXTRACT_ALL REPLACE ROUND SIN SINH SIZE "
74 + "SQRT STRSPLIT SUBSTRING SUM STRINGCONCAT STRINGMAX STRINGMIN STRINGSIZE TAN TANH TOBAG "
75 + "TOKENIZE TOMAP TOP TOTUPLE TRIM TEXTLOADER TUPLESIZE UCFIRST UPPER UTF8STORAGECONVERTER";
76 var pigBuiltinsU = pigBuiltins.split(" ").join("() ").split(" ");
77 var pigBuiltinsL = pigBuiltins.toLowerCase().split(" ").join("() ").split(" ");
78 var pigBuiltinsC = ("BagSize BinStorage Bloom BuildBloom ConstantSize CubeDimensions DoubleAbs "
79 + "DoubleAvg DoubleBase DoubleMax DoubleMin DoubleRound DoubleSum FloatAbs FloatAvg FloatMax "
80 + "FloatMin FloatRound FloatSum GenericInvoker IntAbs IntAvg IntMax IntMin IntSum "
81 + "InvokeForDouble InvokeForFloat InvokeForInt InvokeForLong InvokeForString Invoker "
82 + "IsEmpty JsonLoader JsonMetadata JsonStorage LongAbs LongAvg LongMax LongMin LongSum MapSize "
83 + "MonitoredUDF Nondeterministic OutputSchema PigStorage PigStreaming StringConcat StringMax "
84 + "StringMin StringSize TextLoader TupleSize Utf8StorageConverter").split(" ").join("() ").split(" ");
85
86 function getCompletions(token, context) {
87 var found = [], start = token.string;
88 function maybeAdd(str) {
89 if (str.indexOf(start) == 0 && !arrayContains(found, str)) found.push(str);
90 }
91
92 function gatherCompletions(obj) {
93 if(obj == ":") {
94 forEach(pigTypesL, maybeAdd);
95 }
96 else {
97 forEach(pigBuiltinsU, maybeAdd);
98 forEach(pigBuiltinsL, maybeAdd);
99 forEach(pigBuiltinsC, maybeAdd);
100 forEach(pigTypesU, maybeAdd);
101 forEach(pigTypesL, maybeAdd);
102 forEach(pigKeywordsU, maybeAdd);
103 forEach(pigKeywordsL, maybeAdd);
104 }
105 }
106
107 if (context) {
108 // If this is a property, see if it belongs to some object we can
109 // find in the current environment.
110 var obj = context.pop(), base;
111
112 if (obj.className == "pig-word")
113 base = obj.string;
114 else if(obj.className == "pig-type")
115 base = ":" + obj.string;
116
117 while (base != null && context.length)
118 base = base[context.pop().string];
119 if (base != null) gatherCompletions(base);
120 }
121 return found;
122 }
123 })();
@@ -0,0 +1,137
1
2 (function() {
3
4 CodeMirror.xmlHints = [];
5
6 CodeMirror.xmlHint = function(cm, simbol) {
7
8 if(simbol.length > 0) {
9 var cursor = cm.getCursor();
10 cm.replaceSelection(simbol);
11 cursor = {line: cursor.line, ch: cursor.ch + 1};
12 cm.setCursor(cursor);
13 }
14
15 // dirty hack for simple-hint to receive getHint event on space
16 var getTokenAt = editor.getTokenAt;
17
18 editor.getTokenAt = function() { return 'disabled'; }
19 CodeMirror.simpleHint(cm, getHint);
20
21 editor.getTokenAt = getTokenAt;
22 };
23
24 var getHint = function(cm) {
25
26 var cursor = cm.getCursor();
27
28 if (cursor.ch > 0) {
29
30 var text = cm.getRange({line: 0, ch: 0}, cursor);
31 var typed = '';
32 var simbol = '';
33 for(var i = text.length - 1; i >= 0; i--) {
34 if(text[i] == ' ' || text[i] == '<') {
35 simbol = text[i];
36 break;
37 }
38 else {
39 typed = text[i] + typed;
40 }
41 }
42
43 text = text.substr(0, text.length - typed.length);
44
45 var path = getActiveElement(cm, text) + simbol;
46 var hints = CodeMirror.xmlHints[path];
47
48 if(typeof hints === 'undefined')
49 hints = [''];
50 else {
51 hints = hints.slice(0);
52 for (var i = hints.length - 1; i >= 0; i--) {
53 if(hints[i].indexOf(typed) != 0)
54 hints.splice(i, 1);
55 }
56 }
57
58 return {
59 list: hints,
60 from: { line: cursor.line, ch: cursor.ch - typed.length },
61 to: cursor,
62 };
63 };
64 }
65
66 var getActiveElement = function(codeMirror, text) {
67
68 var element = '';
69
70 if(text.length >= 0) {
71
72 var regex = new RegExp('<([^!?][^\\s/>]*).*?>', 'g');
73
74 var matches = [];
75 var match;
76 while ((match = regex.exec(text)) != null) {
77 matches.push({
78 tag: match[1],
79 selfclose: (match[0].substr(-1) === '/>')
80 });
81 }
82
83 for (var i = matches.length - 1, skip = 0; i >= 0; i--) {
84
85 var item = matches[i];
86
87 if (item.tag[0] == '/')
88 {
89 skip++;
90 }
91 else if (item.selfclose == false)
92 {
93 if (skip > 0)
94 {
95 skip--;
96 }
97 else
98 {
99 element = '<' + item.tag + '>' + element;
100 }
101 }
102 }
103
104 element += getOpenTag(text);
105 }
106
107 return element;
108 };
109
110 var getOpenTag = function(text) {
111
112 var open = text.lastIndexOf('<');
113 var close = text.lastIndexOf('>');
114
115 if (close < open)
116 {
117 text = text.substr(open);
118
119 if(text != '<') {
120
121 var space = text.indexOf(' ');
122 if(space < 0)
123 space = text.indexOf('\t');
124 if(space < 0)
125 space = text.indexOf('\n');
126
127 if (space < 0)
128 space = text.length;
129
130 return text.substr(0, space);
131 }
132 }
133
134 return '';
135 };
136
137 })();
@@ -0,0 +1,280
1 CodeMirror.defineMode("clike", function(config, parserConfig) {
2 var indentUnit = config.indentUnit,
3 keywords = parserConfig.keywords || {},
4 builtin = parserConfig.builtin || {},
5 blockKeywords = parserConfig.blockKeywords || {},
6 atoms = parserConfig.atoms || {},
7 hooks = parserConfig.hooks || {},
8 multiLineStrings = parserConfig.multiLineStrings;
9 var isOperatorChar = /[+\-*&%=<>!?|\/]/;
10
11 var curPunc;
12
13 function tokenBase(stream, state) {
14 var ch = stream.next();
15 if (hooks[ch]) {
16 var result = hooks[ch](stream, state);
17 if (result !== false) return result;
18 }
19 if (ch == '"' || ch == "'") {
20 state.tokenize = tokenString(ch);
21 return state.tokenize(stream, state);
22 }
23 if (/[\[\]{}\(\),;\:\.]/.test(ch)) {
24 curPunc = ch;
25 return null;
26 }
27 if (/\d/.test(ch)) {
28 stream.eatWhile(/[\w\.]/);
29 return "number";
30 }
31 if (ch == "/") {
32 if (stream.eat("*")) {
33 state.tokenize = tokenComment;
34 return tokenComment(stream, state);
35 }
36 if (stream.eat("/")) {
37 stream.skipToEnd();
38 return "comment";
39 }
40 }
41 if (isOperatorChar.test(ch)) {
42 stream.eatWhile(isOperatorChar);
43 return "operator";
44 }
45 stream.eatWhile(/[\w\$_]/);
46 var cur = stream.current();
47 if (keywords.propertyIsEnumerable(cur)) {
48 if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement";
49 return "keyword";
50 }
51 if (builtin.propertyIsEnumerable(cur)) {
52 if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement";
53 return "builtin";
54 }
55 if (atoms.propertyIsEnumerable(cur)) return "atom";
56 return "variable";
57 }
58
59 function tokenString(quote) {
60 return function(stream, state) {
61 var escaped = false, next, end = false;
62 while ((next = stream.next()) != null) {
63 if (next == quote && !escaped) {end = true; break;}
64 escaped = !escaped && next == "\\";
65 }
66 if (end || !(escaped || multiLineStrings))
67 state.tokenize = null;
68 return "string";
69 };
70 }
71
72 function tokenComment(stream, state) {
73 var maybeEnd = false, ch;
74 while (ch = stream.next()) {
75 if (ch == "/" && maybeEnd) {
76 state.tokenize = null;
77 break;
78 }
79 maybeEnd = (ch == "*");
80 }
81 return "comment";
82 }
83
84 function Context(indented, column, type, align, prev) {
85 this.indented = indented;
86 this.column = column;
87 this.type = type;
88 this.align = align;
89 this.prev = prev;
90 }
91 function pushContext(state, col, type) {
92 return state.context = new Context(state.indented, col, type, null, state.context);
93 }
94 function popContext(state) {
95 var t = state.context.type;
96 if (t == ")" || t == "]" || t == "}")
97 state.indented = state.context.indented;
98 return state.context = state.context.prev;
99 }
100
101 // Interface
102
103 return {
104 startState: function(basecolumn) {
105 return {
106 tokenize: null,
107 context: new Context((basecolumn || 0) - indentUnit, 0, "top", false),
108 indented: 0,
109 startOfLine: true
110 };
111 },
112
113 token: function(stream, state) {
114 var ctx = state.context;
115 if (stream.sol()) {
116 if (ctx.align == null) ctx.align = false;
117 state.indented = stream.indentation();
118 state.startOfLine = true;
119 }
120 if (stream.eatSpace()) return null;
121 curPunc = null;
122 var style = (state.tokenize || tokenBase)(stream, state);
123 if (style == "comment" || style == "meta") return style;
124 if (ctx.align == null) ctx.align = true;
125
126 if ((curPunc == ";" || curPunc == ":") && ctx.type == "statement") popContext(state);
127 else if (curPunc == "{") pushContext(state, stream.column(), "}");
128 else if (curPunc == "[") pushContext(state, stream.column(), "]");
129 else if (curPunc == "(") pushContext(state, stream.column(), ")");
130 else if (curPunc == "}") {
131 while (ctx.type == "statement") ctx = popContext(state);
132 if (ctx.type == "}") ctx = popContext(state);
133 while (ctx.type == "statement") ctx = popContext(state);
134 }
135 else if (curPunc == ctx.type) popContext(state);
136 else if (ctx.type == "}" || ctx.type == "top" || (ctx.type == "statement" && curPunc == "newstatement"))
137 pushContext(state, stream.column(), "statement");
138 state.startOfLine = false;
139 return style;
140 },
141
142 indent: function(state, textAfter) {
143 if (state.tokenize != tokenBase && state.tokenize != null) return 0;
144 var ctx = state.context, firstChar = textAfter && textAfter.charAt(0);
145 if (ctx.type == "statement" && firstChar == "}") ctx = ctx.prev;
146 var closing = firstChar == ctx.type;
147 if (ctx.type == "statement") return ctx.indented + (firstChar == "{" ? 0 : indentUnit);
148 else if (ctx.align) return ctx.column + (closing ? 0 : 1);
149 else return ctx.indented + (closing ? 0 : indentUnit);
150 },
151
152 electricChars: "{}"
153 };
154 });
155
156 (function() {
157 function words(str) {
158 var obj = {}, words = str.split(" ");
159 for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
160 return obj;
161 }
162 var cKeywords = "auto if break int case long char register continue return default short do sizeof " +
163 "double static else struct entry switch extern typedef float union for unsigned " +
164 "goto while enum void const signed volatile";
165
166 function cppHook(stream, state) {
167 if (!state.startOfLine) return false;
168 stream.skipToEnd();
169 return "meta";
170 }
171
172 // C#-style strings where "" escapes a quote.
173 function tokenAtString(stream, state) {
174 var next;
175 while ((next = stream.next()) != null) {
176 if (next == '"' && !stream.eat('"')) {
177 state.tokenize = null;
178 break;
179 }
180 }
181 return "string";
182 }
183
184 CodeMirror.defineMIME("text/x-csrc", {
185 name: "clike",
186 keywords: words(cKeywords),
187 blockKeywords: words("case do else for if switch while struct"),
188 atoms: words("null"),
189 hooks: {"#": cppHook}
190 });
191 CodeMirror.defineMIME("text/x-c++src", {
192 name: "clike",
193 keywords: words(cKeywords + " asm dynamic_cast namespace reinterpret_cast try bool explicit new " +
194 "static_cast typeid catch operator template typename class friend private " +
195 "this using const_cast inline public throw virtual delete mutable protected " +
196 "wchar_t"),
197 blockKeywords: words("catch class do else finally for if struct switch try while"),
198 atoms: words("true false null"),
199 hooks: {"#": cppHook}
200 });
201 CodeMirror.defineMIME("text/x-java", {
202 name: "clike",
203 keywords: words("abstract assert boolean break byte case catch char class const continue default " +
204 "do double else enum extends final finally float for goto if implements import " +
205 "instanceof int interface long native new package private protected public " +
206 "return short static strictfp super switch synchronized this throw throws transient " +
207 "try void volatile while"),
208 blockKeywords: words("catch class do else finally for if switch try while"),
209 atoms: words("true false null"),
210 hooks: {
211 "@": function(stream, state) {
212 stream.eatWhile(/[\w\$_]/);
213 return "meta";
214 }
215 }
216 });
217 CodeMirror.defineMIME("text/x-csharp", {
218 name: "clike",
219 keywords: words("abstract as base break case catch checked class const continue" +
220 " default delegate do else enum event explicit extern finally fixed for" +
221 " foreach goto if implicit in interface internal is lock namespace new" +
222 " operator out override params private protected public readonly ref return sealed" +
223 " sizeof stackalloc static struct switch this throw try typeof unchecked" +
224 " unsafe using virtual void volatile while add alias ascending descending dynamic from get" +
225 " global group into join let orderby partial remove select set value var yield"),
226 blockKeywords: words("catch class do else finally for foreach if struct switch try while"),
227 builtin: words("Boolean Byte Char DateTime DateTimeOffset Decimal Double" +
228 " Guid Int16 Int32 Int64 Object SByte Single String TimeSpan UInt16 UInt32" +
229 " UInt64 bool byte char decimal double short int long object" +
230 " sbyte float string ushort uint ulong"),
231 atoms: words("true false null"),
232 hooks: {
233 "@": function(stream, state) {
234 if (stream.eat('"')) {
235 state.tokenize = tokenAtString;
236 return tokenAtString(stream, state);
237 }
238 stream.eatWhile(/[\w\$_]/);
239 return "meta";
240 }
241 }
242 });
243 CodeMirror.defineMIME("text/x-scala", {
244 name: "clike",
245 keywords: words(
246
247 /* scala */
248 "abstract case catch class def do else extends false final finally for forSome if " +
249 "implicit import lazy match new null object override package private protected return " +
250 "sealed super this throw trait try trye type val var while with yield _ : = => <- <: " +
251 "<% >: # @ " +
252
253 /* package scala */
254 "assert assume require print println printf readLine readBoolean readByte readShort " +
255 "readChar readInt readLong readFloat readDouble " +
256
257 "AnyVal App Application Array BufferedIterator BigDecimal BigInt Char Console Either " +
258 "Enumeration Equiv Error Exception Fractional Function IndexedSeq Integral Iterable " +
259 "Iterator List Map Numeric Nil NotNull Option Ordered Ordering PartialFunction PartialOrdering " +
260 "Product Proxy Range Responder Seq Serializable Set Specializable Stream StringBuilder " +
261 "StringContext Symbol Throwable Traversable TraversableOnce Tuple Unit Vector :: #:: " +
262
263 /* package java.lang */
264 "Boolean Byte Character CharSequence Class ClassLoader Cloneable Comparable " +
265 "Compiler Double Exception Float Integer Long Math Number Object Package Pair Process " +
266 "Runtime Runnable SecurityManager Short StackTraceElement StrictMath String " +
267 "StringBuffer System Thread ThreadGroup ThreadLocal Throwable Triple Void"
268
269
270 ),
271 blockKeywords: words("catch class do else finally for forSome if match switch try while"),
272 atoms: words("true false null"),
273 hooks: {
274 "@": function(stream, state) {
275 stream.eatWhile(/[\w\$_]/);
276 return "meta";
277 }
278 }
279 });
280 }());
@@ -0,0 +1,101
1 <!doctype html>
2 <html>
3 <head>
4 <title>CodeMirror: C-like mode</title>
5 <link rel="stylesheet" href="../../lib/codemirror.css">
6 <script src="../../lib/codemirror.js"></script>
7 <script src="clike.js"></script>
8 <link rel="stylesheet" href="../../doc/docs.css">
9 <style>.CodeMirror {border: 2px inset #dee;}</style>
10 </head>
11 <body>
12 <h1>CodeMirror: C-like mode</h1>
13
14 <form><textarea id="code" name="code">
15 /* C demo code */
16
17 #include <zmq.h>
18 #include <pthread.h>
19 #include <semaphore.h>
20 #include <time.h>
21 #include <stdio.h>
22 #include <fcntl.h>
23 #include <malloc.h>
24
25 typedef struct {
26 void* arg_socket;
27 zmq_msg_t* arg_msg;
28 char* arg_string;
29 unsigned long arg_len;
30 int arg_int, arg_command;
31
32 int signal_fd;
33 int pad;
34 void* context;
35 sem_t sem;
36 } acl_zmq_context;
37
38 #define p(X) (context->arg_##X)
39
40 void* zmq_thread(void* context_pointer) {
41 acl_zmq_context* context = (acl_zmq_context*)context_pointer;
42 char ok = 'K', err = 'X';
43 int res;
44
45 while (1) {
46 while ((res = sem_wait(&amp;context->sem)) == EINTR);
47 if (res) {write(context->signal_fd, &amp;err, 1); goto cleanup;}
48 switch(p(command)) {
49 case 0: goto cleanup;
50 case 1: p(socket) = zmq_socket(context->context, p(int)); break;
51 case 2: p(int) = zmq_close(p(socket)); break;
52 case 3: p(int) = zmq_bind(p(socket), p(string)); break;
53 case 4: p(int) = zmq_connect(p(socket), p(string)); break;
54 case 5: p(int) = zmq_getsockopt(p(socket), p(int), (void*)p(string), &amp;p(len)); break;
55 case 6: p(int) = zmq_setsockopt(p(socket), p(int), (void*)p(string), p(len)); break;
56 case 7: p(int) = zmq_send(p(socket), p(msg), p(int)); break;
57 case 8: p(int) = zmq_recv(p(socket), p(msg), p(int)); break;
58 case 9: p(int) = zmq_poll(p(socket), p(int), p(len)); break;
59 }
60 p(command) = errno;
61 write(context->signal_fd, &amp;ok, 1);
62 }
63 cleanup:
64 close(context->signal_fd);
65 free(context_pointer);
66 return 0;
67 }
68
69 void* zmq_thread_init(void* zmq_context, int signal_fd) {
70 acl_zmq_context* context = malloc(sizeof(acl_zmq_context));
71 pthread_t thread;
72
73 context->context = zmq_context;
74 context->signal_fd = signal_fd;
75 sem_init(&amp;context->sem, 1, 0);
76 pthread_create(&amp;thread, 0, &amp;zmq_thread, context);
77 pthread_detach(thread);
78 return context;
79 }
80 </textarea></form>
81
82 <script>
83 var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
84 lineNumbers: true,
85 matchBrackets: true,
86 mode: "text/x-csrc"
87 });
88 </script>
89
90 <p>Simple mode that tries to handle C-like languages as well as it
91 can. Takes two configuration parameters: <code>keywords</code>, an
92 object whose property names are the keywords in the language,
93 and <code>useCPP</code>, which determines whether C preprocessor
94 directives are recognized.</p>
95
96 <p><strong>MIME types defined:</strong> <code>text/x-csrc</code>
97 (C code), <code>text/x-c++src</code> (C++
98 code), <code>text/x-java</code> (Java
99 code), <code>text/x-csharp</code> (C#).</p>
100 </body>
101 </html>
This diff has been collapsed as it changes many lines, (765 lines changed) Show them Hide them
@@ -0,0 +1,765
1 <!doctype html>
2 <html>
3 <head>
4 <title>CodeMirror: C-like mode</title>
5 <link rel="stylesheet" href="../../lib/codemirror.css">
6 <link rel="stylesheet" href="../../theme/ambiance.css">
7 <script src="../../lib/codemirror.js"></script>
8 <script src="clike.js"></script>
9 <link rel="stylesheet" href="../../doc/docs.css">
10 <style>
11 body
12 {
13 margin: 0;
14 padding: 0;
15 max-width:inherit;
16 height: 100%;
17 }
18 html, form, .CodeMirror, .CodeMirror-scroll
19 {
20 height: 100%;
21 }
22 </style>
23 </head>
24 <body>
25 <form>
26 <textarea id="code" name="code">
27
28 /* __ *\
29 ** ________ ___ / / ___ Scala API **
30 ** / __/ __// _ | / / / _ | (c) 2003-2011, LAMP/EPFL **
31 ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
32 ** /____/\___/_/ |_/____/_/ | | **
33 ** |/ **
34 \* */
35
36 package scala.collection
37
38 import generic._
39 import mutable.{ Builder, ListBuffer }
40 import annotation.{tailrec, migration, bridge}
41 import annotation.unchecked.{ uncheckedVariance => uV }
42 import parallel.ParIterable
43
44 /** A template trait for traversable collections of type `Traversable[A]`.
45 *
46 * $traversableInfo
47 * @define mutability
48 * @define traversableInfo
49 * This is a base trait of all kinds of $mutability Scala collections. It
50 * implements the behavior common to all collections, in terms of a method
51 * `foreach` with signature:
52 * {{{
53 * def foreach[U](f: Elem => U): Unit
54 * }}}
55 * Collection classes mixing in this trait provide a concrete
56 * `foreach` method which traverses all the
57 * elements contained in the collection, applying a given function to each.
58 * They also need to provide a method `newBuilder`
59 * which creates a builder for collections of the same kind.
60 *
61 * A traversable class might or might not have two properties: strictness
62 * and orderedness. Neither is represented as a type.
63 *
64 * The instances of a strict collection class have all their elements
65 * computed before they can be used as values. By contrast, instances of
66 * a non-strict collection class may defer computation of some of their
67 * elements until after the instance is available as a value.
68 * A typical example of a non-strict collection class is a
69 * <a href="../immutable/Stream.html" target="ContentFrame">
70 * `scala.collection.immutable.Stream`</a>.
71 * A more general class of examples are `TraversableViews`.
72 *
73 * If a collection is an instance of an ordered collection class, traversing
74 * its elements with `foreach` will always visit elements in the
75 * same order, even for different runs of the program. If the class is not
76 * ordered, `foreach` can visit elements in different orders for
77 * different runs (but it will keep the same order in the same run).'
78 *
79 * A typical example of a collection class which is not ordered is a
80 * `HashMap` of objects. The traversal order for hash maps will
81 * depend on the hash codes of its elements, and these hash codes might
82 * differ from one run to the next. By contrast, a `LinkedHashMap`
83 * is ordered because it's `foreach` method visits elements in the
84 * order they were inserted into the `HashMap`.
85 *
86 * @author Martin Odersky
87 * @version 2.8
88 * @since 2.8
89 * @tparam A the element type of the collection
90 * @tparam Repr the type of the actual collection containing the elements.
91 *
92 * @define Coll Traversable
93 * @define coll traversable collection
94 */
95 trait TraversableLike[+A, +Repr] extends HasNewBuilder[A, Repr]
96 with FilterMonadic[A, Repr]
97 with TraversableOnce[A]
98 with GenTraversableLike[A, Repr]
99 with Parallelizable[A, ParIterable[A]]
100 {
101 self =>
102
103 import Traversable.breaks._
104
105 /** The type implementing this traversable */
106 protected type Self = Repr
107
108 /** The collection of type $coll underlying this `TraversableLike` object.
109 * By default this is implemented as the `TraversableLike` object itself,
110 * but this can be overridden.
111 */
112 def repr: Repr = this.asInstanceOf[Repr]
113
114 /** The underlying collection seen as an instance of `$Coll`.
115 * By default this is implemented as the current collection object itself,
116 * but this can be overridden.
117 */
118 protected[this] def thisCollection: Traversable[A] = this.asInstanceOf[Traversable[A]]
119
120 /** A conversion from collections of type `Repr` to `$Coll` objects.
121 * By default this is implemented as just a cast, but this can be overridden.
122 */
123 protected[this] def toCollection(repr: Repr): Traversable[A] = repr.asInstanceOf[Traversable[A]]
124
125 /** Creates a new builder for this collection type.
126 */
127 protected[this] def newBuilder: Builder[A, Repr]
128
129 protected[this] def parCombiner = ParIterable.newCombiner[A]
130
131 /** Applies a function `f` to all elements of this $coll.
132 *
133 * Note: this method underlies the implementation of most other bulk operations.
134 * It's important to implement this method in an efficient way.
135 *
136 *
137 * @param f the function that is applied for its side-effect to every element.
138 * The result of function `f` is discarded.
139 *
140 * @tparam U the type parameter describing the result of function `f`.
141 * This result will always be ignored. Typically `U` is `Unit`,
142 * but this is not necessary.
143 *
144 * @usecase def foreach(f: A => Unit): Unit
145 */
146 def foreach[U](f: A => U): Unit
147
148 /** Tests whether this $coll is empty.
149 *
150 * @return `true` if the $coll contain no elements, `false` otherwise.
151 */
152 def isEmpty: Boolean = {
153 var result = true
154 breakable {
155 for (x <- this) {
156 result = false
157 break
158 }
159 }
160 result
161 }
162
163 /** Tests whether this $coll is known to have a finite size.
164 * All strict collections are known to have finite size. For a non-strict collection
165 * such as `Stream`, the predicate returns `true` if all elements have been computed.
166 * It returns `false` if the stream is not yet evaluated to the end.
167 *
168 * Note: many collection methods will not work on collections of infinite sizes.
169 *
170 * @return `true` if this collection is known to have finite size, `false` otherwise.
171 */
172 def hasDefiniteSize = true
173
174 def ++[B >: A, That](that: GenTraversableOnce[B])(implicit bf: CanBuildFrom[Repr, B, That]): That = {
175 val b = bf(repr)
176 if (that.isInstanceOf[IndexedSeqLike[_, _]]) b.sizeHint(this, that.seq.size)
177 b ++= thisCollection
178 b ++= that.seq
179 b.result
180 }
181
182 @bridge
183 def ++[B >: A, That](that: TraversableOnce[B])(implicit bf: CanBuildFrom[Repr, B, That]): That =
184 ++(that: GenTraversableOnce[B])(bf)
185
186 /** Concatenates this $coll with the elements of a traversable collection.
187 * It differs from ++ in that the right operand determines the type of the
188 * resulting collection rather than the left one.
189 *
190 * @param that the traversable to append.
191 * @tparam B the element type of the returned collection.
192 * @tparam That $thatinfo
193 * @param bf $bfinfo
194 * @return a new collection of type `That` which contains all elements
195 * of this $coll followed by all elements of `that`.
196 *
197 * @usecase def ++:[B](that: TraversableOnce[B]): $Coll[B]
198 *
199 * @return a new $coll which contains all elements of this $coll
200 * followed by all elements of `that`.
201 */
202 def ++:[B >: A, That](that: TraversableOnce[B])(implicit bf: CanBuildFrom[Repr, B, That]): That = {
203 val b = bf(repr)
204 if (that.isInstanceOf[IndexedSeqLike[_, _]]) b.sizeHint(this, that.size)
205 b ++= that
206 b ++= thisCollection
207 b.result
208 }
209
210 /** This overload exists because: for the implementation of ++: we should reuse
211 * that of ++ because many collections override it with more efficient versions.
212 * Since TraversableOnce has no '++' method, we have to implement that directly,
213 * but Traversable and down can use the overload.
214 */
215 def ++:[B >: A, That](that: Traversable[B])(implicit bf: CanBuildFrom[Repr, B, That]): That =
216 (that ++ seq)(breakOut)
217
218 def map[B, That](f: A => B)(implicit bf: CanBuildFrom[Repr, B, That]): That = {
219 val b = bf(repr)
220 b.sizeHint(this)
221 for (x <- this) b += f(x)
222 b.result
223 }
224
225 def flatMap[B, That](f: A => GenTraversableOnce[B])(implicit bf: CanBuildFrom[Repr, B, That]): That = {
226 val b = bf(repr)
227 for (x <- this) b ++= f(x).seq
228 b.result
229 }
230
231 /** Selects all elements of this $coll which satisfy a predicate.
232 *
233 * @param p the predicate used to test elements.
234 * @return a new $coll consisting of all elements of this $coll that satisfy the given
235 * predicate `p`. The order of the elements is preserved.
236 */
237 def filter(p: A => Boolean): Repr = {
238 val b = newBuilder
239 for (x <- this)
240 if (p(x)) b += x
241 b.result
242 }
243
244 /** Selects all elements of this $coll which do not satisfy a predicate.
245 *
246 * @param p the predicate used to test elements.
247 * @return a new $coll consisting of all elements of this $coll that do not satisfy the given
248 * predicate `p`. The order of the elements is preserved.
249 */
250 def filterNot(p: A => Boolean): Repr = filter(!p(_))
251
252 def collect[B, That](pf: PartialFunction[A, B])(implicit bf: CanBuildFrom[Repr, B, That]): That = {
253 val b = bf(repr)
254 for (x <- this) if (pf.isDefinedAt(x)) b += pf(x)
255 b.result
256 }
257
258 /** Builds a new collection by applying an option-valued function to all
259 * elements of this $coll on which the function is defined.
260 *
261 * @param f the option-valued function which filters and maps the $coll.
262 * @tparam B the element type of the returned collection.
263 * @tparam That $thatinfo
264 * @param bf $bfinfo
265 * @return a new collection of type `That` resulting from applying the option-valued function
266 * `f` to each element and collecting all defined results.
267 * The order of the elements is preserved.
268 *
269 * @usecase def filterMap[B](f: A => Option[B]): $Coll[B]
270 *
271 * @param pf the partial function which filters and maps the $coll.
272 * @return a new $coll resulting from applying the given option-valued function
273 * `f` to each element and collecting all defined results.
274 * The order of the elements is preserved.
275 def filterMap[B, That](f: A => Option[B])(implicit bf: CanBuildFrom[Repr, B, That]): That = {
276 val b = bf(repr)
277 for (x <- this)
278 f(x) match {
279 case Some(y) => b += y
280 case _ =>
281 }
282 b.result
283 }
284 */
285
286 /** Partitions this $coll in two ${coll}s according to a predicate.
287 *
288 * @param p the predicate on which to partition.
289 * @return a pair of ${coll}s: the first $coll consists of all elements that
290 * satisfy the predicate `p` and the second $coll consists of all elements
291 * that don't. The relative order of the elements in the resulting ${coll}s
292 * is the same as in the original $coll.
293 */
294 def partition(p: A => Boolean): (Repr, Repr) = {
295 val l, r = newBuilder
296 for (x <- this) (if (p(x)) l else r) += x
297 (l.result, r.result)
298 }
299
300 def groupBy[K](f: A => K): immutable.Map[K, Repr] = {
301 val m = mutable.Map.empty[K, Builder[A, Repr]]
302 for (elem <- this) {
303 val key = f(elem)
304 val bldr = m.getOrElseUpdate(key, newBuilder)
305 bldr += elem
306 }
307 val b = immutable.Map.newBuilder[K, Repr]
308 for ((k, v) <- m)
309 b += ((k, v.result))
310
311 b.result
312 }
313
314 /** Tests whether a predicate holds for all elements of this $coll.
315 *
316 * $mayNotTerminateInf
317 *
318 * @param p the predicate used to test elements.
319 * @return `true` if the given predicate `p` holds for all elements
320 * of this $coll, otherwise `false`.
321 */
322 def forall(p: A => Boolean): Boolean = {
323 var result = true
324 breakable {
325 for (x <- this)
326 if (!p(x)) { result = false; break }
327 }
328 result
329 }
330
331 /** Tests whether a predicate holds for some of the elements of this $coll.
332 *
333 * $mayNotTerminateInf
334 *
335 * @param p the predicate used to test elements.
336 * @return `true` if the given predicate `p` holds for some of the
337 * elements of this $coll, otherwise `false`.
338 */
339 def exists(p: A => Boolean): Boolean = {
340 var result = false
341 breakable {
342 for (x <- this)
343 if (p(x)) { result = true; break }
344 }
345 result
346 }
347
348 /** Finds the first element of the $coll satisfying a predicate, if any.
349 *
350 * $mayNotTerminateInf
351 * $orderDependent
352 *
353 * @param p the predicate used to test elements.
354 * @return an option value containing the first element in the $coll
355 * that satisfies `p`, or `None` if none exists.
356 */
357 def find(p: A => Boolean): Option[A] = {
358 var result: Option[A] = None
359 breakable {
360 for (x <- this)
361 if (p(x)) { result = Some(x); break }
362 }
363 result
364 }
365
366 def scan[B >: A, That](z: B)(op: (B, B) => B)(implicit cbf: CanBuildFrom[Repr, B, That]): That = scanLeft(z)(op)
367
368 def scanLeft[B, That](z: B)(op: (B, A) => B)(implicit bf: CanBuildFrom[Repr, B, That]): That = {
369 val b = bf(repr)
370 b.sizeHint(this, 1)
371 var acc = z
372 b += acc
373 for (x <- this) { acc = op(acc, x); b += acc }
374 b.result
375 }
376
377 @migration(2, 9,
378 "This scanRight definition has changed in 2.9.\n" +
379 "The previous behavior can be reproduced with scanRight.reverse."
380 )
381 def scanRight[B, That](z: B)(op: (A, B) => B)(implicit bf: CanBuildFrom[Repr, B, That]): That = {
382 var scanned = List(z)
383 var acc = z
384 for (x <- reversed) {
385 acc = op(x, acc)
386 scanned ::= acc
387 }
388 val b = bf(repr)
389 for (elem <- scanned) b += elem
390 b.result
391 }
392
393 /** Selects the first element of this $coll.
394 * $orderDependent
395 * @return the first element of this $coll.
396 * @throws `NoSuchElementException` if the $coll is empty.
397 */
398 def head: A = {
399 var result: () => A = () => throw new NoSuchElementException
400 breakable {
401 for (x <- this) {
402 result = () => x
403 break
404 }
405 }
406 result()
407 }
408
409 /** Optionally selects the first element.
410 * $orderDependent
411 * @return the first element of this $coll if it is nonempty, `None` if it is empty.
412 */
413 def headOption: Option[A] = if (isEmpty) None else Some(head)
414
415 /** Selects all elements except the first.
416 * $orderDependent
417 * @return a $coll consisting of all elements of this $coll
418 * except the first one.
419 * @throws `UnsupportedOperationException` if the $coll is empty.
420 */
421 override def tail: Repr = {
422 if (isEmpty) throw new UnsupportedOperationException("empty.tail")
423 drop(1)
424 }
425
426 /** Selects the last element.
427 * $orderDependent
428 * @return The last element of this $coll.
429 * @throws NoSuchElementException If the $coll is empty.
430 */
431 def last: A = {
432 var lst = head
433 for (x <- this)
434 lst = x
435 lst
436 }
437
438 /** Optionally selects the last element.
439 * $orderDependent
440 * @return the last element of this $coll$ if it is nonempty, `None` if it is empty.
441 */
442 def lastOption: Option[A] = if (isEmpty) None else Some(last)
443
444 /** Selects all elements except the last.
445 * $orderDependent
446 * @return a $coll consisting of all elements of this $coll
447 * except the last one.
448 * @throws `UnsupportedOperationException` if the $coll is empty.
449 */
450 def init: Repr = {
451 if (isEmpty) throw new UnsupportedOperationException("empty.init")
452 var lst = head
453 var follow = false
454 val b = newBuilder
455 b.sizeHint(this, -1)
456 for (x <- this.seq) {
457 if (follow) b += lst
458 else follow = true
459 lst = x
460 }
461 b.result
462 }
463
464 def take(n: Int): Repr = slice(0, n)
465
466 def drop(n: Int): Repr =
467 if (n <= 0) {
468 val b = newBuilder
469 b.sizeHint(this)
470 b ++= thisCollection result
471 }
472 else sliceWithKnownDelta(n, Int.MaxValue, -n)
473
474 def slice(from: Int, until: Int): Repr = sliceWithKnownBound(math.max(from, 0), until)
475
476 // Precondition: from >= 0, until > 0, builder already configured for building.
477 private[this] def sliceInternal(from: Int, until: Int, b: Builder[A, Repr]): Repr = {
478 var i = 0
479 breakable {
480 for (x <- this.seq) {
481 if (i >= from) b += x
482 i += 1
483 if (i >= until) break
484 }
485 }
486 b.result
487 }
488 // Precondition: from >= 0
489 private[scala] def sliceWithKnownDelta(from: Int, until: Int, delta: Int): Repr = {
490 val b = newBuilder
491 if (until <= from) b.result
492 else {
493 b.sizeHint(this, delta)
494 sliceInternal(from, until, b)
495 }
496 }
497 // Precondition: from >= 0
498 private[scala] def sliceWithKnownBound(from: Int, until: Int): Repr = {
499 val b = newBuilder
500 if (until <= from) b.result
501 else {
502 b.sizeHintBounded(until - from, this)
503 sliceInternal(from, until, b)
504 }
505 }
506
507 def takeWhile(p: A => Boolean): Repr = {
508 val b = newBuilder
509 breakable {
510 for (x <- this) {
511 if (!p(x)) break
512 b += x
513 }
514 }
515 b.result
516 }
517
518 def dropWhile(p: A => Boolean): Repr = {
519 val b = newBuilder
520 var go = false
521 for (x <- this) {
522 if (!p(x)) go = true
523 if (go) b += x
524 }
525 b.result
526 }
527
528 def span(p: A => Boolean): (Repr, Repr) = {
529 val l, r = newBuilder
530 var toLeft = true
531 for (x <- this) {
532 toLeft = toLeft && p(x)
533 (if (toLeft) l else r) += x
534 }
535 (l.result, r.result)
536 }
537
538 def splitAt(n: Int): (Repr, Repr) = {
539 val l, r = newBuilder
540 l.sizeHintBounded(n, this)
541 if (n >= 0) r.sizeHint(this, -n)
542 var i = 0
543 for (x <- this) {
544 (if (i < n) l else r) += x
545 i += 1
546 }
547 (l.result, r.result)
548 }
549
550 /** Iterates over the tails of this $coll. The first value will be this
551 * $coll and the final one will be an empty $coll, with the intervening
552 * values the results of successive applications of `tail`.
553 *
554 * @return an iterator over all the tails of this $coll
555 * @example `List(1,2,3).tails = Iterator(List(1,2,3), List(2,3), List(3), Nil)`
556 */
557 def tails: Iterator[Repr] = iterateUntilEmpty(_.tail)
558
559 /** Iterates over the inits of this $coll. The first value will be this
560 * $coll and the final one will be an empty $coll, with the intervening
561 * values the results of successive applications of `init`.
562 *
563 * @return an iterator over all the inits of this $coll
564 * @example `List(1,2,3).inits = Iterator(List(1,2,3), List(1,2), List(1), Nil)`
565 */
566 def inits: Iterator[Repr] = iterateUntilEmpty(_.init)
567
568 /** Copies elements of this $coll to an array.
569 * Fills the given array `xs` with at most `len` elements of
570 * this $coll, starting at position `start`.
571 * Copying will stop once either the end of the current $coll is reached,
572 * or the end of the array is reached, or `len` elements have been copied.
573 *
574 * $willNotTerminateInf
575 *
576 * @param xs the array to fill.
577 * @param start the starting index.
578 * @param len the maximal number of elements to copy.
579 * @tparam B the type of the elements of the array.
580 *
581 *
582 * @usecase def copyToArray(xs: Array[A], start: Int, len: Int): Unit
583 */
584 def copyToArray[B >: A](xs: Array[B], start: Int, len: Int) {
585 var i = start
586 val end = (start + len) min xs.length
587 breakable {
588 for (x <- this) {
589 if (i >= end) break
590 xs(i) = x
591 i += 1
592 }
593 }
594 }
595
596 def toTraversable: Traversable[A] = thisCollection
597 def toIterator: Iterator[A] = toStream.iterator
598 def toStream: Stream[A] = toBuffer.toStream
599
600 /** Converts this $coll to a string.
601 *
602 * @return a string representation of this collection. By default this
603 * string consists of the `stringPrefix` of this $coll,
604 * followed by all elements separated by commas and enclosed in parentheses.
605 */
606 override def toString = mkString(stringPrefix + "(", ", ", ")")
607
608 /** Defines the prefix of this object's `toString` representation.
609 *
610 * @return a string representation which starts the result of `toString`
611 * applied to this $coll. By default the string prefix is the
612 * simple name of the collection class $coll.
613 */
614 def stringPrefix : String = {
615 var string = repr.asInstanceOf[AnyRef].getClass.getName
616 val idx1 = string.lastIndexOf('.' : Int)
617 if (idx1 != -1) string = string.substring(idx1 + 1)
618 val idx2 = string.indexOf('$')
619 if (idx2 != -1) string = string.substring(0, idx2)
620 string
621 }
622
623 /** Creates a non-strict view of this $coll.
624 *
625 * @return a non-strict view of this $coll.
626 */
627 def view = new TraversableView[A, Repr] {
628 protected lazy val underlying = self.repr
629 override def foreach[U](f: A => U) = self foreach f
630 }
631
632 /** Creates a non-strict view of a slice of this $coll.
633 *
634 * Note: the difference between `view` and `slice` is that `view` produces
635 * a view of the current $coll, whereas `slice` produces a new $coll.
636 *
637 * Note: `view(from, to)` is equivalent to `view.slice(from, to)`
638 * $orderDependent
639 *
640 * @param from the index of the first element of the view
641 * @param until the index of the element following the view
642 * @return a non-strict view of a slice of this $coll, starting at index `from`
643 * and extending up to (but not including) index `until`.
644 */
645 def view(from: Int, until: Int): TraversableView[A, Repr] = view.slice(from, until)
646
647 /** Creates a non-strict filter of this $coll.
648 *
649 * Note: the difference between `c filter p` and `c withFilter p` is that
650 * the former creates a new collection, whereas the latter only
651 * restricts the domain of subsequent `map`, `flatMap`, `foreach`,
652 * and `withFilter` operations.
653 * $orderDependent
654 *
655 * @param p the predicate used to test elements.
656 * @return an object of class `WithFilter`, which supports
657 * `map`, `flatMap`, `foreach`, and `withFilter` operations.
658 * All these operations apply to those elements of this $coll which
659 * satisfy the predicate `p`.
660 */
661 def withFilter(p: A => Boolean): FilterMonadic[A, Repr] = new WithFilter(p)
662
663 /** A class supporting filtered operations. Instances of this class are
664 * returned by method `withFilter`.
665 */
666 class WithFilter(p: A => Boolean) extends FilterMonadic[A, Repr] {
667
668 /** Builds a new collection by applying a function to all elements of the
669 * outer $coll containing this `WithFilter` instance that satisfy predicate `p`.
670 *
671 * @param f the function to apply to each element.
672 * @tparam B the element type of the returned collection.
673 * @tparam That $thatinfo
674 * @param bf $bfinfo
675 * @return a new collection of type `That` resulting from applying
676 * the given function `f` to each element of the outer $coll
677 * that satisfies predicate `p` and collecting the results.
678 *
679 * @usecase def map[B](f: A => B): $Coll[B]
680 *
681 * @return a new $coll resulting from applying the given function
682 * `f` to each element of the outer $coll that satisfies
683 * predicate `p` and collecting the results.
684 */
685 def map[B, That](f: A => B)(implicit bf: CanBuildFrom[Repr, B, That]): That = {
686 val b = bf(repr)
687 for (x <- self)
688 if (p(x)) b += f(x)
689 b.result
690 }
691
692 /** Builds a new collection by applying a function to all elements of the
693 * outer $coll containing this `WithFilter` instance that satisfy
694 * predicate `p` and concatenating the results.
695 *
696 * @param f the function to apply to each element.
697 * @tparam B the element type of the returned collection.
698 * @tparam That $thatinfo
699 * @param bf $bfinfo
700 * @return a new collection of type `That` resulting from applying
701 * the given collection-valued function `f` to each element
702 * of the outer $coll that satisfies predicate `p` and
703 * concatenating the results.
704 *
705 * @usecase def flatMap[B](f: A => TraversableOnce[B]): $Coll[B]
706 *
707 * @return a new $coll resulting from applying the given collection-valued function
708 * `f` to each element of the outer $coll that satisfies predicate `p` and concatenating the results.
709 */
710 def flatMap[B, That](f: A => GenTraversableOnce[B])(implicit bf: CanBuildFrom[Repr, B, That]): That = {
711 val b = bf(repr)
712 for (x <- self)
713 if (p(x)) b ++= f(x).seq
714 b.result
715 }
716
717 /** Applies a function `f` to all elements of the outer $coll containing
718 * this `WithFilter` instance that satisfy predicate `p`.
719 *
720 * @param f the function that is applied for its side-effect to every element.
721 * The result of function `f` is discarded.
722 *
723 * @tparam U the type parameter describing the result of function `f`.
724 * This result will always be ignored. Typically `U` is `Unit`,
725 * but this is not necessary.
726 *
727 * @usecase def foreach(f: A => Unit): Unit
728 */
729 def foreach[U](f: A => U): Unit =
730 for (x <- self)
731 if (p(x)) f(x)
732
733 /** Further refines the filter for this $coll.
734 *
735 * @param q the predicate used to test elements.
736 * @return an object of class `WithFilter`, which supports
737 * `map`, `flatMap`, `foreach`, and `withFilter` operations.
738 * All these operations apply to those elements of this $coll which
739 * satisfy the predicate `q` in addition to the predicate `p`.
740 */
741 def withFilter(q: A => Boolean): WithFilter =
742 new WithFilter(x => p(x) && q(x))
743 }
744
745 // A helper for tails and inits.
746 private def iterateUntilEmpty(f: Traversable[A @uV] => Traversable[A @uV]): Iterator[Repr] = {
747 val it = Iterator.iterate(thisCollection)(f) takeWhile (x => !x.isEmpty)
748 it ++ Iterator(Nil) map (newBuilder ++= _ result)
749 }
750 }
751
752
753 </textarea>
754 </form>
755
756 <script>
757 var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
758 lineNumbers: true,
759 matchBrackets: true,
760 theme: "ambiance",
761 mode: "text/x-scala"
762 });
763 </script>
764 </body>
765 </html>
@@ -0,0 +1,207
1 /**
2 * Author: Hans Engel
3 * Branched from CodeMirror's Scheme mode (by Koh Zi Han, based on implementation by Koh Zi Chun)
4 */
5 CodeMirror.defineMode("clojure", function (config, mode) {
6 var BUILTIN = "builtin", COMMENT = "comment", STRING = "string", TAG = "tag",
7 ATOM = "atom", NUMBER = "number", BRACKET = "bracket", KEYWORD = "keyword";
8 var INDENT_WORD_SKIP = 2, KEYWORDS_SKIP = 1;
9
10 function makeKeywords(str) {
11 var obj = {}, words = str.split(" ");
12 for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
13 return obj;
14 }
15
16 var atoms = makeKeywords("true false nil");
17
18 var keywords = makeKeywords(
19 "defn defn- def def- defonce defmulti defmethod defmacro defstruct deftype defprotocol defrecord defproject deftest slice defalias defhinted defmacro- defn-memo defnk defnk defonce- defunbound defunbound- defvar defvar- let letfn do case cond condp for loop recur when when-not when-let when-first if if-let if-not . .. -> ->> doto and or dosync doseq dotimes dorun doall load import unimport ns in-ns refer try catch finally throw with-open with-local-vars binding gen-class gen-and-load-class gen-and-save-class handler-case handle");
20
21 var builtins = makeKeywords(
22 "* *1 *2 *3 *agent* *allow-unresolved-vars* *assert *clojure-version* *command-line-args* *compile-files* *compile-path* *e *err* *file* *flush-on-newline* *in* *macro-meta* *math-context* *ns* *out* *print-dup* *print-length* *print-level* *print-meta* *print-readably* *read-eval* *source-path* *use-context-classloader* *warn-on-reflection* + - / < <= = == > >= accessor aclone agent agent-errors aget alength alias all-ns alter alter-meta! alter-var-root amap ancestors and apply areduce array-map aset aset-boolean aset-byte aset-char aset-double aset-float aset-int aset-long aset-short assert assoc assoc! assoc-in associative? atom await await-for await1 bases bean bigdec bigint binding bit-and bit-and-not bit-clear bit-flip bit-not bit-or bit-set bit-shift-left bit-shift-right bit-test bit-xor boolean boolean-array booleans bound-fn bound-fn* butlast byte byte-array bytes case cast char char-array char-escape-string char-name-string char? chars chunk chunk-append chunk-buffer chunk-cons chunk-first chunk-next chunk-rest chunked-seq? class class? clear-agent-errors clojure-version coll? comment commute comp comparator compare compare-and-set! compile complement concat cond condp conj conj! cons constantly construct-proxy contains? count counted? create-ns create-struct cycle dec decimal? declare definline defmacro defmethod defmulti defn defn- defonce defstruct delay delay? deliver deref derive descendants destructure disj disj! dissoc dissoc! distinct distinct? doall doc dorun doseq dosync dotimes doto double double-array doubles drop drop-last drop-while empty empty? ensure enumeration-seq eval even? every? extend extend-protocol extend-type extends? extenders false? ffirst file-seq filter find find-doc find-ns find-var first float float-array float? floats flush fn fn? fnext for force format future future-call future-cancel future-cancelled? future-done? future? gen-class gen-interface gensym get get-in get-method get-proxy-class get-thread-bindings get-validator hash hash-map hash-set identical? identity if-let if-not ifn? import in-ns inc init-proxy instance? int int-array integer? interleave intern interpose into into-array ints io! isa? iterate iterator-seq juxt key keys keyword keyword? last lazy-cat lazy-seq let letfn line-seq list list* list? load load-file load-reader load-string loaded-libs locking long long-array longs loop macroexpand macroexpand-1 make-array make-hierarchy map map? mapcat max max-key memfn memoize merge merge-with meta method-sig methods min min-key mod name namespace neg? newline next nfirst nil? nnext not not-any? not-empty not-every? not= ns ns-aliases ns-imports ns-interns ns-map ns-name ns-publics ns-refers ns-resolve ns-unalias ns-unmap nth nthnext num number? odd? or parents partial partition pcalls peek persistent! pmap pop pop! pop-thread-bindings pos? pr pr-str prefer-method prefers primitives-classnames print print-ctor print-doc print-dup print-method print-namespace-doc print-simple print-special-doc print-str printf println println-str prn prn-str promise proxy proxy-call-with-super proxy-mappings proxy-name proxy-super push-thread-bindings pvalues quot rand rand-int range ratio? rational? rationalize re-find re-groups re-matcher re-matches re-pattern re-seq read read-line read-string reify reduce ref ref-history-count ref-max-history ref-min-history ref-set refer refer-clojure release-pending-sends rem remove remove-method remove-ns repeat repeatedly replace replicate require reset! reset-meta! resolve rest resultset-seq reverse reversible? rseq rsubseq satisfies? second select-keys send send-off seq seq? seque sequence sequential? set set-validator! set? short short-array shorts shutdown-agents slurp some sort sort-by sorted-map sorted-map-by sorted-set sorted-set-by sorted? special-form-anchor special-symbol? split-at split-with str stream? string? struct struct-map subs subseq subvec supers swap! symbol symbol? sync syntax-symbol-anchor take take-last take-nth take-while test the-ns time to-array to-array-2d trampoline transient tree-seq true? type unchecked-add unchecked-dec unchecked-divide unchecked-inc unchecked-multiply unchecked-negate unchecked-remainder unchecked-subtract underive unquote unquote-splicing update-in update-proxy use val vals var-get var-set var? vary-meta vec vector vector? when when-first when-let when-not while with-bindings with-bindings* with-in-str with-loading-context with-local-vars with-meta with-open with-out-str with-precision xml-seq");
23
24 var indentKeys = makeKeywords(
25 // Built-ins
26 "ns fn def defn defmethod bound-fn if if-not case condp when while when-not when-first do future comment doto locking proxy with-open with-precision reify deftype defrecord defprotocol extend extend-protocol extend-type try catch " +
27
28 // Binding forms
29 "let letfn binding loop for doseq dotimes when-let if-let " +
30
31 // Data structures
32 "defstruct struct-map assoc " +
33
34 // clojure.test
35 "testing deftest " +
36
37 // contrib
38 "handler-case handle dotrace deftrace");
39
40 var tests = {
41 digit: /\d/,
42 digit_or_colon: /[\d:]/,
43 hex: /[0-9a-fA-F]/,
44 sign: /[+-]/,
45 exponent: /[eE]/,
46 keyword_char: /[^\s\(\[\;\)\]]/,
47 basic: /[\w\$_\-]/,
48 lang_keyword: /[\w*+!\-_?:\/]/
49 };
50
51 function stateStack(indent, type, prev) { // represents a state stack object
52 this.indent = indent;
53 this.type = type;
54 this.prev = prev;
55 }
56
57 function pushStack(state, indent, type) {
58 state.indentStack = new stateStack(indent, type, state.indentStack);
59 }
60
61 function popStack(state) {
62 state.indentStack = state.indentStack.prev;
63 }
64
65 function isNumber(ch, stream){
66 // hex
67 if ( ch === '0' && 'x' == stream.peek().toLowerCase() ) {
68 stream.eat('x');
69 stream.eatWhile(tests.hex);
70 return true;
71 }
72
73 // leading sign
74 if ( ch == '+' || ch == '-' ) {
75 stream.eat(tests.sign);
76 ch = stream.next();
77 }
78
79 if ( tests.digit.test(ch) ) {
80 stream.eat(ch);
81 stream.eatWhile(tests.digit);
82
83 if ( '.' == stream.peek() ) {
84 stream.eat('.');
85 stream.eatWhile(tests.digit);
86 }
87
88 if ( 'e' == stream.peek().toLowerCase() ) {
89 stream.eat(tests.exponent);
90 stream.eat(tests.sign);
91 stream.eatWhile(tests.digit);
92 }
93
94 return true;
95 }
96
97 return false;
98 }
99
100 return {
101 startState: function () {
102 return {
103 indentStack: null,
104 indentation: 0,
105 mode: false
106 };
107 },
108
109 token: function (stream, state) {
110 if (state.indentStack == null && stream.sol()) {
111 // update indentation, but only if indentStack is empty
112 state.indentation = stream.indentation();
113 }
114
115 // skip spaces
116 if (stream.eatSpace()) {
117 return null;
118 }
119 var returnType = null;
120
121 switch(state.mode){
122 case "string": // multi-line string parsing mode
123 var next, escaped = false;
124 while ((next = stream.next()) != null) {
125 if (next == "\"" && !escaped) {
126
127 state.mode = false;
128 break;
129 }
130 escaped = !escaped && next == "\\";
131 }
132 returnType = STRING; // continue on in string mode
133 break;
134 default: // default parsing mode
135 var ch = stream.next();
136
137 if (ch == "\"") {
138 state.mode = "string";
139 returnType = STRING;
140 } else if (ch == "'" && !( tests.digit_or_colon.test(stream.peek()) )) {
141 returnType = ATOM;
142 } else if (ch == ";") { // comment
143 stream.skipToEnd(); // rest of the line is a comment
144 returnType = COMMENT;
145 } else if (isNumber(ch,stream)){
146 returnType = NUMBER;
147 } else if (ch == "(" || ch == "[") {
148 var keyWord = ''; var indentTemp = stream.column();
149 /**
150 Either
151 (indent-word ..
152 (non-indent-word ..
153 (;something else, bracket, etc.
154 */
155
156 if (ch == "(") while ((letter = stream.eat(tests.keyword_char)) != null) {
157 keyWord += letter;
158 }
159
160 if (keyWord.length > 0 && indentKeys.propertyIsEnumerable(keyWord)) { // indent-word
161 pushStack(state, indentTemp + INDENT_WORD_SKIP, ch);
162 } else { // non-indent word
163 // we continue eating the spaces
164 stream.eatSpace();
165 if (stream.eol() || stream.peek() == ";") {
166 // nothing significant after
167 // we restart indentation 1 space after
168 pushStack(state, indentTemp + 1, ch);
169 } else {
170 pushStack(state, indentTemp + stream.current().length, ch); // else we match
171 }
172 }
173 stream.backUp(stream.current().length - 1); // undo all the eating
174
175 returnType = BRACKET;
176 } else if (ch == ")" || ch == "]") {
177 returnType = BRACKET;
178 if (state.indentStack != null && state.indentStack.type == (ch == ")" ? "(" : "[")) {
179 popStack(state);
180 }
181 } else if ( ch == ":" ) {
182 stream.eatWhile(tests.lang_keyword);
183 return ATOM;
184 } else {
185 stream.eatWhile(tests.basic);
186
187 if (keywords && keywords.propertyIsEnumerable(stream.current())) {
188 returnType = KEYWORD;
189 } else if (builtins && builtins.propertyIsEnumerable(stream.current())) {
190 returnType = BUILTIN;
191 } else if (atoms && atoms.propertyIsEnumerable(stream.current())) {
192 returnType = ATOM;
193 } else returnType = null;
194 }
195 }
196
197 return returnType;
198 },
199
200 indent: function (state, textAfter) {
201 if (state.indentStack == null) return state.indentation;
202 return state.indentStack.indent;
203 }
204 };
205 });
206
207 CodeMirror.defineMIME("text/x-clojure", "clojure");
@@ -0,0 +1,66
1 <!doctype html>
2 <html>
3 <head>
4 <title>CodeMirror: Clojure mode</title>
5 <link rel="stylesheet" href="../../lib/codemirror.css">
6 <script src="../../lib/codemirror.js"></script>
7 <script src="clojure.js"></script>
8 <style>.CodeMirror {background: #f8f8f8;}</style>
9 <link rel="stylesheet" href="../../doc/docs.css">
10 </head>
11 <body>
12 <h1>CodeMirror: Clojure mode</h1>
13 <form><textarea id="code" name="code">
14 ; Conway's Game of Life, based on the work of:
15 ;; Laurent Petit https://gist.github.com/1200343
16 ;; Christophe Grand http://clj-me.cgrand.net/2011/08/19/conways-game-of-life
17
18 (ns ^{:doc "Conway's Game of Life."}
19 game-of-life)
20
21 ;; Core game of life's algorithm functions
22
23 (defn neighbours
24 "Given a cell's coordinates, returns the coordinates of its neighbours."
25 [[x y]]
26 (for [dx [-1 0 1] dy (if (zero? dx) [-1 1] [-1 0 1])]
27 [(+ dx x) (+ dy y)]))
28
29 (defn step
30 "Given a set of living cells, computes the new set of living cells."
31 [cells]
32 (set (for [[cell n] (frequencies (mapcat neighbours cells))
33 :when (or (= n 3) (and (= n 2) (cells cell)))]
34 cell)))
35
36 ;; Utility methods for displaying game on a text terminal
37
38 (defn print-board
39 "Prints a board on *out*, representing a step in the game."
40 [board w h]
41 (doseq [x (range (inc w)) y (range (inc h))]
42 (if (= y 0) (print "\n"))
43 (print (if (board [x y]) "[X]" " . "))))
44
45 (defn display-grids
46 "Prints a squence of boards on *out*, representing several steps."
47 [grids w h]
48 (doseq [board grids]
49 (print-board board w h)
50 (print "\n")))
51
52 ;; Launches an example board
53
54 (def
55 ^{:doc "board represents the initial set of living cells"}
56 board #{[2 1] [2 2] [2 3]})
57
58 (display-grids (take 3 (iterate step board)) 5 5) </textarea></form>
59 <script>
60 var editor = CodeMirror.fromTextArea(document.getElementById("code"), {});
61 </script>
62
63 <p><strong>MIME types defined:</strong> <code>text/x-clojure</code>.</p>
64
65 </body>
66 </html>
@@ -0,0 +1,22
1 The MIT License
2
3 Copyright (c) 2011 Jeff Pickhardt
4 Modified from the Python CodeMirror mode, Copyright (c) 2010 Timothy Farrell
5
6 Permission is hereby granted, free of charge, to any person obtaining a copy
7 of this software and associated documentation files (the "Software"), to deal
8 in the Software without restriction, including without limitation the rights
9 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 copies of the Software, and to permit persons to whom the Software is
11 furnished to do so, subject to the following conditions:
12
13 The above copyright notice and this permission notice shall be included in
14 all copies or substantial portions of the Software.
15
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 THE SOFTWARE. No newline at end of file
@@ -0,0 +1,346
1 /**
2 * Link to the project's GitHub page:
3 * https://github.com/pickhardt/coffeescript-codemirror-mode
4 */
5 CodeMirror.defineMode('coffeescript', function(conf) {
6 var ERRORCLASS = 'error';
7
8 function wordRegexp(words) {
9 return new RegExp("^((" + words.join(")|(") + "))\\b");
10 }
11
12 var singleOperators = new RegExp("^[\\+\\-\\*/%&|\\^~<>!\?]");
13 var singleDelimiters = new RegExp('^[\\(\\)\\[\\]\\{\\},:`=;\\.]');
14 var doubleOperators = new RegExp("^((\->)|(\=>)|(\\+\\+)|(\\+\\=)|(\\-\\-)|(\\-\\=)|(\\*\\*)|(\\*\\=)|(\\/\\/)|(\\/\\=)|(==)|(!=)|(<=)|(>=)|(<>)|(<<)|(>>)|(//))");
15 var doubleDelimiters = new RegExp("^((\\.\\.)|(\\+=)|(\\-=)|(\\*=)|(%=)|(/=)|(&=)|(\\|=)|(\\^=))");
16 var tripleDelimiters = new RegExp("^((\\.\\.\\.)|(//=)|(>>=)|(<<=)|(\\*\\*=))");
17 var identifiers = new RegExp("^[_A-Za-z$][_A-Za-z$0-9]*");
18 var properties = new RegExp("^(@|this\.)[_A-Za-z$][_A-Za-z$0-9]*");
19
20 var wordOperators = wordRegexp(['and', 'or', 'not',
21 'is', 'isnt', 'in',
22 'instanceof', 'typeof']);
23 var indentKeywords = ['for', 'while', 'loop', 'if', 'unless', 'else',
24 'switch', 'try', 'catch', 'finally', 'class'];
25 var commonKeywords = ['break', 'by', 'continue', 'debugger', 'delete',
26 'do', 'in', 'of', 'new', 'return', 'then',
27 'this', 'throw', 'when', 'until'];
28
29 var keywords = wordRegexp(indentKeywords.concat(commonKeywords));
30
31 indentKeywords = wordRegexp(indentKeywords);
32
33
34 var stringPrefixes = new RegExp("^('{3}|\"{3}|['\"])");
35 var regexPrefixes = new RegExp("^(/{3}|/)");
36 var commonConstants = ['Infinity', 'NaN', 'undefined', 'null', 'true', 'false', 'on', 'off', 'yes', 'no'];
37 var constants = wordRegexp(commonConstants);
38
39 // Tokenizers
40 function tokenBase(stream, state) {
41 // Handle scope changes
42 if (stream.sol()) {
43 var scopeOffset = state.scopes[0].offset;
44 if (stream.eatSpace()) {
45 var lineOffset = stream.indentation();
46 if (lineOffset > scopeOffset) {
47 return 'indent';
48 } else if (lineOffset < scopeOffset) {
49 return 'dedent';
50 }
51 return null;
52 } else {
53 if (scopeOffset > 0) {
54 dedent(stream, state);
55 }
56 }
57 }
58 if (stream.eatSpace()) {
59 return null;
60 }
61
62 var ch = stream.peek();
63
64 // Handle docco title comment (single line)
65 if (stream.match("####")) {
66 stream.skipToEnd();
67 return 'comment';
68 }
69
70 // Handle multi line comments
71 if (stream.match("###")) {
72 state.tokenize = longComment;
73 return state.tokenize(stream, state);
74 }
75
76 // Single line comment
77 if (ch === '#') {
78 stream.skipToEnd();
79 return 'comment';
80 }
81
82 // Handle number literals
83 if (stream.match(/^-?[0-9\.]/, false)) {
84 var floatLiteral = false;
85 // Floats
86 if (stream.match(/^-?\d*\.\d+(e[\+\-]?\d+)?/i)) {
87 floatLiteral = true;
88 }
89 if (stream.match(/^-?\d+\.\d*/)) {
90 floatLiteral = true;
91 }
92 if (stream.match(/^-?\.\d+/)) {
93 floatLiteral = true;
94 }
95
96 if (floatLiteral) {
97 // prevent from getting extra . on 1..
98 if (stream.peek() == "."){
99 stream.backUp(1);
100 }
101 return 'number';
102 }
103 // Integers
104 var intLiteral = false;
105 // Hex
106 if (stream.match(/^-?0x[0-9a-f]+/i)) {
107 intLiteral = true;
108 }
109 // Decimal
110 if (stream.match(/^-?[1-9]\d*(e[\+\-]?\d+)?/)) {
111 intLiteral = true;
112 }
113 // Zero by itself with no other piece of number.
114 if (stream.match(/^-?0(?![\dx])/i)) {
115 intLiteral = true;
116 }
117 if (intLiteral) {
118 return 'number';
119 }
120 }
121
122 // Handle strings
123 if (stream.match(stringPrefixes)) {
124 state.tokenize = tokenFactory(stream.current(), 'string');
125 return state.tokenize(stream, state);
126 }
127 // Handle regex literals
128 if (stream.match(regexPrefixes)) {
129 if (stream.current() != '/' || stream.match(/^.*\//, false)) { // prevent highlight of division
130 state.tokenize = tokenFactory(stream.current(), 'string-2');
131 return state.tokenize(stream, state);
132 } else {
133 stream.backUp(1);
134 }
135 }
136
137 // Handle operators and delimiters
138 if (stream.match(tripleDelimiters) || stream.match(doubleDelimiters)) {
139 return 'punctuation';
140 }
141 if (stream.match(doubleOperators)
142 || stream.match(singleOperators)
143 || stream.match(wordOperators)) {
144 return 'operator';
145 }
146 if (stream.match(singleDelimiters)) {
147 return 'punctuation';
148 }
149
150 if (stream.match(constants)) {
151 return 'atom';
152 }
153
154 if (stream.match(keywords)) {
155 return 'keyword';
156 }
157
158 if (stream.match(identifiers)) {
159 return 'variable';
160 }
161
162 if (stream.match(properties)) {
163 return 'property';
164 }
165
166 // Handle non-detected items
167 stream.next();
168 return ERRORCLASS;
169 }
170
171 function tokenFactory(delimiter, outclass) {
172 var singleline = delimiter.length == 1;
173 return function tokenString(stream, state) {
174 while (!stream.eol()) {
175 stream.eatWhile(/[^'"\/\\]/);
176 if (stream.eat('\\')) {
177 stream.next();
178 if (singleline && stream.eol()) {
179 return outclass;
180 }
181 } else if (stream.match(delimiter)) {
182 state.tokenize = tokenBase;
183 return outclass;
184 } else {
185 stream.eat(/['"\/]/);
186 }
187 }
188 if (singleline) {
189 if (conf.mode.singleLineStringErrors) {
190 outclass = ERRORCLASS
191 } else {
192 state.tokenize = tokenBase;
193 }
194 }
195 return outclass;
196 };
197 }
198
199 function longComment(stream, state) {
200 while (!stream.eol()) {
201 stream.eatWhile(/[^#]/);
202 if (stream.match("###")) {
203 state.tokenize = tokenBase;
204 break;
205 }
206 stream.eatWhile("#");
207 }
208 return "comment"
209 }
210
211 function indent(stream, state, type) {
212 type = type || 'coffee';
213 var indentUnit = 0;
214 if (type === 'coffee') {
215 for (var i = 0; i < state.scopes.length; i++) {
216 if (state.scopes[i].type === 'coffee') {
217 indentUnit = state.scopes[i].offset + conf.indentUnit;
218 break;
219 }
220 }
221 } else {
222 indentUnit = stream.column() + stream.current().length;
223 }
224 state.scopes.unshift({
225 offset: indentUnit,
226 type: type
227 });
228 }
229
230 function dedent(stream, state) {
231 if (state.scopes.length == 1) return;
232 if (state.scopes[0].type === 'coffee') {
233 var _indent = stream.indentation();
234 var _indent_index = -1;
235 for (var i = 0; i < state.scopes.length; ++i) {
236 if (_indent === state.scopes[i].offset) {
237 _indent_index = i;
238 break;
239 }
240 }
241 if (_indent_index === -1) {
242 return true;
243 }
244 while (state.scopes[0].offset !== _indent) {
245 state.scopes.shift();
246 }
247 return false
248 } else {
249 state.scopes.shift();
250 return false;
251 }
252 }
253
254 function tokenLexer(stream, state) {
255 var style = state.tokenize(stream, state);
256 var current = stream.current();
257
258 // Handle '.' connected identifiers
259 if (current === '.') {
260 style = state.tokenize(stream, state);
261 current = stream.current();
262 if (style === 'variable') {
263 return 'variable';
264 } else {
265 return ERRORCLASS;
266 }
267 }
268
269 // Handle scope changes.
270 if (current === 'return') {
271 state.dedent += 1;
272 }
273 if (((current === '->' || current === '=>') &&
274 !state.lambda &&
275 state.scopes[0].type == 'coffee' &&
276 stream.peek() === '')
277 || style === 'indent') {
278 indent(stream, state);
279 }
280 var delimiter_index = '[({'.indexOf(current);
281 if (delimiter_index !== -1) {
282 indent(stream, state, '])}'.slice(delimiter_index, delimiter_index+1));
283 }
284 if (indentKeywords.exec(current)){
285 indent(stream, state);
286 }
287 if (current == 'then'){
288 dedent(stream, state);
289 }
290
291
292 if (style === 'dedent') {
293 if (dedent(stream, state)) {
294 return ERRORCLASS;
295 }
296 }
297 delimiter_index = '])}'.indexOf(current);
298 if (delimiter_index !== -1) {
299 if (dedent(stream, state)) {
300 return ERRORCLASS;
301 }
302 }
303 if (state.dedent > 0 && stream.eol() && state.scopes[0].type == 'coffee') {
304 if (state.scopes.length > 1) state.scopes.shift();
305 state.dedent -= 1;
306 }
307
308 return style;
309 }
310
311 var external = {
312 startState: function(basecolumn) {
313 return {
314 tokenize: tokenBase,
315 scopes: [{offset:basecolumn || 0, type:'coffee'}],
316 lastToken: null,
317 lambda: false,
318 dedent: 0
319 };
320 },
321
322 token: function(stream, state) {
323 var style = tokenLexer(stream, state);
324
325 state.lastToken = {style:style, content: stream.current()};
326
327 if (stream.eol() && stream.lambda) {
328 state.lambda = false;
329 }
330
331 return style;
332 },
333
334 indent: function(state, textAfter) {
335 if (state.tokenize != tokenBase) {
336 return 0;
337 }
338
339 return state.scopes[0].offset;
340 }
341
342 };
343 return external;
344 });
345
346 CodeMirror.defineMIME('text/x-coffeescript', 'coffeescript');
This diff has been collapsed as it changes many lines, (727 lines changed) Show them Hide them
@@ -0,0 +1,727
1 <!doctype html>
2 <html>
3 <head>
4 <title>CodeMirror: CoffeeScript mode</title>
5 <link rel="stylesheet" href="../../lib/codemirror.css">
6 <script src="../../lib/codemirror.js"></script>
7 <script src="coffeescript.js"></script>
8 <style>.CodeMirror {border-top: 1px solid silver; border-bottom: 1px solid silver;}</style>
9 <link rel="stylesheet" href="../../doc/docs.css">
10 </head>
11 <body>
12 <h1>CodeMirror: CoffeeScript mode</h1>
13 <form><textarea id="code" name="code">
14 # CoffeeScript mode for CodeMirror
15 # Copyright (c) 2011 Jeff Pickhardt, released under
16 # the MIT License.
17 #
18 # Modified from the Python CodeMirror mode, which also is
19 # under the MIT License Copyright (c) 2010 Timothy Farrell.
20 #
21 # The following script, Underscore.coffee, is used to
22 # demonstrate CoffeeScript mode for CodeMirror.
23 #
24 # To download CoffeeScript mode for CodeMirror, go to:
25 # https://github.com/pickhardt/coffeescript-codemirror-mode
26
27 # **Underscore.coffee
28 # (c) 2011 Jeremy Ashkenas, DocumentCloud Inc.**
29 # Underscore is freely distributable under the terms of the
30 # [MIT license](http://en.wikipedia.org/wiki/MIT_License).
31 # Portions of Underscore are inspired by or borrowed from
32 # [Prototype.js](http://prototypejs.org/api), Oliver Steele's
33 # [Functional](http://osteele.com), and John Resig's
34 # [Micro-Templating](http://ejohn.org).
35 # For all details and documentation:
36 # http://documentcloud.github.com/underscore/
37
38
39 # Baseline setup
40 # --------------
41
42 # Establish the root object, `window` in the browser, or `global` on the server.
43 root = this
44
45
46 # Save the previous value of the `_` variable.
47 previousUnderscore = root._
48
49 ### Multiline
50 comment
51 ###
52
53 # Establish the object that gets thrown to break out of a loop iteration.
54 # `StopIteration` is SOP on Mozilla.
55 breaker = if typeof(StopIteration) is 'undefined' then '__break__' else StopIteration
56
57
58 #### Docco style single line comment (title)
59
60
61 # Helper function to escape **RegExp** contents, because JS doesn't have one.
62 escapeRegExp = (string) -> string.replace(/([.*+?^${}()|[\]\/\\])/g, '\\$1')
63
64
65 # Save bytes in the minified (but not gzipped) version:
66 ArrayProto = Array.prototype
67 ObjProto = Object.prototype
68
69
70 # Create quick reference variables for speed access to core prototypes.
71 slice = ArrayProto.slice
72 unshift = ArrayProto.unshift
73 toString = ObjProto.toString
74 hasOwnProperty = ObjProto.hasOwnProperty
75 propertyIsEnumerable = ObjProto.propertyIsEnumerable
76
77
78 # All **ECMA5** native implementations we hope to use are declared here.
79 nativeForEach = ArrayProto.forEach
80 nativeMap = ArrayProto.map
81 nativeReduce = ArrayProto.reduce
82 nativeReduceRight = ArrayProto.reduceRight
83 nativeFilter = ArrayProto.filter
84 nativeEvery = ArrayProto.every
85 nativeSome = ArrayProto.some
86 nativeIndexOf = ArrayProto.indexOf
87 nativeLastIndexOf = ArrayProto.lastIndexOf
88 nativeIsArray = Array.isArray
89 nativeKeys = Object.keys
90
91
92 # Create a safe reference to the Underscore object for use below.
93 _ = (obj) -> new wrapper(obj)
94
95
96 # Export the Underscore object for **CommonJS**.
97 if typeof(exports) != 'undefined' then exports._ = _
98
99
100 # Export Underscore to global scope.
101 root._ = _
102
103
104 # Current version.
105 _.VERSION = '1.1.0'
106
107
108 # Collection Functions
109 # --------------------
110
111 # The cornerstone, an **each** implementation.
112 # Handles objects implementing **forEach**, arrays, and raw objects.
113 _.each = (obj, iterator, context) ->
114 try
115 if nativeForEach and obj.forEach is nativeForEach
116 obj.forEach iterator, context
117 else if _.isNumber obj.length
118 iterator.call context, obj[i], i, obj for i in [0...obj.length]
119 else
120 iterator.call context, val, key, obj for own key, val of obj
121 catch e
122 throw e if e isnt breaker
123 obj
124
125
126 # Return the results of applying the iterator to each element. Use JavaScript
127 # 1.6's version of **map**, if possible.
128 _.map = (obj, iterator, context) ->
129 return obj.map(iterator, context) if nativeMap and obj.map is nativeMap
130 results = []
131 _.each obj, (value, index, list) ->
132 results.push iterator.call context, value, index, list
133 results
134
135
136 # **Reduce** builds up a single result from a list of values. Also known as
137 # **inject**, or **foldl**. Uses JavaScript 1.8's version of **reduce**, if possible.
138 _.reduce = (obj, iterator, memo, context) ->
139 if nativeReduce and obj.reduce is nativeReduce
140 iterator = _.bind iterator, context if context
141 return obj.reduce iterator, memo
142 _.each obj, (value, index, list) ->
143 memo = iterator.call context, memo, value, index, list
144 memo
145
146
147 # The right-associative version of **reduce**, also known as **foldr**. Uses
148 # JavaScript 1.8's version of **reduceRight**, if available.
149 _.reduceRight = (obj, iterator, memo, context) ->
150 if nativeReduceRight and obj.reduceRight is nativeReduceRight
151 iterator = _.bind iterator, context if context
152 return obj.reduceRight iterator, memo
153 reversed = _.clone(_.toArray(obj)).reverse()
154 _.reduce reversed, iterator, memo, context
155
156
157 # Return the first value which passes a truth test.
158 _.detect = (obj, iterator, context) ->
159 result = null
160 _.each obj, (value, index, list) ->
161 if iterator.call context, value, index, list
162 result = value
163 _.breakLoop()
164 result
165
166
167 # Return all the elements that pass a truth test. Use JavaScript 1.6's
168 # **filter**, if it exists.
169 _.filter = (obj, iterator, context) ->
170 return obj.filter iterator, context if nativeFilter and obj.filter is nativeFilter
171 results = []
172 _.each obj, (value, index, list) ->
173 results.push value if iterator.call context, value, index, list
174 results
175
176
177 # Return all the elements for which a truth test fails.
178 _.reject = (obj, iterator, context) ->
179 results = []
180 _.each obj, (value, index, list) ->
181 results.push value if not iterator.call context, value, index, list
182 results
183
184
185 # Determine whether all of the elements match a truth test. Delegate to
186 # JavaScript 1.6's **every**, if it is present.
187 _.every = (obj, iterator, context) ->
188 iterator ||= _.identity
189 return obj.every iterator, context if nativeEvery and obj.every is nativeEvery
190 result = true
191 _.each obj, (value, index, list) ->
192 _.breakLoop() unless (result = result and iterator.call(context, value, index, list))
193 result
194
195
196 # Determine if at least one element in the object matches a truth test. Use
197 # JavaScript 1.6's **some**, if it exists.
198 _.some = (obj, iterator, context) ->
199 iterator ||= _.identity
200 return obj.some iterator, context if nativeSome and obj.some is nativeSome
201 result = false
202 _.each obj, (value, index, list) ->
203 _.breakLoop() if (result = iterator.call(context, value, index, list))
204 result
205
206
207 # Determine if a given value is included in the array or object,
208 # based on `===`.
209 _.include = (obj, target) ->
210 return _.indexOf(obj, target) isnt -1 if nativeIndexOf and obj.indexOf is nativeIndexOf
211 return true for own key, val of obj when val is target
212 false
213
214
215 # Invoke a method with arguments on every item in a collection.
216 _.invoke = (obj, method) ->
217 args = _.rest arguments, 2
218 (if method then val[method] else val).apply(val, args) for val in obj
219
220
221 # Convenience version of a common use case of **map**: fetching a property.
222 _.pluck = (obj, key) ->
223 _.map(obj, (val) -> val[key])
224
225
226 # Return the maximum item or (item-based computation).
227 _.max = (obj, iterator, context) ->
228 return Math.max.apply(Math, obj) if not iterator and _.isArray(obj)
229 result = computed: -Infinity
230 _.each obj, (value, index, list) ->
231 computed = if iterator then iterator.call(context, value, index, list) else value
232 computed >= result.computed and (result = {value: value, computed: computed})
233 result.value
234
235
236 # Return the minimum element (or element-based computation).
237 _.min = (obj, iterator, context) ->
238 return Math.min.apply(Math, obj) if not iterator and _.isArray(obj)
239 result = computed: Infinity
240 _.each obj, (value, index, list) ->
241 computed = if iterator then iterator.call(context, value, index, list) else value
242 computed < result.computed and (result = {value: value, computed: computed})
243 result.value
244
245
246 # Sort the object's values by a criterion produced by an iterator.
247 _.sortBy = (obj, iterator, context) ->
248 _.pluck(((_.map obj, (value, index, list) ->
249 {value: value, criteria: iterator.call(context, value, index, list)}
250 ).sort((left, right) ->
251 a = left.criteria; b = right.criteria
252 if a < b then -1 else if a > b then 1 else 0
253 )), 'value')
254
255
256 # Use a comparator function to figure out at what index an object should
257 # be inserted so as to maintain order. Uses binary search.
258 _.sortedIndex = (array, obj, iterator) ->
259 iterator ||= _.identity
260 low = 0
261 high = array.length
262 while low < high
263 mid = (low + high) >> 1
264 if iterator(array[mid]) < iterator(obj) then low = mid + 1 else high = mid
265 low
266
267
268 # Convert anything iterable into a real, live array.
269 _.toArray = (iterable) ->
270 return [] if (!iterable)
271 return iterable.toArray() if (iterable.toArray)
272 return iterable if (_.isArray(iterable))
273 return slice.call(iterable) if (_.isArguments(iterable))
274 _.values(iterable)
275
276
277 # Return the number of elements in an object.
278 _.size = (obj) -> _.toArray(obj).length
279
280
281 # Array Functions
282 # ---------------
283
284 # Get the first element of an array. Passing `n` will return the first N
285 # values in the array. Aliased as **head**. The `guard` check allows it to work
286 # with **map**.
287 _.first = (array, n, guard) ->
288 if n and not guard then slice.call(array, 0, n) else array[0]
289
290
291 # Returns everything but the first entry of the array. Aliased as **tail**.
292 # Especially useful on the arguments object. Passing an `index` will return
293 # the rest of the values in the array from that index onward. The `guard`
294 # check allows it to work with **map**.
295 _.rest = (array, index, guard) ->
296 slice.call(array, if _.isUndefined(index) or guard then 1 else index)
297
298
299 # Get the last element of an array.
300 _.last = (array) -> array[array.length - 1]
301
302
303 # Trim out all falsy values from an array.
304 _.compact = (array) -> item for item in array when item
305
306
307 # Return a completely flattened version of an array.
308 _.flatten = (array) ->
309 _.reduce array, (memo, value) ->
310 return memo.concat(_.flatten(value)) if _.isArray value
311 memo.push value
312 memo
313 , []
314
315
316 # Return a version of the array that does not contain the specified value(s).
317 _.without = (array) ->
318 values = _.rest arguments
319 val for val in _.toArray(array) when not _.include values, val
320
321
322 # Produce a duplicate-free version of the array. If the array has already
323 # been sorted, you have the option of using a faster algorithm.
324 _.uniq = (array, isSorted) ->
325 memo = []
326 for el, i in _.toArray array
327 memo.push el if i is 0 || (if isSorted is true then _.last(memo) isnt el else not _.include(memo, el))
328 memo
329
330
331 # Produce an array that contains every item shared between all the
332 # passed-in arrays.
333 _.intersect = (array) ->
334 rest = _.rest arguments
335 _.select _.uniq(array), (item) ->
336 _.all rest, (other) ->
337 _.indexOf(other, item) >= 0
338
339
340 # Zip together multiple lists into a single array -- elements that share
341 # an index go together.
342 _.zip = ->
343 length = _.max _.pluck arguments, 'length'
344 results = new Array length
345 for i in [0...length]
346 results[i] = _.pluck arguments, String i
347 results
348
349
350 # If the browser doesn't supply us with **indexOf** (I'm looking at you, MSIE),
351 # we need this function. Return the position of the first occurrence of an
352 # item in an array, or -1 if the item is not included in the array.
353 _.indexOf = (array, item) ->
354 return array.indexOf item if nativeIndexOf and array.indexOf is nativeIndexOf
355 i = 0; l = array.length
356 while l - i
357 if array[i] is item then return i else i++
358 -1
359
360
361 # Provide JavaScript 1.6's **lastIndexOf**, delegating to the native function,
362 # if possible.
363 _.lastIndexOf = (array, item) ->
364 return array.lastIndexOf(item) if nativeLastIndexOf and array.lastIndexOf is nativeLastIndexOf
365 i = array.length
366 while i
367 if array[i] is item then return i else i--
368 -1
369
370
371 # Generate an integer Array containing an arithmetic progression. A port of
372 # [the native Python **range** function](http://docs.python.org/library/functions.html#range).
373 _.range = (start, stop, step) ->
374 a = arguments
375 solo = a.length <= 1
376 i = start = if solo then 0 else a[0]
377 stop = if solo then a[0] else a[1]
378 step = a[2] or 1
379 len = Math.ceil((stop - start) / step)
380 return [] if len <= 0
381 range = new Array len
382 idx = 0
383 loop
384 return range if (if step > 0 then i - stop else stop - i) >= 0
385 range[idx] = i
386 idx++
387 i+= step
388
389
390 # Function Functions
391 # ------------------
392
393 # Create a function bound to a given object (assigning `this`, and arguments,
394 # optionally). Binding with arguments is also known as **curry**.
395 _.bind = (func, obj) ->
396 args = _.rest arguments, 2
397 -> func.apply obj or root, args.concat arguments
398
399
400 # Bind all of an object's methods to that object. Useful for ensuring that
401 # all callbacks defined on an object belong to it.
402 _.bindAll = (obj) ->
403 funcs = if arguments.length > 1 then _.rest(arguments) else _.functions(obj)
404 _.each funcs, (f) -> obj[f] = _.bind obj[f], obj
405 obj
406
407
408 # Delays a function for the given number of milliseconds, and then calls
409 # it with the arguments supplied.
410 _.delay = (func, wait) ->
411 args = _.rest arguments, 2
412 setTimeout((-> func.apply(func, args)), wait)
413
414
415 # Memoize an expensive function by storing its results.
416 _.memoize = (func, hasher) ->
417 memo = {}
418 hasher or= _.identity
419 ->
420 key = hasher.apply this, arguments
421 return memo[key] if key of memo
422 memo[key] = func.apply this, arguments
423
424
425 # Defers a function, scheduling it to run after the current call stack has
426 # cleared.
427 _.defer = (func) ->
428 _.delay.apply _, [func, 1].concat _.rest arguments
429
430
431 # Returns the first function passed as an argument to the second,
432 # allowing you to adjust arguments, run code before and after, and
433 # conditionally execute the original function.
434 _.wrap = (func, wrapper) ->
435 -> wrapper.apply wrapper, [func].concat arguments
436
437
438 # Returns a function that is the composition of a list of functions, each
439 # consuming the return value of the function that follows.
440 _.compose = ->
441 funcs = arguments
442 ->
443 args = arguments
444 for i in [funcs.length - 1..0] by -1
445 args = [funcs[i].apply(this, args)]
446 args[0]
447
448
449 # Object Functions
450 # ----------------
451
452 # Retrieve the names of an object's properties.
453 _.keys = nativeKeys or (obj) ->
454 return _.range 0, obj.length if _.isArray(obj)
455 key for key, val of obj
456
457
458 # Retrieve the values of an object's properties.
459 _.values = (obj) ->
460 _.map obj, _.identity
461
462
463 # Return a sorted list of the function names available in Underscore.
464 _.functions = (obj) ->
465 _.filter(_.keys(obj), (key) -> _.isFunction(obj[key])).sort()
466
467
468 # Extend a given object with all of the properties in a source object.
469 _.extend = (obj) ->
470 for source in _.rest(arguments)
471 obj[key] = val for key, val of source
472 obj
473
474
475 # Create a (shallow-cloned) duplicate of an object.
476 _.clone = (obj) ->
477 return obj.slice 0 if _.isArray obj
478 _.extend {}, obj
479
480
481 # Invokes interceptor with the obj, and then returns obj.
482 # The primary purpose of this method is to "tap into" a method chain,
483 # in order to perform operations on intermediate results within
484 the chain.
485 _.tap = (obj, interceptor) ->
486 interceptor obj
487 obj
488
489
490 # Perform a deep comparison to check if two objects are equal.
491 _.isEqual = (a, b) ->
492 # Check object identity.
493 return true if a is b
494 # Different types?
495 atype = typeof(a); btype = typeof(b)
496 return false if atype isnt btype
497 # Basic equality test (watch out for coercions).
498 return true if `a == b`
499 # One is falsy and the other truthy.
500 return false if (!a and b) or (a and !b)
501 # One of them implements an `isEqual()`?
502 return a.isEqual(b) if a.isEqual
503 # Check dates' integer values.
504 return a.getTime() is b.getTime() if _.isDate(a) and _.isDate(b)
505 # Both are NaN?
506 return false if _.isNaN(a) and _.isNaN(b)
507 # Compare regular expressions.
508 if _.isRegExp(a) and _.isRegExp(b)
509 return a.source is b.source and
510 a.global is b.global and
511 a.ignoreCase is b.ignoreCase and
512 a.multiline is b.multiline
513 # If a is not an object by this point, we can't handle it.
514 return false if atype isnt 'object'
515 # Check for different array lengths before comparing contents.
516 return false if a.length and (a.length isnt b.length)
517 # Nothing else worked, deep compare the contents.
518 aKeys = _.keys(a); bKeys = _.keys(b)
519 # Different object sizes?
520 return false if aKeys.length isnt bKeys.length
521 # Recursive comparison of contents.
522 return false for key, val of a when !(key of b) or !_.isEqual(val, b[key])
523 true
524
525
526 # Is a given array or object empty?
527 _.isEmpty = (obj) ->
528 return obj.length is 0 if _.isArray(obj) or _.isString(obj)
529 return false for own key of obj
530 true
531
532
533 # Is a given value a DOM element?
534 _.isElement = (obj) -> obj and obj.nodeType is 1
535
536
537 # Is a given value an array?
538 _.isArray = nativeIsArray or (obj) -> !!(obj and obj.concat and obj.unshift and not obj.callee)
539
540
541 # Is a given variable an arguments object?
542 _.isArguments = (obj) -> obj and obj.callee
543
544
545 # Is the given value a function?
546 _.isFunction = (obj) -> !!(obj and obj.constructor and obj.call and obj.apply)
547
548
549 # Is the given value a string?
550 _.isString = (obj) -> !!(obj is '' or (obj and obj.charCodeAt and obj.substr))
551
552
553 # Is a given value a number?
554 _.isNumber = (obj) -> (obj is +obj) or toString.call(obj) is '[object Number]'
555
556
557 # Is a given value a boolean?
558 _.isBoolean = (obj) -> obj is true or obj is false
559
560
561 # Is a given value a Date?
562 _.isDate = (obj) -> !!(obj and obj.getTimezoneOffset and obj.setUTCFullYear)
563
564
565 # Is the given value a regular expression?
566 _.isRegExp = (obj) -> !!(obj and obj.exec and (obj.ignoreCase or obj.ignoreCase is false))
567
568
569 # Is the given value NaN -- this one is interesting. `NaN != NaN`, and
570 # `isNaN(undefined) == true`, so we make sure it's a number first.
571 _.isNaN = (obj) -> _.isNumber(obj) and window.isNaN(obj)
572
573
574 # Is a given value equal to null?
575 _.isNull = (obj) -> obj is null
576
577
578 # Is a given variable undefined?
579 _.isUndefined = (obj) -> typeof obj is 'undefined'
580
581
582 # Utility Functions
583 # -----------------
584
585 # Run Underscore.js in noConflict mode, returning the `_` variable to its
586 # previous owner. Returns a reference to the Underscore object.
587 _.noConflict = ->
588 root._ = previousUnderscore
589 this
590
591
592 # Keep the identity function around for default iterators.
593 _.identity = (value) -> value
594
595
596 # Run a function `n` times.
597 _.times = (n, iterator, context) ->
598 iterator.call context, i for i in [0...n]
599
600
601 # Break out of the middle of an iteration.
602 _.breakLoop = -> throw breaker
603
604
605 # Add your own custom functions to the Underscore object, ensuring that
606 # they're correctly added to the OOP wrapper as well.
607 _.mixin = (obj) ->
608 for name in _.functions(obj)
609 addToWrapper name, _[name] = obj[name]
610
611
612 # Generate a unique integer id (unique within the entire client session).
613 # Useful for temporary DOM ids.
614 idCounter = 0
615 _.uniqueId = (prefix) ->
616 (prefix or '') + idCounter++
617
618
619 # By default, Underscore uses **ERB**-style template delimiters, change the
620 # following template settings to use alternative delimiters.
621 _.templateSettings = {
622 start: '<%'
623 end: '%>'
624 interpolate: /<%=(.+?)%>/g
625 }
626
627
628 # JavaScript templating a-la **ERB**, pilfered from John Resig's
629 # *Secrets of the JavaScript Ninja*, page 83.
630 # Single-quote fix from Rick Strahl.
631 # With alterations for arbitrary delimiters, and to preserve whitespace.
632 _.template = (str, data) ->
633 c = _.templateSettings
634 endMatch = new RegExp("'(?=[^"+c.end.substr(0, 1)+"]*"+escapeRegExp(c.end)+")","g")
635 fn = new Function 'obj',
636 'var p=[],print=function(){p.push.apply(p,arguments);};' +
637 'with(obj||{}){p.push(\'' +
638 str.replace(/\r/g, '\\r')
639 .replace(/\n/g, '\\n')
640 .replace(/\t/g, '\\t')
641 .replace(endMatch,"���")
642 .split("'").join("\\'")
643 .split("���").join("'")
644 .replace(c.interpolate, "',$1,'")
645 .split(c.start).join("');")
646 .split(c.end).join("p.push('") +
647 "');}return p.join('');"
648 if data then fn(data) else fn
649
650
651 # Aliases
652 # -------
653
654 _.forEach = _.each
655 _.foldl = _.inject = _.reduce
656 _.foldr = _.reduceRight
657 _.select = _.filter
658 _.all = _.every
659 _.any = _.some
660 _.contains = _.include
661 _.head = _.first
662 _.tail = _.rest
663 _.methods = _.functions
664
665
666 # Setup the OOP Wrapper
667 # ---------------------
668
669 # If Underscore is called as a function, it returns a wrapped object that
670 # can be used OO-style. This wrapper holds altered versions of all the
671 # underscore functions. Wrapped objects may be chained.
672 wrapper = (obj) ->
673 this._wrapped = obj
674 this
675
676
677 # Helper function to continue chaining intermediate results.
678 result = (obj, chain) ->
679 if chain then _(obj).chain() else obj
680
681
682 # A method to easily add functions to the OOP wrapper.
683 addToWrapper = (name, func) ->
684 wrapper.prototype[name] = ->
685 args = _.toArray arguments
686 unshift.call args, this._wrapped
687 result func.apply(_, args), this._chain
688
689
690 # Add all ofthe Underscore functions to the wrapper object.
691 _.mixin _
692
693
694 # Add all mutator Array functions to the wrapper.
695 _.each ['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], (name) ->
696 method = Array.prototype[name]
697 wrapper.prototype[name] = ->
698 method.apply(this._wrapped, arguments)
699 result(this._wrapped, this._chain)
700
701
702 # Add all accessor Array functions to the wrapper.
703 _.each ['concat', 'join', 'slice'], (name) ->
704 method = Array.prototype[name]
705 wrapper.prototype[name] = ->
706 result(method.apply(this._wrapped, arguments), this._chain)
707
708
709 # Start chaining a wrapped Underscore object.
710 wrapper::chain = ->
711 this._chain = true
712 this
713
714
715 # Extracts the result from a wrapped and chained object.
716 wrapper::value = -> this._wrapped
717 </textarea></form>
718 <script>
719 var editor = CodeMirror.fromTextArea(document.getElementById("code"), {});
720 </script>
721
722 <p><strong>MIME types defined:</strong> <code>text/x-coffeescript</code>.</p>
723
724 <p>The CoffeeScript mode was written by Jeff Pickhardt (<a href="LICENSE">license</a>).</p>
725
726 </body>
727 </html>
@@ -0,0 +1,32
1 CodeMirror.defineMode("diff", function() {
2
3 var TOKEN_NAMES = {
4 '+': 'tag',
5 '-': 'string',
6 '@': 'meta'
7 };
8
9 return {
10 token: function(stream) {
11 var tw_pos = stream.string.search(/[\t ]+?$/);
12
13 if (!stream.sol() || tw_pos === 0) {
14 stream.skipToEnd();
15 return ("error " + (
16 TOKEN_NAMES[stream.string.charAt(0)] || '')).replace(/ $/, '');
17 }
18
19 var token_name = TOKEN_NAMES[stream.peek()] || stream.skipToEnd();
20
21 if (tw_pos === -1) {
22 stream.skipToEnd();
23 } else {
24 stream.pos = tw_pos;
25 }
26
27 return token_name;
28 }
29 };
30 });
31
32 CodeMirror.defineMIME("text/x-diff", "diff");
@@ -0,0 +1,104
1 <!doctype html>
2 <html>
3 <head>
4 <title>CodeMirror: Diff mode</title>
5 <link rel="stylesheet" href="../../lib/codemirror.css">
6 <script src="../../lib/codemirror.js"></script>
7 <script src="diff.js"></script>
8 <style>
9 .CodeMirror {border-top: 1px solid #ddd; border-bottom: 1px solid #ddd;}
10 span.cm-meta {color: #a0b !important;}
11 span.cm-error { background-color: black; opacity: 0.4;}
12 span.cm-error.cm-string { background-color: red; }
13 span.cm-error.cm-tag { background-color: #2b2; }
14 </style>
15 <link rel="stylesheet" href="../../doc/docs.css">
16 </head>
17 <body>
18 <h1>CodeMirror: Diff mode</h1>
19 <form><textarea id="code" name="code">
20 diff --git a/index.html b/index.html
21 index c1d9156..7764744 100644
22 --- a/index.html
23 +++ b/index.html
24 @@ -95,7 +95,8 @@ StringStream.prototype = {
25 <script>
26 var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
27 lineNumbers: true,
28 - autoMatchBrackets: true
29 + autoMatchBrackets: true,
30 + onGutterClick: function(x){console.log(x);}
31 });
32 </script>
33 </body>
34 diff --git a/lib/codemirror.js b/lib/codemirror.js
35 index 04646a9..9a39cc7 100644
36 --- a/lib/codemirror.js
37 +++ b/lib/codemirror.js
38 @@ -399,10 +399,16 @@ var CodeMirror = (function() {
39 }
40
41 function onMouseDown(e) {
42 - var start = posFromMouse(e), last = start;
43 + var start = posFromMouse(e), last = start, target = e.target();
44 if (!start) return;
45 setCursor(start.line, start.ch, false);
46 if (e.button() != 1) return;
47 + if (target.parentNode == gutter) {
48 + if (options.onGutterClick)
49 + options.onGutterClick(indexOf(gutter.childNodes, target) + showingFrom);
50 + return;
51 + }
52 +
53 if (!focused) onFocus();
54
55 e.stop();
56 @@ -808,7 +814,7 @@ var CodeMirror = (function() {
57 for (var i = showingFrom; i < showingTo; ++i) {
58 var marker = lines[i].gutterMarker;
59 if (marker) html.push('<div class="' + marker.style + '">' + htmlEscape(marker.text) + '</div>');
60 - else html.push("<div>" + (options.lineNumbers ? i + 1 : "\u00a0") + "</div>");
61 + else html.push("<div>" + (options.lineNumbers ? i + options.firstLineNumber : "\u00a0") + "</div>");
62 }
63 gutter.style.display = "none"; // TODO test whether this actually helps
64 gutter.innerHTML = html.join("");
65 @@ -1371,10 +1377,8 @@ var CodeMirror = (function() {
66 if (option == "parser") setParser(value);
67 else if (option === "lineNumbers") setLineNumbers(value);
68 else if (option === "gutter") setGutter(value);
69 - else if (option === "readOnly") options.readOnly = value;
70 - else if (option === "indentUnit") {options.indentUnit = indentUnit = value; setParser(options.parser);}
71 - else if (/^(?:enterMode|tabMode|indentWithTabs|readOnly|autoMatchBrackets|undoDepth)$/.test(option)) options[option] = value;
72 - else throw new Error("Can't set option " + option);
73 + else if (option === "indentUnit") {options.indentUnit = value; setParser(options.parser);}
74 + else options[option] = value;
75 },
76 cursorCoords: cursorCoords,
77 undo: operation(undo),
78 @@ -1402,7 +1406,8 @@ var CodeMirror = (function() {
79 replaceRange: operation(replaceRange),
80
81 operation: function(f){return operation(f)();},
82 - refresh: function(){updateDisplay([{from: 0, to: lines.length}]);}
83 + refresh: function(){updateDisplay([{from: 0, to: lines.length}]);},
84 + getInputField: function(){return input;}
85 };
86 return instance;
87 }
88 @@ -1420,6 +1425,7 @@ var CodeMirror = (function() {
89 readOnly: false,
90 onChange: null,
91 onCursorActivity: null,
92 + onGutterClick: null,
93 autoMatchBrackets: false,
94 workTime: 200,
95 workDelay: 300,
96 </textarea></form>
97 <script>
98 var editor = CodeMirror.fromTextArea(document.getElementById("code"), {});
99 </script>
100
101 <p><strong>MIME types defined:</strong> <code>text/x-diff</code>.</p>
102
103 </body>
104 </html>
@@ -0,0 +1,203
1 CodeMirror.defineMode("ecl", function(config) {
2
3 function words(str) {
4 var obj = {}, words = str.split(" ");
5 for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
6 return obj;
7 }
8
9 function metaHook(stream, state) {
10 if (!state.startOfLine) return false;
11 stream.skipToEnd();
12 return "meta";
13 }
14
15 function tokenAtString(stream, state) {
16 var next;
17 while ((next = stream.next()) != null) {
18 if (next == '"' && !stream.eat('"')) {
19 state.tokenize = null;
20 break;
21 }
22 }
23 return "string";
24 }
25
26 var indentUnit = config.indentUnit;
27 var keyword = words("abs acos allnodes ascii asin asstring atan atan2 ave case choose choosen choosesets clustersize combine correlation cos cosh count covariance cron dataset dedup define denormalize distribute distributed distribution ebcdic enth error evaluate event eventextra eventname exists exp failcode failmessage fetch fromunicode getisvalid global graph group hash hash32 hash64 hashcrc hashmd5 having if index intformat isvalid iterate join keyunicode length library limit ln local log loop map matched matchlength matchposition matchtext matchunicode max merge mergejoin min nolocal nonempty normalize parse pipe power preload process project pull random range rank ranked realformat recordof regexfind regexreplace regroup rejected rollup round roundup row rowdiff sample set sin sinh sizeof soapcall sort sorted sqrt stepped stored sum table tan tanh thisnode topn tounicode transfer trim truncate typeof ungroup unicodeorder variance which workunit xmldecode xmlencode xmltext xmlunicode");
28 var variable = words("apply assert build buildindex evaluate fail keydiff keypatch loadxml nothor notify output parallel sequential soapcall wait");
29 var variable_2 = words("__compressed__ all and any as atmost before beginc++ best between case const counter csv descend encrypt end endc++ endmacro except exclusive expire export extend false few first flat from full function group header heading hole ifblock import in interface joined keep keyed last left limit load local locale lookup macro many maxcount maxlength min skew module named nocase noroot noscan nosort not of only opt or outer overwrite packed partition penalty physicallength pipe quote record relationship repeat return right scan self separator service shared skew skip sql store terminator thor threshold token transform trim true type unicodeorder unsorted validate virtual whole wild within xml xpath");
30 var variable_3 = words("ascii big_endian boolean data decimal ebcdic integer pattern qstring real record rule set of string token udecimal unicode unsigned varstring varunicode");
31 var builtin = words("checkpoint deprecated failcode failmessage failure global independent onwarning persist priority recovery stored success wait when");
32 var blockKeywords = words("catch class do else finally for if switch try while");
33 var atoms = words("true false null");
34 var hooks = {"#": metaHook};
35 var multiLineStrings;
36 var isOperatorChar = /[+\-*&%=<>!?|\/]/;
37
38 var curPunc;
39
40 function tokenBase(stream, state) {
41 var ch = stream.next();
42 if (hooks[ch]) {
43 var result = hooks[ch](stream, state);
44 if (result !== false) return result;
45 }
46 if (ch == '"' || ch == "'") {
47 state.tokenize = tokenString(ch);
48 return state.tokenize(stream, state);
49 }
50 if (/[\[\]{}\(\),;\:\.]/.test(ch)) {
51 curPunc = ch;
52 return null
53 }
54 if (/\d/.test(ch)) {
55 stream.eatWhile(/[\w\.]/);
56 return "number";
57 }
58 if (ch == "/") {
59 if (stream.eat("*")) {
60 state.tokenize = tokenComment;
61 return tokenComment(stream, state);
62 }
63 if (stream.eat("/")) {
64 stream.skipToEnd();
65 return "comment";
66 }
67 }
68 if (isOperatorChar.test(ch)) {
69 stream.eatWhile(isOperatorChar);
70 return "operator";
71 }
72 stream.eatWhile(/[\w\$_]/);
73 var cur = stream.current().toLowerCase();
74 if (keyword.propertyIsEnumerable(cur)) {
75 if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement";
76 return "keyword";
77 } else if (variable.propertyIsEnumerable(cur)) {
78 if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement";
79 return "variable";
80 } else if (variable_2.propertyIsEnumerable(cur)) {
81 if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement";
82 return "variable-2";
83 } else if (variable_3.propertyIsEnumerable(cur)) {
84 if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement";
85 return "variable-3";
86 } else if (builtin.propertyIsEnumerable(cur)) {
87 if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement";
88 return "builtin";
89 } else { //Data types are of from KEYWORD##
90 var i = cur.length - 1;
91 while(i >= 0 && (!isNaN(cur[i]) || cur[i] == '_'))
92 --i;
93
94 if (i > 0) {
95 var cur2 = cur.substr(0, i + 1);
96 if (variable_3.propertyIsEnumerable(cur2)) {
97 if (blockKeywords.propertyIsEnumerable(cur2)) curPunc = "newstatement";
98 return "variable-3";
99 }
100 }
101 }
102 if (atoms.propertyIsEnumerable(cur)) return "atom";
103 return null;
104 }
105
106 function tokenString(quote) {
107 return function(stream, state) {
108 var escaped = false, next, end = false;
109 while ((next = stream.next()) != null) {
110 if (next == quote && !escaped) {end = true; break;}
111 escaped = !escaped && next == "\\";
112 }
113 if (end || !(escaped || multiLineStrings))
114 state.tokenize = tokenBase;
115 return "string";
116 };
117 }
118
119 function tokenComment(stream, state) {
120 var maybeEnd = false, ch;
121 while (ch = stream.next()) {
122 if (ch == "/" && maybeEnd) {
123 state.tokenize = tokenBase;
124 break;
125 }
126 maybeEnd = (ch == "*");
127 }
128 return "comment";
129 }
130
131 function Context(indented, column, type, align, prev) {
132 this.indented = indented;
133 this.column = column;
134 this.type = type;
135 this.align = align;
136 this.prev = prev;
137 }
138 function pushContext(state, col, type) {
139 return state.context = new Context(state.indented, col, type, null, state.context);
140 }
141 function popContext(state) {
142 var t = state.context.type;
143 if (t == ")" || t == "]" || t == "}")
144 state.indented = state.context.indented;
145 return state.context = state.context.prev;
146 }
147
148 // Interface
149
150 return {
151 startState: function(basecolumn) {
152 return {
153 tokenize: null,
154 context: new Context((basecolumn || 0) - indentUnit, 0, "top", false),
155 indented: 0,
156 startOfLine: true
157 };
158 },
159
160 token: function(stream, state) {
161 var ctx = state.context;
162 if (stream.sol()) {
163 if (ctx.align == null) ctx.align = false;
164 state.indented = stream.indentation();
165 state.startOfLine = true;
166 }
167 if (stream.eatSpace()) return null;
168 curPunc = null;
169 var style = (state.tokenize || tokenBase)(stream, state);
170 if (style == "comment" || style == "meta") return style;
171 if (ctx.align == null) ctx.align = true;
172
173 if ((curPunc == ";" || curPunc == ":") && ctx.type == "statement") popContext(state);
174 else if (curPunc == "{") pushContext(state, stream.column(), "}");
175 else if (curPunc == "[") pushContext(state, stream.column(), "]");
176 else if (curPunc == "(") pushContext(state, stream.column(), ")");
177 else if (curPunc == "}") {
178 while (ctx.type == "statement") ctx = popContext(state);
179 if (ctx.type == "}") ctx = popContext(state);
180 while (ctx.type == "statement") ctx = popContext(state);
181 }
182 else if (curPunc == ctx.type) popContext(state);
183 else if (ctx.type == "}" || ctx.type == "top" || (ctx.type == "statement" && curPunc == "newstatement"))
184 pushContext(state, stream.column(), "statement");
185 state.startOfLine = false;
186 return style;
187 },
188
189 indent: function(state, textAfter) {
190 if (state.tokenize != tokenBase && state.tokenize != null) return 0;
191 var ctx = state.context, firstChar = textAfter && textAfter.charAt(0);
192 if (ctx.type == "statement" && firstChar == "}") ctx = ctx.prev;
193 var closing = firstChar == ctx.type;
194 if (ctx.type == "statement") return ctx.indented + (firstChar == "{" ? 0 : indentUnit);
195 else if (ctx.align) return ctx.column + (closing ? 0 : 1);
196 else return ctx.indented + (closing ? 0 : indentUnit);
197 },
198
199 electricChars: "{}"
200 };
201 });
202
203 CodeMirror.defineMIME("text/x-ecl", "ecl");
@@ -0,0 +1,42
1 <!doctype html>
2 <html>
3 <head>
4 <title>CodeMirror: ECL mode</title>
5 <link rel="stylesheet" href="../../lib/codemirror.css">
6 <script src="../../lib/codemirror.js"></script>
7 <script src="ecl.js"></script>
8 <link rel="stylesheet" href="../../doc/docs.css">
9 <style>.CodeMirror {border: 1px solid black;}</style>
10 </head>
11 <body>
12 <h1>CodeMirror: ECL mode</h1>
13 <form><textarea id="code" name="code">
14 /*
15 sample useless code to demonstrate ecl syntax highlighting
16 this is a multiline comment!
17 */
18
19 // this is a singleline comment!
20
21 import ut;
22 r :=
23 record
24 string22 s1 := '123';
25 integer4 i1 := 123;
26 end;
27 #option('tmp', true);
28 d := dataset('tmp::qb', r, thor);
29 output(d);
30 </textarea></form>
31 <script>
32 var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
33 tabMode: "indent",
34 matchBrackets: true,
35 });
36 </script>
37
38 <p>Based on CodeMirror's clike mode. For more information see <a href="http://hpccsystems.com">HPCC Systems</a> web site.</p>
39 <p><strong>MIME types defined:</strong> <code>text/x-ecl</code>.</p>
40
41 </body>
42 </html>
@@ -0,0 +1,463
1 // block; "begin", "case", "fun", "if", "receive", "try": closed by "end"
2 // block internal; "after", "catch", "of"
3 // guard; "when", closed by "->"
4 // "->" opens a clause, closed by ";" or "."
5 // "<<" opens a binary, closed by ">>"
6 // "," appears in arglists, lists, tuples and terminates lines of code
7 // "." resets indentation to 0
8 // obsolete; "cond", "let", "query"
9
10 CodeMirror.defineMIME("text/x-erlang", "erlang");
11
12 CodeMirror.defineMode("erlang", function(cmCfg, modeCfg) {
13
14 function rval(state,stream,type) {
15 // distinguish between "." as terminator and record field operator
16 if (type == "record") {
17 state.context = "record";
18 }else{
19 state.context = false;
20 }
21
22 // remember last significant bit on last line for indenting
23 if (type != "whitespace" && type != "comment") {
24 state.lastToken = stream.current();
25 }
26 // erlang -> CodeMirror tag
27 switch (type) {
28 case "atom": return "atom";
29 case "attribute": return "attribute";
30 case "builtin": return "builtin";
31 case "comment": return "comment";
32 case "fun": return "meta";
33 case "function": return "tag";
34 case "guard": return "property";
35 case "keyword": return "keyword";
36 case "macro": return "variable-2";
37 case "number": return "number";
38 case "operator": return "operator";
39 case "record": return "bracket";
40 case "string": return "string";
41 case "type": return "def";
42 case "variable": return "variable";
43 case "error": return "error";
44 case "separator": return null;
45 case "open_paren": return null;
46 case "close_paren": return null;
47 default: return null;
48 }
49 }
50
51 var typeWords = [
52 "-type", "-spec", "-export_type", "-opaque"];
53
54 var keywordWords = [
55 "after","begin","catch","case","cond","end","fun","if",
56 "let","of","query","receive","try","when"];
57
58 var separatorWords = [
59 "->",";",":",".",","];
60
61 var operatorWords = [
62 "and","andalso","band","bnot","bor","bsl","bsr","bxor",
63 "div","not","or","orelse","rem","xor"];
64
65 var symbolWords = [
66 "+","-","*","/",">",">=","<","=<","=:=","==","=/=","/=","||","<-"];
67
68 var openParenWords = [
69 "<<","(","[","{"];
70
71 var closeParenWords = [
72 "}","]",")",">>"];
73
74 var guardWords = [
75 "is_atom","is_binary","is_bitstring","is_boolean","is_float",
76 "is_function","is_integer","is_list","is_number","is_pid",
77 "is_port","is_record","is_reference","is_tuple",
78 "atom","binary","bitstring","boolean","function","integer","list",
79 "number","pid","port","record","reference","tuple"];
80
81 var bifWords = [
82 "abs","adler32","adler32_combine","alive","apply","atom_to_binary",
83 "atom_to_list","binary_to_atom","binary_to_existing_atom",
84 "binary_to_list","binary_to_term","bit_size","bitstring_to_list",
85 "byte_size","check_process_code","contact_binary","crc32",
86 "crc32_combine","date","decode_packet","delete_module",
87 "disconnect_node","element","erase","exit","float","float_to_list",
88 "garbage_collect","get","get_keys","group_leader","halt","hd",
89 "integer_to_list","internal_bif","iolist_size","iolist_to_binary",
90 "is_alive","is_atom","is_binary","is_bitstring","is_boolean",
91 "is_float","is_function","is_integer","is_list","is_number","is_pid",
92 "is_port","is_process_alive","is_record","is_reference","is_tuple",
93 "length","link","list_to_atom","list_to_binary","list_to_bitstring",
94 "list_to_existing_atom","list_to_float","list_to_integer",
95 "list_to_pid","list_to_tuple","load_module","make_ref","module_loaded",
96 "monitor_node","node","node_link","node_unlink","nodes","notalive",
97 "now","open_port","pid_to_list","port_close","port_command",
98 "port_connect","port_control","pre_loaded","process_flag",
99 "process_info","processes","purge_module","put","register",
100 "registered","round","self","setelement","size","spawn","spawn_link",
101 "spawn_monitor","spawn_opt","split_binary","statistics",
102 "term_to_binary","time","throw","tl","trunc","tuple_size",
103 "tuple_to_list","unlink","unregister","whereis"];
104
105 // ignored for indenting purposes
106 var ignoreWords = [
107 ",", ":", "catch", "after", "of", "cond", "let", "query"];
108
109
110 var smallRE = /[a-z_]/;
111 var largeRE = /[A-Z_]/;
112 var digitRE = /[0-9]/;
113 var octitRE = /[0-7]/;
114 var anumRE = /[a-z_A-Z0-9]/;
115 var symbolRE = /[\+\-\*\/<>=\|:]/;
116 var openParenRE = /[<\(\[\{]/;
117 var closeParenRE = /[>\)\]\}]/;
118 var sepRE = /[\->\.,:;]/;
119
120 function isMember(element,list) {
121 return (-1 < list.indexOf(element));
122 }
123
124 function isPrev(stream,string) {
125 var start = stream.start;
126 var len = string.length;
127 if (len <= start) {
128 var word = stream.string.slice(start-len,start);
129 return word == string;
130 }else{
131 return false;
132 }
133 }
134
135 function tokenize(stream, state) {
136 if (stream.eatSpace()) {
137 return rval(state,stream,"whitespace");
138 }
139
140 // attributes and type specs
141 if ((peekToken(state).token == "" || peekToken(state).token == ".") &&
142 stream.peek() == '-') {
143 stream.next();
144 if (stream.eat(smallRE) && stream.eatWhile(anumRE)) {
145 if (isMember(stream.current(),typeWords)) {
146 return rval(state,stream,"type");
147 }else{
148 return rval(state,stream,"attribute");
149 }
150 }
151 stream.backUp(1);
152 }
153
154 var ch = stream.next();
155
156 // comment
157 if (ch == '%') {
158 stream.skipToEnd();
159 return rval(state,stream,"comment");
160 }
161
162 // macro
163 if (ch == '?') {
164 stream.eatWhile(anumRE);
165 return rval(state,stream,"macro");
166 }
167
168 // record
169 if ( ch == "#") {
170 stream.eatWhile(anumRE);
171 return rval(state,stream,"record");
172 }
173
174 // char
175 if ( ch == "$") {
176 if (stream.next() == "\\") {
177 if (!stream.eatWhile(octitRE)) {
178 stream.next();
179 }
180 }
181 return rval(state,stream,"string");
182 }
183
184 // quoted atom
185 if (ch == '\'') {
186 if (singleQuote(stream)) {
187 return rval(state,stream,"atom");
188 }else{
189 return rval(state,stream,"error");
190 }
191 }
192
193 // string
194 if (ch == '"') {
195 if (doubleQuote(stream)) {
196 return rval(state,stream,"string");
197 }else{
198 return rval(state,stream,"error");
199 }
200 }
201
202 // variable
203 if (largeRE.test(ch)) {
204 stream.eatWhile(anumRE);
205 return rval(state,stream,"variable");
206 }
207
208 // atom/keyword/BIF/function
209 if (smallRE.test(ch)) {
210 stream.eatWhile(anumRE);
211
212 if (stream.peek() == "/") {
213 stream.next();
214 if (stream.eatWhile(digitRE)) {
215 return rval(state,stream,"fun"); // f/0 style fun
216 }else{
217 stream.backUp(1);
218 return rval(state,stream,"atom");
219 }
220 }
221
222 var w = stream.current();
223
224 if (isMember(w,keywordWords)) {
225 pushToken(state,stream);
226 return rval(state,stream,"keyword");
227 }
228 if (stream.peek() == "(") {
229 // 'put' and 'erlang:put' are bifs, 'foo:put' is not
230 if (isMember(w,bifWords) &&
231 (!isPrev(stream,":") || isPrev(stream,"erlang:"))) {
232 return rval(state,stream,"builtin");
233 }else{
234 return rval(state,stream,"function");
235 }
236 }
237 if (isMember(w,guardWords)) {
238 return rval(state,stream,"guard");
239 }
240 if (isMember(w,operatorWords)) {
241 return rval(state,stream,"operator");
242 }
243 if (stream.peek() == ":") {
244 if (w == "erlang") {
245 return rval(state,stream,"builtin");
246 } else {
247 return rval(state,stream,"function");
248 }
249 }
250 return rval(state,stream,"atom");
251 }
252
253 // number
254 if (digitRE.test(ch)) {
255 stream.eatWhile(digitRE);
256 if (stream.eat('#')) {
257 stream.eatWhile(digitRE); // 16#10 style integer
258 } else {
259 if (stream.eat('.')) { // float
260 stream.eatWhile(digitRE);
261 }
262 if (stream.eat(/[eE]/)) {
263 stream.eat(/[-+]/); // float with exponent
264 stream.eatWhile(digitRE);
265 }
266 }
267 return rval(state,stream,"number"); // normal integer
268 }
269
270 // open parens
271 if (nongreedy(stream,openParenRE,openParenWords)) {
272 pushToken(state,stream);
273 return rval(state,stream,"open_paren");
274 }
275
276 // close parens
277 if (nongreedy(stream,closeParenRE,closeParenWords)) {
278 pushToken(state,stream);
279 return rval(state,stream,"close_paren");
280 }
281
282 // separators
283 if (greedy(stream,sepRE,separatorWords)) {
284 // distinguish between "." as terminator and record field operator
285 if (state.context == false) {
286 pushToken(state,stream);
287 }
288 return rval(state,stream,"separator");
289 }
290
291 // operators
292 if (greedy(stream,symbolRE,symbolWords)) {
293 return rval(state,stream,"operator");
294 }
295
296 return rval(state,stream,null);
297 }
298
299 function nongreedy(stream,re,words) {
300 if (stream.current().length == 1 && re.test(stream.current())) {
301 stream.backUp(1);
302 while (re.test(stream.peek())) {
303 stream.next();
304 if (isMember(stream.current(),words)) {
305 return true;
306 }
307 }
308 stream.backUp(stream.current().length-1);
309 }
310 return false;
311 }
312
313 function greedy(stream,re,words) {
314 if (stream.current().length == 1 && re.test(stream.current())) {
315 while (re.test(stream.peek())) {
316 stream.next();
317 }
318 while (0 < stream.current().length) {
319 if (isMember(stream.current(),words)) {
320 return true;
321 }else{
322 stream.backUp(1);
323 }
324 }
325 stream.next();
326 }
327 return false;
328 }
329
330 function doubleQuote(stream) {
331 return quote(stream, '"', '\\');
332 }
333
334 function singleQuote(stream) {
335 return quote(stream,'\'','\\');
336 }
337
338 function quote(stream,quoteChar,escapeChar) {
339 while (!stream.eol()) {
340 var ch = stream.next();
341 if (ch == quoteChar) {
342 return true;
343 }else if (ch == escapeChar) {
344 stream.next();
345 }
346 }
347 return false;
348 }
349
350 function Token(stream) {
351 this.token = stream ? stream.current() : "";
352 this.column = stream ? stream.column() : 0;
353 this.indent = stream ? stream.indentation() : 0;
354 }
355
356 function myIndent(state,textAfter) {
357 var indent = cmCfg.indentUnit;
358 var outdentWords = ["after","catch"];
359 var token = (peekToken(state)).token;
360 var wordAfter = takewhile(textAfter,/[^a-z]/);
361
362 if (isMember(token,openParenWords)) {
363 return (peekToken(state)).column+token.length;
364 }else if (token == "." || token == ""){
365 return 0;
366 }else if (token == "->") {
367 if (wordAfter == "end") {
368 return peekToken(state,2).column;
369 }else if (peekToken(state,2).token == "fun") {
370 return peekToken(state,2).column+indent;
371 }else{
372 return (peekToken(state)).indent+indent;
373 }
374 }else if (isMember(wordAfter,outdentWords)) {
375 return (peekToken(state)).indent;
376 }else{
377 return (peekToken(state)).column+indent;
378 }
379 }
380
381 function takewhile(str,re) {
382 var m = str.match(re);
383 return m ? str.slice(0,m.index) : str;
384 }
385
386 function popToken(state) {
387 return state.tokenStack.pop();
388 }
389
390 function peekToken(state,depth) {
391 var len = state.tokenStack.length;
392 var dep = (depth ? depth : 1);
393 if (len < dep) {
394 return new Token;
395 }else{
396 return state.tokenStack[len-dep];
397 }
398 }
399
400 function pushToken(state,stream) {
401 var token = stream.current();
402 var prev_token = peekToken(state).token;
403 if (isMember(token,ignoreWords)) {
404 return false;
405 }else if (drop_both(prev_token,token)) {
406 popToken(state);
407 return false;
408 }else if (drop_first(prev_token,token)) {
409 popToken(state);
410 return pushToken(state,stream);
411 }else{
412 state.tokenStack.push(new Token(stream));
413 return true;
414 }
415 }
416
417 function drop_first(open, close) {
418 switch (open+" "+close) {
419 case "when ->": return true;
420 case "-> end": return true;
421 case "-> .": return true;
422 case ". .": return true;
423 default: return false;
424 }
425 }
426
427 function drop_both(open, close) {
428 switch (open+" "+close) {
429 case "( )": return true;
430 case "[ ]": return true;
431 case "{ }": return true;
432 case "<< >>": return true;
433 case "begin end": return true;
434 case "case end": return true;
435 case "fun end": return true;
436 case "if end": return true;
437 case "receive end": return true;
438 case "try end": return true;
439 case "-> ;": return true;
440 default: return false;
441 }
442 }
443
444 return {
445 startState:
446 function() {
447 return {tokenStack: [],
448 context: false,
449 lastToken: null};
450 },
451
452 token:
453 function(stream, state) {
454 return tokenize(stream, state);
455 },
456
457 indent:
458 function(state, textAfter) {
459 // console.log(state.tokenStack);
460 return myIndent(state,textAfter);
461 }
462 };
463 });
@@ -0,0 +1,62
1 <!doctype html>
2 <html>
3 <head>
4 <title>CodeMirror: Erlang mode</title>
5 <link rel="stylesheet" href="../../lib/codemirror.css">
6 <script src="../../lib/codemirror.js"></script>
7 <script src="erlang.js"></script>
8 <link rel="stylesheet" href="../../theme/erlang-dark.css">
9 <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
10 <link rel="stylesheet" href="../../doc/docs.css">
11 </head>
12 <body>
13 <h1>CodeMirror: Erlang mode</h1>
14
15 <form><textarea id="code" name="code">
16 %% -*- mode: erlang; erlang-indent-level: 2 -*-
17 %%% Created : 7 May 2012 by mats cronqvist <masse@klarna.com>
18
19 %% @doc
20 %% Demonstrates how to print a record.
21 %% @end
22
23 -module('ex').
24 -author('mats cronqvist').
25 -export([demo/0,
26 rec_info/1]).
27
28 -record(demo,{a="One",b="Two",c="Three",d="Four"}).
29
30 rec_info(demo) -> record_info(fields,demo).
31
32 demo() -> expand_recs(?MODULE,#demo{a="A",b="BB"}).
33
34 expand_recs(M,List) when is_list(List) ->
35 [expand_recs(M,L)||L<-List];
36 expand_recs(M,Tup) when is_tuple(Tup) ->
37 case tuple_size(Tup) of
38 L when L < 1 -> Tup;
39 L ->
40 try Fields = M:rec_info(element(1,Tup)),
41 L = length(Fields)+1,
42 lists:zip(Fields,expand_recs(M,tl(tuple_to_list(Tup))))
43 catch _:_ ->
44 list_to_tuple(expand_recs(M,tuple_to_list(Tup)))
45 end
46 end;
47 expand_recs(_,Term) ->
48 Term.
49 </textarea></form>
50
51 <script>
52 var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
53 lineNumbers: true,
54 matchBrackets: true,
55 extraKeys: {"Tab": "indentAuto"},
56 theme: "erlang-dark"
57 });
58 </script>
59
60 <p><strong>MIME types defined:</strong> <code>text/x-erlang</code>.</p>
61 </body>
62 </html>
@@ -0,0 +1,144
1 CodeMirror.defineMode("gfm", function(config, parserConfig) {
2 var mdMode = CodeMirror.getMode(config, "markdown");
3 var aliases = {
4 html: "htmlmixed",
5 js: "javascript",
6 json: "application/json",
7 c: "text/x-csrc",
8 "c++": "text/x-c++src",
9 java: "text/x-java",
10 csharp: "text/x-csharp",
11 "c#": "text/x-csharp"
12 };
13
14 // make this lazy so that we don't need to load GFM last
15 var getMode = (function () {
16 var i, modes = {}, mimes = {}, mime;
17
18 var list = CodeMirror.listModes();
19 for (i = 0; i < list.length; i++) {
20 modes[list[i]] = list[i];
21 }
22 var mimesList = CodeMirror.listMIMEs();
23 for (i = 0; i < mimesList.length; i++) {
24 mime = mimesList[i].mime;
25 mimes[mime] = mimesList[i].mime;
26 }
27
28 for (var a in aliases) {
29 if (aliases[a] in modes || aliases[a] in mimes)
30 modes[a] = aliases[a];
31 }
32
33 return function (lang) {
34 return modes[lang] ? CodeMirror.getMode(config, modes[lang]) : null;
35 }
36 }());
37
38 function markdown(stream, state) {
39 // intercept fenced code blocks
40 if (stream.sol() && stream.match(/^```([\w+#]*)/)) {
41 // try switching mode
42 state.localMode = getMode(RegExp.$1)
43 if (state.localMode)
44 state.localState = state.localMode.startState();
45
46 state.token = local;
47 return 'code';
48 }
49
50 return mdMode.token(stream, state.mdState);
51 }
52
53 function local(stream, state) {
54 if (stream.sol() && stream.match(/^```/)) {
55 state.localMode = state.localState = null;
56 state.token = markdown;
57 return 'code';
58 }
59 else if (state.localMode) {
60 return state.localMode.token(stream, state.localState);
61 } else {
62 stream.skipToEnd();
63 return 'code';
64 }
65 }
66
67 // custom handleText to prevent emphasis in the middle of a word
68 // and add autolinking
69 function handleText(stream, mdState) {
70 var match;
71 if (stream.match(/^\w+:\/\/\S+/)) {
72 return 'link';
73 }
74 if (stream.match(/^[^\[*\\<>` _][^\[*\\<>` ]*[^\[*\\<>` _]/)) {
75 return mdMode.getType(mdState);
76 }
77 if (match = stream.match(/^[^\[*\\<>` ]+/)) {
78 var word = match[0];
79 if (word[0] === '_' && word[word.length-1] === '_') {
80 stream.backUp(word.length);
81 return undefined;
82 }
83 return mdMode.getType(mdState);
84 }
85 if (stream.eatSpace()) {
86 return null;
87 }
88 }
89
90 return {
91 startState: function() {
92 var mdState = mdMode.startState();
93 mdState.text = handleText;
94 return {token: markdown, mode: "markdown", mdState: mdState,
95 localMode: null, localState: null};
96 },
97
98 copyState: function(state) {
99 return {token: state.token, mode: state.mode, mdState: CodeMirror.copyState(mdMode, state.mdState),
100 localMode: state.localMode,
101 localState: state.localMode ? CodeMirror.copyState(state.localMode, state.localState) : null};
102 },
103
104 token: function(stream, state) {
105 /* Parse GFM double bracket links */
106 if ((ch = stream.peek()) != undefined && ch == '[') {
107 stream.next(); // Advance the stream
108
109 /* Only handle double bracket links */
110 if ((ch = stream.peek()) == undefined || ch != '[') {
111 stream.backUp(1);
112 return state.token(stream, state);
113 }
114
115 while ((ch = stream.next()) != undefined && ch != ']') {}
116
117 if (ch == ']' && (ch = stream.next()) != undefined && ch == ']')
118 return 'link';
119
120 /* If we did not find the second ']' */
121 stream.backUp(1);
122 }
123
124 /* Match GFM latex formulas, as well as latex formulas within '$' */
125 if (stream.match(/^\$[^\$]+\$/)) {
126 return "string";
127 }
128
129 if (stream.match(/^\\\((.*?)\\\)/)) {
130 return "string";
131 }
132
133 if (stream.match(/^\$\$[^\$]+\$\$/)) {
134 return "string";
135 }
136
137 if (stream.match(/^\\\[(.*?)\\\]/)) {
138 return "string";
139 }
140
141 return state.token(stream, state);
142 }
143 }
144 }, "markdown");
@@ -0,0 +1,47
1 <!doctype html>
2 <html>
3 <head>
4 <title>CodeMirror: GFM mode</title>
5 <link rel="stylesheet" href="../../lib/codemirror.css">
6 <script src="../../lib/codemirror.js"></script>
7 <script src="../xml/xml.js"></script>
8 <script src="../markdown/markdown.js"></script>
9 <script src="gfm.js"></script>
10 <script src="../javascript/javascript.js"></script>
11 <link rel="stylesheet" href="../markdown/markdown.css">
12 <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
13 <link rel="stylesheet" href="../../doc/docs.css">
14 </head>
15 <body>
16 <h1>CodeMirror: GFM mode</h1>
17
18 <!-- source: http://daringfireball.net/projects/markdown/basics.text -->
19 <form><textarea id="code" name="code">
20 Github Flavored Markdown
21 ========================
22
23 Everything from markdown plus GFM features:
24
25 ## Fenced code blocks
26
27 ```javascript
28 for (var i = 0; i &lt; items.length; i++) {
29 console.log(items[i], i); // log them
30 }
31 ```
32
33 See http://github.github.com/github-flavored-markdown/
34
35 </textarea></form>
36
37 <script>
38 var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
39 mode: 'gfm',
40 lineNumbers: true,
41 matchBrackets: true,
42 theme: "default"
43 });
44 </script>
45
46 </body>
47 </html>
@@ -0,0 +1,170
1 CodeMirror.defineMode("go", function(config, parserConfig) {
2 var indentUnit = config.indentUnit;
3
4 var keywords = {
5 "break":true, "case":true, "chan":true, "const":true, "continue":true,
6 "default":true, "defer":true, "else":true, "fallthrough":true, "for":true,
7 "func":true, "go":true, "goto":true, "if":true, "import":true,
8 "interface":true, "map":true, "package":true, "range":true, "return":true,
9 "select":true, "struct":true, "switch":true, "type":true, "var":true,
10 "bool":true, "byte":true, "complex64":true, "complex128":true,
11 "float32":true, "float64":true, "int8":true, "int16":true, "int32":true,
12 "int64":true, "string":true, "uint8":true, "uint16":true, "uint32":true,
13 "uint64":true, "int":true, "uint":true, "uintptr":true
14 };
15
16 var atoms = {
17 "true":true, "false":true, "iota":true, "nil":true, "append":true,
18 "cap":true, "close":true, "complex":true, "copy":true, "imag":true,
19 "len":true, "make":true, "new":true, "panic":true, "print":true,
20 "println":true, "real":true, "recover":true
21 };
22
23 var blockKeywords = {
24 "else":true, "for":true, "func":true, "if":true, "interface":true,
25 "select":true, "struct":true, "switch":true
26 };
27
28 var isOperatorChar = /[+\-*&^%:=<>!|\/]/;
29
30 var curPunc;
31
32 function tokenBase(stream, state) {
33 var ch = stream.next();
34 if (ch == '"' || ch == "'" || ch == "`") {
35 state.tokenize = tokenString(ch);
36 return state.tokenize(stream, state);
37 }
38 if (/[\d\.]/.test(ch)) {
39 if (ch == ".") {
40 stream.match(/^[0-9]+([eE][\-+]?[0-9]+)?/);
41 } else if (ch == "0") {
42 stream.match(/^[xX][0-9a-fA-F]+/) || stream.match(/^0[0-7]+/);
43 } else {
44 stream.match(/^[0-9]*\.?[0-9]*([eE][\-+]?[0-9]+)?/);
45 }
46 return "number";
47 }
48 if (/[\[\]{}\(\),;\:\.]/.test(ch)) {
49 curPunc = ch;
50 return null
51 }
52 if (ch == "/") {
53 if (stream.eat("*")) {
54 state.tokenize = tokenComment;
55 return tokenComment(stream, state);
56 }
57 if (stream.eat("/")) {
58 stream.skipToEnd();
59 return "comment";
60 }
61 }
62 if (isOperatorChar.test(ch)) {
63 stream.eatWhile(isOperatorChar);
64 return "operator";
65 }
66 stream.eatWhile(/[\w\$_]/);
67 var cur = stream.current();
68 if (keywords.propertyIsEnumerable(cur)) {
69 if (cur == "case" || cur == "default") curPunc = "case";
70 return "keyword";
71 }
72 if (atoms.propertyIsEnumerable(cur)) return "atom";
73 return "variable";
74 }
75
76 function tokenString(quote) {
77 return function(stream, state) {
78 var escaped = false, next, end = false;
79 while ((next = stream.next()) != null) {
80 if (next == quote && !escaped) {end = true; break;}
81 escaped = !escaped && next == "\\";
82 }
83 if (end || !(escaped || quote == "`"))
84 state.tokenize = tokenBase;
85 return "string";
86 };
87 }
88
89 function tokenComment(stream, state) {
90 var maybeEnd = false, ch;
91 while (ch = stream.next()) {
92 if (ch == "/" && maybeEnd) {
93 state.tokenize = tokenBase;
94 break;
95 }
96 maybeEnd = (ch == "*");
97 }
98 return "comment";
99 }
100
101 function Context(indented, column, type, align, prev) {
102 this.indented = indented;
103 this.column = column;
104 this.type = type;
105 this.align = align;
106 this.prev = prev;
107 }
108 function pushContext(state, col, type) {
109 return state.context = new Context(state.indented, col, type, null, state.context);
110 }
111 function popContext(state) {
112 var t = state.context.type;
113 if (t == ")" || t == "]" || t == "}")
114 state.indented = state.context.indented;
115 return state.context = state.context.prev;
116 }
117
118 // Interface
119
120 return {
121 startState: function(basecolumn) {
122 return {
123 tokenize: null,
124 context: new Context((basecolumn || 0) - indentUnit, 0, "top", false),
125 indented: 0,
126 startOfLine: true
127 };
128 },
129
130 token: function(stream, state) {
131 var ctx = state.context;
132 if (stream.sol()) {
133 if (ctx.align == null) ctx.align = false;
134 state.indented = stream.indentation();
135 state.startOfLine = true;
136 if (ctx.type == "case") ctx.type = "}";
137 }
138 if (stream.eatSpace()) return null;
139 curPunc = null;
140 var style = (state.tokenize || tokenBase)(stream, state);
141 if (style == "comment") return style;
142 if (ctx.align == null) ctx.align = true;
143
144 if (curPunc == "{") pushContext(state, stream.column(), "}");
145 else if (curPunc == "[") pushContext(state, stream.column(), "]");
146 else if (curPunc == "(") pushContext(state, stream.column(), ")");
147 else if (curPunc == "case") ctx.type = "case"
148 else if (curPunc == "}" && ctx.type == "}") ctx = popContext(state);
149 else if (curPunc == ctx.type) popContext(state);
150 state.startOfLine = false;
151 return style;
152 },
153
154 indent: function(state, textAfter) {
155 if (state.tokenize != tokenBase && state.tokenize != null) return 0;
156 var ctx = state.context, firstChar = textAfter && textAfter.charAt(0);
157 if (ctx.type == "case" && /^(?:case|default)\b/.test(textAfter)) {
158 state.context.type = "}";
159 return ctx.indented;
160 }
161 var closing = firstChar == ctx.type;
162 if (ctx.align) return ctx.column + (closing ? 0 : 1);
163 else return ctx.indented + (closing ? 0 : indentUnit);
164 },
165
166 electricChars: "{}:"
167 };
168 });
169
170 CodeMirror.defineMIME("text/x-go", "go");
@@ -0,0 +1,72
1 <!doctype html>
2 <html>
3 <head>
4 <title>CodeMirror: Go mode</title>
5 <link rel="stylesheet" href="../../lib/codemirror.css">
6 <link rel="stylesheet" href="../../theme/elegant.css">
7 <script src="../../lib/codemirror.js"></script>
8 <script src="go.js"></script>
9 <link rel="stylesheet" href="../../doc/docs.css">
10 <style>.CodeMirror {border:1px solid #999; background:#ffc}</style>
11 </head>
12 <body>
13 <h1>CodeMirror: Go mode</h1>
14
15 <form><textarea id="code" name="code">
16 // Prime Sieve in Go.
17 // Taken from the Go specification.
18 // Copyright © The Go Authors.
19
20 package main
21
22 import "fmt"
23
24 // Send the sequence 2, 3, 4, ... to channel 'ch'.
25 func generate(ch chan&lt;- int) {
26 for i := 2; ; i++ {
27 ch &lt;- i // Send 'i' to channel 'ch'
28 }
29 }
30
31 // Copy the values from channel 'src' to channel 'dst',
32 // removing those divisible by 'prime'.
33 func filter(src &lt;-chan int, dst chan&lt;- int, prime int) {
34 for i := range src { // Loop over values received from 'src'.
35 if i%prime != 0 {
36 dst &lt;- i // Send 'i' to channel 'dst'.
37 }
38 }
39 }
40
41 // The prime sieve: Daisy-chain filter processes together.
42 func sieve() {
43 ch := make(chan int) // Create a new channel.
44 go generate(ch) // Start generate() as a subprocess.
45 for {
46 prime := &lt;-ch
47 fmt.Print(prime, "\n")
48 ch1 := make(chan int)
49 go filter(ch, ch1, prime)
50 ch = ch1
51 }
52 }
53
54 func main() {
55 sieve()
56 }
57 </textarea></form>
58
59 <script>
60 var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
61 theme: "elegant",
62 matchBrackets: true,
63 indentUnit: 8,
64 tabSize: 8,
65 indentWithTabs: true,
66 mode: "text/x-go"
67 });
68 </script>
69
70 <p><strong>MIME type:</strong> <code>text/x-go</code></p>
71 </body>
72 </html>
@@ -0,0 +1,210
1 CodeMirror.defineMode("groovy", function(config, parserConfig) {
2 function words(str) {
3 var obj = {}, words = str.split(" ");
4 for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
5 return obj;
6 }
7 var keywords = words(
8 "abstract as assert boolean break byte case catch char class const continue def default " +
9 "do double else enum extends final finally float for goto if implements import in " +
10 "instanceof int interface long native new package private protected public return " +
11 "short static strictfp super switch synchronized threadsafe throw throws transient " +
12 "try void volatile while");
13 var blockKeywords = words("catch class do else finally for if switch try while enum interface def");
14 var atoms = words("null true false this");
15
16 var curPunc;
17 function tokenBase(stream, state) {
18 var ch = stream.next();
19 if (ch == '"' || ch == "'") {
20 return startString(ch, stream, state);
21 }
22 if (/[\[\]{}\(\),;\:\.]/.test(ch)) {
23 curPunc = ch;
24 return null
25 }
26 if (/\d/.test(ch)) {
27 stream.eatWhile(/[\w\.]/);
28 if (stream.eat(/eE/)) { stream.eat(/\+\-/); stream.eatWhile(/\d/); }
29 return "number";
30 }
31 if (ch == "/") {
32 if (stream.eat("*")) {
33 state.tokenize.push(tokenComment);
34 return tokenComment(stream, state);
35 }
36 if (stream.eat("/")) {
37 stream.skipToEnd();
38 return "comment";
39 }
40 if (expectExpression(state.lastToken)) {
41 return startString(ch, stream, state);
42 }
43 }
44 if (ch == "-" && stream.eat(">")) {
45 curPunc = "->";
46 return null;
47 }
48 if (/[+\-*&%=<>!?|\/~]/.test(ch)) {
49 stream.eatWhile(/[+\-*&%=<>|~]/);
50 return "operator";
51 }
52 stream.eatWhile(/[\w\$_]/);
53 if (ch == "@") { stream.eatWhile(/[\w\$_\.]/); return "meta"; }
54 if (state.lastToken == ".") return "property";
55 if (stream.eat(":")) { curPunc = "proplabel"; return "property"; }
56 var cur = stream.current();
57 if (atoms.propertyIsEnumerable(cur)) { return "atom"; }
58 if (keywords.propertyIsEnumerable(cur)) {
59 if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement";
60 return "keyword";
61 }
62 return "variable";
63 }
64 tokenBase.isBase = true;
65
66 function startString(quote, stream, state) {
67 var tripleQuoted = false;
68 if (quote != "/" && stream.eat(quote)) {
69 if (stream.eat(quote)) tripleQuoted = true;
70 else return "string";
71 }
72 function t(stream, state) {
73 var escaped = false, next, end = !tripleQuoted;
74 while ((next = stream.next()) != null) {
75 if (next == quote && !escaped) {
76 if (!tripleQuoted) { break; }
77 if (stream.match(quote + quote)) { end = true; break; }
78 }
79 if (quote == '"' && next == "$" && !escaped && stream.eat("{")) {
80 state.tokenize.push(tokenBaseUntilBrace());
81 return "string";
82 }
83 escaped = !escaped && next == "\\";
84 }
85 if (end) state.tokenize.pop();
86 return "string";
87 }
88 state.tokenize.push(t);
89 return t(stream, state);
90 }
91
92 function tokenBaseUntilBrace() {
93 var depth = 1;
94 function t(stream, state) {
95 if (stream.peek() == "}") {
96 depth--;
97 if (depth == 0) {
98 state.tokenize.pop();
99 return state.tokenize[state.tokenize.length-1](stream, state);
100 }
101 } else if (stream.peek() == "{") {
102 depth++;
103 }
104 return tokenBase(stream, state);
105 }
106 t.isBase = true;
107 return t;
108 }
109
110 function tokenComment(stream, state) {
111 var maybeEnd = false, ch;
112 while (ch = stream.next()) {
113 if (ch == "/" && maybeEnd) {
114 state.tokenize.pop();
115 break;
116 }
117 maybeEnd = (ch == "*");
118 }
119 return "comment";
120 }
121
122 function expectExpression(last) {
123 return !last || last == "operator" || last == "->" || /[\.\[\{\(,;:]/.test(last) ||
124 last == "newstatement" || last == "keyword" || last == "proplabel";
125 }
126
127 function Context(indented, column, type, align, prev) {
128 this.indented = indented;
129 this.column = column;
130 this.type = type;
131 this.align = align;
132 this.prev = prev;
133 }
134 function pushContext(state, col, type) {
135 return state.context = new Context(state.indented, col, type, null, state.context);
136 }
137 function popContext(state) {
138 var t = state.context.type;
139 if (t == ")" || t == "]" || t == "}")
140 state.indented = state.context.indented;
141 return state.context = state.context.prev;
142 }
143
144 // Interface
145
146 return {
147 startState: function(basecolumn) {
148 return {
149 tokenize: [tokenBase],
150 context: new Context((basecolumn || 0) - config.indentUnit, 0, "top", false),
151 indented: 0,
152 startOfLine: true,
153 lastToken: null
154 };
155 },
156
157 token: function(stream, state) {
158 var ctx = state.context;
159 if (stream.sol()) {
160 if (ctx.align == null) ctx.align = false;
161 state.indented = stream.indentation();
162 state.startOfLine = true;
163 // Automatic semicolon insertion
164 if (ctx.type == "statement" && !expectExpression(state.lastToken)) {
165 popContext(state); ctx = state.context;
166 }
167 }
168 if (stream.eatSpace()) return null;
169 curPunc = null;
170 var style = state.tokenize[state.tokenize.length-1](stream, state);
171 if (style == "comment") return style;
172 if (ctx.align == null) ctx.align = true;
173
174 if ((curPunc == ";" || curPunc == ":") && ctx.type == "statement") popContext(state);
175 // Handle indentation for {x -> \n ... }
176 else if (curPunc == "->" && ctx.type == "statement" && ctx.prev.type == "}") {
177 popContext(state);
178 state.context.align = false;
179 }
180 else if (curPunc == "{") pushContext(state, stream.column(), "}");
181 else if (curPunc == "[") pushContext(state, stream.column(), "]");
182 else if (curPunc == "(") pushContext(state, stream.column(), ")");
183 else if (curPunc == "}") {
184 while (ctx.type == "statement") ctx = popContext(state);
185 if (ctx.type == "}") ctx = popContext(state);
186 while (ctx.type == "statement") ctx = popContext(state);
187 }
188 else if (curPunc == ctx.type) popContext(state);
189 else if (ctx.type == "}" || ctx.type == "top" || (ctx.type == "statement" && curPunc == "newstatement"))
190 pushContext(state, stream.column(), "statement");
191 state.startOfLine = false;
192 state.lastToken = curPunc || style;
193 return style;
194 },
195
196 indent: function(state, textAfter) {
197 if (!state.tokenize[state.tokenize.length-1].isBase) return 0;
198 var firstChar = textAfter && textAfter.charAt(0), ctx = state.context;
199 if (ctx.type == "statement" && !expectExpression(state.lastToken)) ctx = ctx.prev;
200 var closing = firstChar == ctx.type;
201 if (ctx.type == "statement") return ctx.indented + (firstChar == "{" ? 0 : config.indentUnit);
202 else if (ctx.align) return ctx.column + (closing ? 0 : 1);
203 else return ctx.indented + (closing ? 0 : config.indentUnit);
204 },
205
206 electricChars: "{}"
207 };
208 });
209
210 CodeMirror.defineMIME("text/x-groovy", "groovy");
@@ -0,0 +1,71
1 <!doctype html>
2 <html>
3 <head>
4 <title>CodeMirror: Groovy mode</title>
5 <link rel="stylesheet" href="../../lib/codemirror.css">
6 <script src="../../lib/codemirror.js"></script>
7 <script src="groovy.js"></script>
8 <link rel="stylesheet" href="../../doc/docs.css">
9 <style>.CodeMirror {border-top: 1px solid #500; border-bottom: 1px solid #500;}</style>
10 </head>
11 <body>
12 <h1>CodeMirror: Groovy mode</h1>
13
14 <form><textarea id="code" name="code">
15 //Pattern for groovy script
16 def p = ~/.*\.groovy/
17 new File( 'd:\\scripts' ).eachFileMatch(p) {f ->
18 // imports list
19 def imports = []
20 f.eachLine {
21 // condition to detect an import instruction
22 ln -> if ( ln =~ '^import .*' ) {
23 imports << "${ln - 'import '}"
24 }
25 }
26 // print thmen
27 if ( ! imports.empty ) {
28 println f
29 imports.each{ println " $it" }
30 }
31 }
32
33 /* Coin changer demo code from http://groovy.codehaus.org */
34
35 enum UsCoin {
36 quarter(25), dime(10), nickel(5), penny(1)
37 UsCoin(v) { value = v }
38 final value
39 }
40
41 enum OzzieCoin {
42 fifty(50), twenty(20), ten(10), five(5)
43 OzzieCoin(v) { value = v }
44 final value
45 }
46
47 def plural(word, count) {
48 if (count == 1) return word
49 word[-1] == 'y' ? word[0..-2] + "ies" : word + "s"
50 }
51
52 def change(currency, amount) {
53 currency.values().inject([]){ list, coin ->
54 int count = amount / coin.value
55 amount = amount % coin.value
56 list += "$count ${plural(coin.toString(), count)}"
57 }
58 }
59 </textarea></form>
60
61 <script>
62 var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
63 lineNumbers: true,
64 matchBrackets: true,
65 mode: "text/x-groovy"
66 });
67 </script>
68
69 <p><strong>MIME types defined:</strong> <code>text/x-groovy</code></p>
70 </body>
71 </html>
@@ -0,0 +1,242
1 CodeMirror.defineMode("haskell", function(cmCfg, modeCfg) {
2
3 function switchState(source, setState, f) {
4 setState(f);
5 return f(source, setState);
6 }
7
8 // These should all be Unicode extended, as per the Haskell 2010 report
9 var smallRE = /[a-z_]/;
10 var largeRE = /[A-Z]/;
11 var digitRE = /[0-9]/;
12 var hexitRE = /[0-9A-Fa-f]/;
13 var octitRE = /[0-7]/;
14 var idRE = /[a-z_A-Z0-9']/;
15 var symbolRE = /[-!#$%&*+.\/<=>?@\\^|~:]/;
16 var specialRE = /[(),;[\]`{}]/;
17 var whiteCharRE = /[ \t\v\f]/; // newlines are handled in tokenizer
18
19 function normal(source, setState) {
20 if (source.eatWhile(whiteCharRE)) {
21 return null;
22 }
23
24 var ch = source.next();
25 if (specialRE.test(ch)) {
26 if (ch == '{' && source.eat('-')) {
27 var t = "comment";
28 if (source.eat('#')) {
29 t = "meta";
30 }
31 return switchState(source, setState, ncomment(t, 1));
32 }
33 return null;
34 }
35
36 if (ch == '\'') {
37 if (source.eat('\\')) {
38 source.next(); // should handle other escapes here
39 }
40 else {
41 source.next();
42 }
43 if (source.eat('\'')) {
44 return "string";
45 }
46 return "error";
47 }
48
49 if (ch == '"') {
50 return switchState(source, setState, stringLiteral);
51 }
52
53 if (largeRE.test(ch)) {
54 source.eatWhile(idRE);
55 if (source.eat('.')) {
56 return "qualifier";
57 }
58 return "variable-2";
59 }
60
61 if (smallRE.test(ch)) {
62 source.eatWhile(idRE);
63 return "variable";
64 }
65
66 if (digitRE.test(ch)) {
67 if (ch == '0') {
68 if (source.eat(/[xX]/)) {
69 source.eatWhile(hexitRE); // should require at least 1
70 return "integer";
71 }
72 if (source.eat(/[oO]/)) {
73 source.eatWhile(octitRE); // should require at least 1
74 return "number";
75 }
76 }
77 source.eatWhile(digitRE);
78 var t = "number";
79 if (source.eat('.')) {
80 t = "number";
81 source.eatWhile(digitRE); // should require at least 1
82 }
83 if (source.eat(/[eE]/)) {
84 t = "number";
85 source.eat(/[-+]/);
86 source.eatWhile(digitRE); // should require at least 1
87 }
88 return t;
89 }
90
91 if (symbolRE.test(ch)) {
92 if (ch == '-' && source.eat(/-/)) {
93 source.eatWhile(/-/);
94 if (!source.eat(symbolRE)) {
95 source.skipToEnd();
96 return "comment";
97 }
98 }
99 var t = "variable";
100 if (ch == ':') {
101 t = "variable-2";
102 }
103 source.eatWhile(symbolRE);
104 return t;
105 }
106
107 return "error";
108 }
109
110 function ncomment(type, nest) {
111 if (nest == 0) {
112 return normal;
113 }
114 return function(source, setState) {
115 var currNest = nest;
116 while (!source.eol()) {
117 var ch = source.next();
118 if (ch == '{' && source.eat('-')) {
119 ++currNest;
120 }
121 else if (ch == '-' && source.eat('}')) {
122 --currNest;
123 if (currNest == 0) {
124 setState(normal);
125 return type;
126 }
127 }
128 }
129 setState(ncomment(type, currNest));
130 return type;
131 }
132 }
133
134 function stringLiteral(source, setState) {
135 while (!source.eol()) {
136 var ch = source.next();
137 if (ch == '"') {
138 setState(normal);
139 return "string";
140 }
141 if (ch == '\\') {
142 if (source.eol() || source.eat(whiteCharRE)) {
143 setState(stringGap);
144 return "string";
145 }
146 if (source.eat('&')) {
147 }
148 else {
149 source.next(); // should handle other escapes here
150 }
151 }
152 }
153 setState(normal);
154 return "error";
155 }
156
157 function stringGap(source, setState) {
158 if (source.eat('\\')) {
159 return switchState(source, setState, stringLiteral);
160 }
161 source.next();
162 setState(normal);
163 return "error";
164 }
165
166
167 var wellKnownWords = (function() {
168 var wkw = {};
169 function setType(t) {
170 return function () {
171 for (var i = 0; i < arguments.length; i++)
172 wkw[arguments[i]] = t;
173 }
174 }
175
176 setType("keyword")(
177 "case", "class", "data", "default", "deriving", "do", "else", "foreign",
178 "if", "import", "in", "infix", "infixl", "infixr", "instance", "let",
179 "module", "newtype", "of", "then", "type", "where", "_");
180
181 setType("keyword")(
182 "\.\.", ":", "::", "=", "\\", "\"", "<-", "->", "@", "~", "=>");
183
184 setType("builtin")(
185 "!!", "$!", "$", "&&", "+", "++", "-", ".", "/", "/=", "<", "<=", "=<<",
186 "==", ">", ">=", ">>", ">>=", "^", "^^", "||", "*", "**");
187
188 setType("builtin")(
189 "Bool", "Bounded", "Char", "Double", "EQ", "Either", "Enum", "Eq",
190 "False", "FilePath", "Float", "Floating", "Fractional", "Functor", "GT",
191 "IO", "IOError", "Int", "Integer", "Integral", "Just", "LT", "Left",
192 "Maybe", "Monad", "Nothing", "Num", "Ord", "Ordering", "Rational", "Read",
193 "ReadS", "Real", "RealFloat", "RealFrac", "Right", "Show", "ShowS",
194 "String", "True");
195
196 setType("builtin")(
197 "abs", "acos", "acosh", "all", "and", "any", "appendFile", "asTypeOf",
198 "asin", "asinh", "atan", "atan2", "atanh", "break", "catch", "ceiling",
199 "compare", "concat", "concatMap", "const", "cos", "cosh", "curry",
200 "cycle", "decodeFloat", "div", "divMod", "drop", "dropWhile", "either",
201 "elem", "encodeFloat", "enumFrom", "enumFromThen", "enumFromThenTo",
202 "enumFromTo", "error", "even", "exp", "exponent", "fail", "filter",
203 "flip", "floatDigits", "floatRadix", "floatRange", "floor", "fmap",
204 "foldl", "foldl1", "foldr", "foldr1", "fromEnum", "fromInteger",
205 "fromIntegral", "fromRational", "fst", "gcd", "getChar", "getContents",
206 "getLine", "head", "id", "init", "interact", "ioError", "isDenormalized",
207 "isIEEE", "isInfinite", "isNaN", "isNegativeZero", "iterate", "last",
208 "lcm", "length", "lex", "lines", "log", "logBase", "lookup", "map",
209 "mapM", "mapM_", "max", "maxBound", "maximum", "maybe", "min", "minBound",
210 "minimum", "mod", "negate", "not", "notElem", "null", "odd", "or",
211 "otherwise", "pi", "pred", "print", "product", "properFraction",
212 "putChar", "putStr", "putStrLn", "quot", "quotRem", "read", "readFile",
213 "readIO", "readList", "readLn", "readParen", "reads", "readsPrec",
214 "realToFrac", "recip", "rem", "repeat", "replicate", "return", "reverse",
215 "round", "scaleFloat", "scanl", "scanl1", "scanr", "scanr1", "seq",
216 "sequence", "sequence_", "show", "showChar", "showList", "showParen",
217 "showString", "shows", "showsPrec", "significand", "signum", "sin",
218 "sinh", "snd", "span", "splitAt", "sqrt", "subtract", "succ", "sum",
219 "tail", "take", "takeWhile", "tan", "tanh", "toEnum", "toInteger",
220 "toRational", "truncate", "uncurry", "undefined", "unlines", "until",
221 "unwords", "unzip", "unzip3", "userError", "words", "writeFile", "zip",
222 "zip3", "zipWith", "zipWith3");
223
224 return wkw;
225 })();
226
227
228
229 return {
230 startState: function () { return { f: normal }; },
231 copyState: function (s) { return { f: s.f }; },
232
233 token: function(stream, state) {
234 var t = state.f(stream, function(s) { state.f = s; });
235 var w = stream.current();
236 return (w in wellKnownWords) ? wellKnownWords[w] : t;
237 }
238 };
239
240 });
241
242 CodeMirror.defineMIME("text/x-haskell", "haskell");
@@ -0,0 +1,60
1 <!doctype html>
2 <html>
3 <head>
4 <title>CodeMirror: Haskell mode</title>
5 <link rel="stylesheet" href="../../lib/codemirror.css">
6 <script src="../../lib/codemirror.js"></script>
7 <script src="haskell.js"></script>
8 <link rel="stylesheet" href="../../theme/elegant.css">
9 <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
10 <link rel="stylesheet" href="../../doc/docs.css">
11 </head>
12 <body>
13 <h1>CodeMirror: Haskell mode</h1>
14
15 <form><textarea id="code" name="code">
16 module UniquePerms (
17 uniquePerms
18 )
19 where
20
21 -- | Find all unique permutations of a list where there might be duplicates.
22 uniquePerms :: (Eq a) => [a] -> [[a]]
23 uniquePerms = permBag . makeBag
24
25 -- | An unordered collection where duplicate values are allowed,
26 -- but represented with a single value and a count.
27 type Bag a = [(a, Int)]
28
29 makeBag :: (Eq a) => [a] -> Bag a
30 makeBag [] = []
31 makeBag (a:as) = mix a $ makeBag as
32 where
33 mix a [] = [(a,1)]
34 mix a (bn@(b,n):bs) | a == b = (b,n+1):bs
35 | otherwise = bn : mix a bs
36
37 permBag :: Bag a -> [[a]]
38 permBag [] = [[]]
39 permBag bs = concatMap (\(f,cs) -> map (f:) $ permBag cs) . oneOfEach $ bs
40 where
41 oneOfEach [] = []
42 oneOfEach (an@(a,n):bs) =
43 let bs' = if n == 1 then bs else (a,n-1):bs
44 in (a,bs') : mapSnd (an:) (oneOfEach bs)
45
46 apSnd f (a,b) = (a, f b)
47 mapSnd = map . apSnd
48 </textarea></form>
49
50 <script>
51 var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
52 lineNumbers: true,
53 matchBrackets: true,
54 theme: "elegant"
55 });
56 </script>
57
58 <p><strong>MIME types defined:</strong> <code>text/x-haskell</code>.</p>
59 </body>
60 </html>
@@ -0,0 +1,432
1 CodeMirror.defineMode("haxe", function(config, parserConfig) {
2 var indentUnit = config.indentUnit;
3
4 // Tokenizer
5
6 var keywords = function(){
7 function kw(type) {return {type: type, style: "keyword"};}
8 var A = kw("keyword a"), B = kw("keyword b"), C = kw("keyword c");
9 var operator = kw("operator"), atom = {type: "atom", style: "atom"}, attribute = {type:"attribute", style: "attribute"}
10 var type = kw("typedef");
11 return {
12 "if": A, "while": A, "else": B, "do": B, "try": B,
13 "return": C, "break": C, "continue": C, "new": C, "throw": C,
14 "var": kw("var"), "inline":attribute, "static": attribute, "using":kw("import"),
15 "public": attribute, "private": attribute, "cast": kw("cast"), "import": kw("import"), "macro": kw("macro"),
16 "function": kw("function"), "catch": kw("catch"), "untyped": kw("untyped"), "callback": kw("cb"),
17 "for": kw("for"), "switch": kw("switch"), "case": kw("case"), "default": kw("default"),
18 "in": operator, "never": kw("property_access"), "trace":kw("trace"),
19 "class": type, "enum":type, "interface":type, "typedef":type, "extends":type, "implements":type, "dynamic":type,
20 "true": atom, "false": atom, "null": atom
21 };
22 }();
23
24 var isOperatorChar = /[+\-*&%=<>!?|]/;
25
26 function chain(stream, state, f) {
27 state.tokenize = f;
28 return f(stream, state);
29 }
30
31 function nextUntilUnescaped(stream, end) {
32 var escaped = false, next;
33 while ((next = stream.next()) != null) {
34 if (next == end && !escaped)
35 return false;
36 escaped = !escaped && next == "\\";
37 }
38 return escaped;
39 }
40
41 // Used as scratch variables to communicate multiple values without
42 // consing up tons of objects.
43 var type, content;
44 function ret(tp, style, cont) {
45 type = tp; content = cont;
46 return style;
47 }
48
49 function haxeTokenBase(stream, state) {
50 var ch = stream.next();
51 if (ch == '"' || ch == "'")
52 return chain(stream, state, haxeTokenString(ch));
53 else if (/[\[\]{}\(\),;\:\.]/.test(ch))
54 return ret(ch);
55 else if (ch == "0" && stream.eat(/x/i)) {
56 stream.eatWhile(/[\da-f]/i);
57 return ret("number", "number");
58 }
59 else if (/\d/.test(ch) || ch == "-" && stream.eat(/\d/)) {
60 stream.match(/^\d*(?:\.\d*)?(?:[eE][+\-]?\d+)?/);
61 return ret("number", "number");
62 }
63 else if (state.reAllowed && (ch == "~" && stream.eat(/\//))) {
64 nextUntilUnescaped(stream, "/");
65 stream.eatWhile(/[gimsu]/);
66 return ret("regexp", "string-2");
67 }
68 else if (ch == "/") {
69 if (stream.eat("*")) {
70 return chain(stream, state, haxeTokenComment);
71 }
72 else if (stream.eat("/")) {
73 stream.skipToEnd();
74 return ret("comment", "comment");
75 }
76 else {
77 stream.eatWhile(isOperatorChar);
78 return ret("operator", null, stream.current());
79 }
80 }
81 else if (ch == "#") {
82 stream.skipToEnd();
83 return ret("conditional", "meta");
84 }
85 else if (ch == "@") {
86 stream.eat(/:/);
87 stream.eatWhile(/[\w_]/);
88 return ret ("metadata", "meta");
89 }
90 else if (isOperatorChar.test(ch)) {
91 stream.eatWhile(isOperatorChar);
92 return ret("operator", null, stream.current());
93 }
94 else {
95 var word;
96 if(/[A-Z]/.test(ch))
97 {
98 stream.eatWhile(/[\w_<>]/);
99 word = stream.current();
100 return ret("type", "variable-3", word);
101 }
102 else
103 {
104 stream.eatWhile(/[\w_]/);
105 var word = stream.current(), known = keywords.propertyIsEnumerable(word) && keywords[word];
106 return (known && state.kwAllowed) ? ret(known.type, known.style, word) :
107 ret("variable", "variable", word);
108 }
109 }
110 }
111
112 function haxeTokenString(quote) {
113 return function(stream, state) {
114 if (!nextUntilUnescaped(stream, quote))
115 state.tokenize = haxeTokenBase;
116 return ret("string", "string");
117 };
118 }
119
120 function haxeTokenComment(stream, state) {
121 var maybeEnd = false, ch;
122 while (ch = stream.next()) {
123 if (ch == "/" && maybeEnd) {
124 state.tokenize = haxeTokenBase;
125 break;
126 }
127 maybeEnd = (ch == "*");
128 }
129 return ret("comment", "comment");
130 }
131
132 // Parser
133
134 var atomicTypes = {"atom": true, "number": true, "variable": true, "string": true, "regexp": true};
135
136 function HaxeLexical(indented, column, type, align, prev, info) {
137 this.indented = indented;
138 this.column = column;
139 this.type = type;
140 this.prev = prev;
141 this.info = info;
142 if (align != null) this.align = align;
143 }
144
145 function inScope(state, varname) {
146 for (var v = state.localVars; v; v = v.next)
147 if (v.name == varname) return true;
148 }
149
150 function parseHaxe(state, style, type, content, stream) {
151 var cc = state.cc;
152 // Communicate our context to the combinators.
153 // (Less wasteful than consing up a hundred closures on every call.)
154 cx.state = state; cx.stream = stream; cx.marked = null, cx.cc = cc;
155
156 if (!state.lexical.hasOwnProperty("align"))
157 state.lexical.align = true;
158
159 while(true) {
160 var combinator = cc.length ? cc.pop() : statement;
161 if (combinator(type, content)) {
162 while(cc.length && cc[cc.length - 1].lex)
163 cc.pop()();
164 if (cx.marked) return cx.marked;
165 if (type == "variable" && inScope(state, content)) return "variable-2";
166 if (type == "variable" && imported(state, content)) return "variable-3";
167 return style;
168 }
169 }
170 }
171
172 function imported(state, typename)
173 {
174 if (/[a-z]/.test(typename.charAt(0)))
175 return false;
176 var len = state.importedtypes.length;
177 for (var i = 0; i<len; i++)
178 if(state.importedtypes[i]==typename) return true;
179 }
180
181
182 function registerimport(importname) {
183 var state = cx.state;
184 for (var t = state.importedtypes; t; t = t.next)
185 if(t.name == importname) return;
186 state.importedtypes = { name: importname, next: state.importedtypes };
187 }
188 // Combinator utils
189
190 var cx = {state: null, column: null, marked: null, cc: null};
191 function pass() {
192 for (var i = arguments.length - 1; i >= 0; i--) cx.cc.push(arguments[i]);
193 }
194 function cont() {
195 pass.apply(null, arguments);
196 return true;
197 }
198 function register(varname) {
199 var state = cx.state;
200 if (state.context) {
201 cx.marked = "def";
202 for (var v = state.localVars; v; v = v.next)
203 if (v.name == varname) return;
204 state.localVars = {name: varname, next: state.localVars};
205 }
206 }
207
208 // Combinators
209
210 var defaultVars = {name: "this", next: null};
211 function pushcontext() {
212 if (!cx.state.context) cx.state.localVars = defaultVars;
213 cx.state.context = {prev: cx.state.context, vars: cx.state.localVars};
214 }
215 function popcontext() {
216 cx.state.localVars = cx.state.context.vars;
217 cx.state.context = cx.state.context.prev;
218 }
219 function pushlex(type, info) {
220 var result = function() {
221 var state = cx.state;
222 state.lexical = new HaxeLexical(state.indented, cx.stream.column(), type, null, state.lexical, info)
223 };
224 result.lex = true;
225 return result;
226 }
227 function poplex() {
228 var state = cx.state;
229 if (state.lexical.prev) {
230 if (state.lexical.type == ")")
231 state.indented = state.lexical.indented;
232 state.lexical = state.lexical.prev;
233 }
234 }
235 poplex.lex = true;
236
237 function expect(wanted) {
238 return function expecting(type) {
239 if (type == wanted) return cont();
240 else if (wanted == ";") return pass();
241 else return cont(arguments.callee);
242 };
243 }
244
245 function statement(type) {
246 if (type == "@") return cont(metadef)
247 if (type == "var") return cont(pushlex("vardef"), vardef1, expect(";"), poplex);
248 if (type == "keyword a") return cont(pushlex("form"), expression, statement, poplex);
249 if (type == "keyword b") return cont(pushlex("form"), statement, poplex);
250 if (type == "{") return cont(pushlex("}"), pushcontext, block, poplex, popcontext);
251 if (type == ";") return cont();
252 if (type == "attribute") return cont(maybeattribute);
253 if (type == "function") return cont(functiondef);
254 if (type == "for") return cont(pushlex("form"), expect("("), pushlex(")"), forspec1, expect(")"),
255 poplex, statement, poplex);
256 if (type == "variable") return cont(pushlex("stat"), maybelabel);
257 if (type == "switch") return cont(pushlex("form"), expression, pushlex("}", "switch"), expect("{"),
258 block, poplex, poplex);
259 if (type == "case") return cont(expression, expect(":"));
260 if (type == "default") return cont(expect(":"));
261 if (type == "catch") return cont(pushlex("form"), pushcontext, expect("("), funarg, expect(")"),
262 statement, poplex, popcontext);
263 if (type == "import") return cont(importdef, expect(";"));
264 if (type == "typedef") return cont(typedef);
265 return pass(pushlex("stat"), expression, expect(";"), poplex);
266 }
267 function expression(type) {
268 if (atomicTypes.hasOwnProperty(type)) return cont(maybeoperator);
269 if (type == "function") return cont(functiondef);
270 if (type == "keyword c") return cont(maybeexpression);
271 if (type == "(") return cont(pushlex(")"), maybeexpression, expect(")"), poplex, maybeoperator);
272 if (type == "operator") return cont(expression);
273 if (type == "[") return cont(pushlex("]"), commasep(expression, "]"), poplex, maybeoperator);
274 if (type == "{") return cont(pushlex("}"), commasep(objprop, "}"), poplex, maybeoperator);
275 return cont();
276 }
277 function maybeexpression(type) {
278 if (type.match(/[;\}\)\],]/)) return pass();
279 return pass(expression);
280 }
281
282 function maybeoperator(type, value) {
283 if (type == "operator" && /\+\+|--/.test(value)) return cont(maybeoperator);
284 if (type == "operator" || type == ":") return cont(expression);
285 if (type == ";") return;
286 if (type == "(") return cont(pushlex(")"), commasep(expression, ")"), poplex, maybeoperator);
287 if (type == ".") return cont(property, maybeoperator);
288 if (type == "[") return cont(pushlex("]"), expression, expect("]"), poplex, maybeoperator);
289 }
290
291 function maybeattribute(type, value) {
292 if (type == "attribute") return cont(maybeattribute);
293 if (type == "function") return cont(functiondef);
294 if (type == "var") return cont(vardef1);
295 }
296
297 function metadef(type, value) {
298 if(type == ":") return cont(metadef);
299 if(type == "variable") return cont(metadef);
300 if(type == "(") return cont(pushlex(")"), comasep(metaargs, ")"), poplex, statement)
301 }
302 function metaargs(type, value) {
303 if(typ == "variable") return cont();
304 }
305
306 function importdef (type, value) {
307 if(type == "variable" && /[A-Z]/.test(value.charAt(0))) { registerimport(value); return cont(); }
308 else if(type == "variable" || type == "property" || type == ".") return cont(importdef);
309 }
310
311 function typedef (type, value)
312 {
313 if(type == "variable" && /[A-Z]/.test(value.charAt(0))) { registerimport(value); return cont(); }
314 }
315
316 function maybelabel(type) {
317 if (type == ":") return cont(poplex, statement);
318 return pass(maybeoperator, expect(";"), poplex);
319 }
320 function property(type) {
321 if (type == "variable") {cx.marked = "property"; return cont();}
322 }
323 function objprop(type) {
324 if (type == "variable") cx.marked = "property";
325 if (atomicTypes.hasOwnProperty(type)) return cont(expect(":"), expression);
326 }
327 function commasep(what, end) {
328 function proceed(type) {
329 if (type == ",") return cont(what, proceed);
330 if (type == end) return cont();
331 return cont(expect(end));
332 }
333 return function commaSeparated(type) {
334 if (type == end) return cont();
335 else return pass(what, proceed);
336 };
337 }
338 function block(type) {
339 if (type == "}") return cont();
340 return pass(statement, block);
341 }
342 function vardef1(type, value) {
343 if (type == "variable"){register(value); return cont(typeuse, vardef2);}
344 return cont();
345 }
346 function vardef2(type, value) {
347 if (value == "=") return cont(expression, vardef2);
348 if (type == ",") return cont(vardef1);
349 }
350 function forspec1(type, value) {
351 if (type == "variable") {
352 register(value);
353 }
354 return cont(pushlex(")"), pushcontext, forin, expression, poplex, statement, popcontext);
355 }
356 function forin(type, value) {
357 if (value == "in") return cont();
358 }
359 function functiondef(type, value) {
360 if (type == "variable") {register(value); return cont(functiondef);}
361 if (value == "new") return cont(functiondef);
362 if (type == "(") return cont(pushlex(")"), pushcontext, commasep(funarg, ")"), poplex, typeuse, statement, popcontext);
363 }
364 function typeuse(type, value) {
365 if(type == ":") return cont(typestring);
366 }
367 function typestring(type, value) {
368 if(type == "type") return cont();
369 if(type == "variable") return cont();
370 if(type == "{") return cont(pushlex("}"), commasep(typeprop, "}"), poplex);
371 }
372 function typeprop(type, value) {
373 if(type == "variable") return cont(typeuse);
374 }
375 function funarg(type, value) {
376 if (type == "variable") {register(value); return cont(typeuse);}
377 }
378
379 // Interface
380
381 return {
382 startState: function(basecolumn) {
383 var defaulttypes = ["Int", "Float", "String", "Void", "Std", "Bool", "Dynamic", "Array"];
384 return {
385 tokenize: haxeTokenBase,
386 reAllowed: true,
387 kwAllowed: true,
388 cc: [],
389 lexical: new HaxeLexical((basecolumn || 0) - indentUnit, 0, "block", false),
390 localVars: parserConfig.localVars,
391 importedtypes: defaulttypes,
392 context: parserConfig.localVars && {vars: parserConfig.localVars},
393 indented: 0
394 };
395 },
396
397 token: function(stream, state) {
398 if (stream.sol()) {
399 if (!state.lexical.hasOwnProperty("align"))
400 state.lexical.align = false;
401 state.indented = stream.indentation();
402 }
403 if (stream.eatSpace()) return null;
404 var style = state.tokenize(stream, state);
405 if (type == "comment") return style;
406 state.reAllowed = !!(type == "operator" || type == "keyword c" || type.match(/^[\[{}\(,;:]$/));
407 state.kwAllowed = type != '.';
408 return parseHaxe(state, style, type, content, stream);
409 },
410
411 indent: function(state, textAfter) {
412 if (state.tokenize != haxeTokenBase) return 0;
413 var firstChar = textAfter && textAfter.charAt(0), lexical = state.lexical;
414 if (lexical.type == "stat" && firstChar == "}") lexical = lexical.prev;
415 var type = lexical.type, closing = firstChar == type;
416 if (type == "vardef") return lexical.indented + 4;
417 else if (type == "form" && firstChar == "{") return lexical.indented;
418 else if (type == "stat" || type == "form") return lexical.indented + indentUnit;
419 else if (lexical.info == "switch" && !closing)
420 return lexical.indented + (/^(?:case|default)\b/.test(textAfter) ? indentUnit : 2 * indentUnit);
421 else if (lexical.align) return lexical.column + (closing ? 0 : 1);
422 else return lexical.indented + (closing ? 0 : indentUnit);
423 },
424 compareStates: function(state1, state2) {
425 return (state1.localVars == state2.localVars) && (state1.context == state2.context);
426 },
427
428 electricChars: "{}"
429 };
430 });
431
432 CodeMirror.defineMIME("text/x-haxe", "haxe");
@@ -0,0 +1,90
1 <!doctype html>
2 <html>
3 <head>
4 <title>CodeMirror: Haxe mode</title>
5 <link rel="stylesheet" href="../../lib/codemirror.css">
6 <script src="../../lib/codemirror.js"></script>
7 <script src="haxe.js"></script>
8 <link rel="stylesheet" href="../../doc/docs.css">
9 <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
10 </head>
11 <body>
12 <h1>CodeMirror: Haxe mode</h1>
13
14 <div><textarea id="code" name="code">
15 import one.two.Three;
16
17 @attr("test")
18 class Foo&lt;T&gt; extends Three
19 {
20 public function new()
21 {
22 noFoo = 12;
23 }
24
25 public static inline function doFoo(obj:{k:Int, l:Float}):Int
26 {
27 for(i in 0...10)
28 {
29 obj.k++;
30 trace(i);
31 var var1 = new Array();
32 if(var1.length > 1)
33 throw "Error";
34 }
35 // The following line should not be colored, the variable is scoped out
36 var1;
37 /* Multi line
38 * Comment test
39 */
40 return obj.k;
41 }
42 private function bar():Void
43 {
44 #if flash
45 var t1:String = "1.21";
46 #end
47 try {
48 doFoo({k:3, l:1.2});
49 }
50 catch (e : String) {
51 trace(e);
52 }
53 var t2:Float = cast(3.2);
54 var t3:haxe.Timer = new haxe.Timer();
55 var t4 = {k:Std.int(t2), l:Std.parseFloat(t1)};
56 var t5 = ~/123+.*$/i;
57 doFoo(t4);
58 untyped t1 = 4;
59 bob = new Foo&lt;Int&gt;
60 }
61 public var okFoo(default, never):Float;
62 var noFoo(getFoo, null):Int;
63 function getFoo():Int {
64 return noFoo;
65 }
66
67 public var three:Int;
68 }
69 enum Color
70 {
71 red;
72 green;
73 blue;
74 grey( v : Int );
75 rgb (r:Int,g:Int,b:Int);
76 }
77 </textarea></div>
78
79 <script>
80 var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
81 lineNumbers: true,
82 matchBrackets: true,
83 indentUnit: 4,
84 indentWithTabs: true
85 });
86 </script>
87
88 <p><strong>MIME types defined:</strong> <code>text/x-haxe</code>.</p>
89 </body>
90 </html>
@@ -0,0 +1,68
1 CodeMirror.defineMode("htmlembedded", function(config, parserConfig) {
2
3 //config settings
4 var scriptStartRegex = parserConfig.scriptStartRegex || /^<%/i,
5 scriptEndRegex = parserConfig.scriptEndRegex || /^%>/i;
6
7 //inner modes
8 var scriptingMode, htmlMixedMode;
9
10 //tokenizer when in html mode
11 function htmlDispatch(stream, state) {
12 if (stream.match(scriptStartRegex, false)) {
13 state.token=scriptingDispatch;
14 return scriptingMode.token(stream, state.scriptState);
15 }
16 else
17 return htmlMixedMode.token(stream, state.htmlState);
18 }
19
20 //tokenizer when in scripting mode
21 function scriptingDispatch(stream, state) {
22 if (stream.match(scriptEndRegex, false)) {
23 state.token=htmlDispatch;
24 return htmlMixedMode.token(stream, state.htmlState);
25 }
26 else
27 return scriptingMode.token(stream, state.scriptState);
28 }
29
30
31 return {
32 startState: function() {
33 scriptingMode = scriptingMode || CodeMirror.getMode(config, parserConfig.scriptingModeSpec);
34 htmlMixedMode = htmlMixedMode || CodeMirror.getMode(config, "htmlmixed");
35 return {
36 token : parserConfig.startOpen ? scriptingDispatch : htmlDispatch,
37 htmlState : htmlMixedMode.startState(),
38 scriptState : scriptingMode.startState()
39 }
40 },
41
42 token: function(stream, state) {
43 return state.token(stream, state);
44 },
45
46 indent: function(state, textAfter) {
47 if (state.token == htmlDispatch)
48 return htmlMixedMode.indent(state.htmlState, textAfter);
49 else
50 return scriptingMode.indent(state.scriptState, textAfter);
51 },
52
53 copyState: function(state) {
54 return {
55 token : state.token,
56 htmlState : CodeMirror.copyState(htmlMixedMode, state.htmlState),
57 scriptState : CodeMirror.copyState(scriptingMode, state.scriptState)
58 }
59 },
60
61
62 electricChars: "/{}:"
63 }
64 }, "htmlmixed");
65
66 CodeMirror.defineMIME("application/x-ejs", { name: "htmlembedded", scriptingModeSpec:"javascript"});
67 CodeMirror.defineMIME("application/x-aspx", { name: "htmlembedded", scriptingModeSpec:"text/x-csharp"});
68 CodeMirror.defineMIME("application/x-jsp", { name: "htmlembedded", scriptingModeSpec:"text/x-java"});
@@ -0,0 +1,49
1 <!doctype html>
2 <html>
3 <head>
4 <title>CodeMirror: Html Embedded Scripts mode</title>
5 <link rel="stylesheet" href="../../lib/codemirror.css">
6 <script src="../../lib/codemirror.js"></script>
7 <script src="../xml/xml.js"></script>
8 <script src="../javascript/javascript.js"></script>
9 <script src="../css/css.js"></script>
10 <script src="../htmlmixed/htmlmixed.js"></script>
11 <script src="htmlembedded.js"></script>
12 <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
13 <link rel="stylesheet" href="../../doc/docs.css">
14 </head>
15 <body>
16 <h1>CodeMirror: Html Embedded Scripts mode</h1>
17
18 <form><textarea id="code" name="code">
19 <%
20 function hello(who) {
21 return "Hello " + who;
22 }
23 %>
24 This is an example of EJS (embedded javascript)
25 <p>The program says <%= hello("world") %>.</p>
26 <script>
27 alert("And here is some normal JS code"); // also colored
28 </script>
29 </textarea></form>
30
31 <script>
32 var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
33 lineNumbers: true,
34 matchBrackets: true,
35 mode: "application/x-ejs",
36 indentUnit: 4,
37 indentWithTabs: true,
38 enterMode: "keep",
39 tabMode: "shift"
40 });
41 </script>
42
43 <p>Mode for html embedded scripts like JSP and ASP.NET. Depends on HtmlMixed which in turn depends on
44 JavaScript, CSS and XML.<br />Other dependancies include those of the scriping language chosen.</p>
45
46 <p><strong>MIME types defined:</strong> <code>application/x-aspx</code> (ASP.NET),
47 <code>application/x-ejs</code> (Embedded Javascript), <code>application/x-jsp</code> (JavaServer Pages)</p>
48 </body>
49 </html>
@@ -0,0 +1,37
1 <!doctype html>
2 <html>
3 <head>
4 <title>CodeMirror: Jinja2 mode</title>
5 <link rel="stylesheet" href="../../lib/codemirror.css">
6 <script src="../../lib/codemirror.js"></script>
7 <script src="jinja2.js"></script>
8 <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
9 <link rel="stylesheet" href="../../doc/docs.css">
10 </head>
11 <body>
12 <h1>CodeMirror: Jinja2 mode</h1>
13 <form><textarea id="code" name="code">
14 &lt;html style="color: green"&gt;
15 &lt;!-- this is a comment --&gt;
16 &lt;head&gt;
17 &lt;title&gt;Jinja2 Example&lt;/title&gt;
18 &lt;/head&gt;
19 &lt;body&gt;
20 &lt;ul&gt;
21 {# this is a comment #}
22 {%- for item in li -%}
23 &lt;li&gt;
24 {{ item.label }}
25 &lt;/li&gt;
26 {% endfor -%}
27 &lt;/ul&gt;
28 &lt;/body&gt;
29 &lt;/html&gt;
30 </textarea></form>
31 <script>
32 var editor =
33 CodeMirror.fromTextArea(document.getElementById("code"), {mode:
34 {name: "jinja2", htmlMode: true}});
35 </script>
36 </body>
37 </html>
@@ -0,0 +1,42
1 CodeMirror.defineMode("jinja2", function(config, parserConf) {
2 var keywords = ["block", "endblock", "for", "endfor", "in", "true", "false",
3 "loop", "none", "self", "super", "if", "as", "not", "and",
4 "else", "import", "with", "without", "context"];
5 keywords = new RegExp("^((" + keywords.join(")|(") + "))\\b");
6
7 function tokenBase (stream, state) {
8 var ch = stream.next();
9 if (ch == "{") {
10 if (ch = stream.eat(/\{|%|#/)) {
11 stream.eat("-");
12 state.tokenize = inTag(ch);
13 return "tag";
14 }
15 }
16 }
17 function inTag (close) {
18 if (close == "{") {
19 close = "}";
20 }
21 return function (stream, state) {
22 var ch = stream.next();
23 if ((ch == close || (ch == "-" && stream.eat(close)))
24 && stream.eat("}")) {
25 state.tokenize = tokenBase;
26 return "tag";
27 }
28 if (stream.match(keywords)) {
29 return "keyword";
30 }
31 return close == "#" ? "comment" : "string";
32 };
33 }
34 return {
35 startState: function () {
36 return {tokenize: tokenBase};
37 },
38 token: function (stream, state) {
39 return state.tokenize(stream, state);
40 }
41 };
42 });
This diff has been collapsed as it changes many lines, (618 lines changed) Show them Hide them
@@ -0,0 +1,618
1 <!doctype html>
2 <html>
3 <head>
4 <title>CodeMirror: LESS mode</title>
5 <link rel="stylesheet" href="../../lib/codemirror.css">
6 <script src="../../lib/codemirror.js"></script>
7 <script src="less.js"></script>
8 <style>.CodeMirror {background: #f8f8f8; border: 1px solid #ddd; font-size:12px} .CodeMirror-scroll {height: 400px}</style>
9 <link rel="stylesheet" href="../../doc/docs.css">
10 <link rel="stylesheet" href="../../theme/lesser-dark.css">
11 <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
12 </head>
13 <body>
14 <h1>CodeMirror: LESS mode</h1>
15 <form><textarea id="code" name="code">/* Some LESS code */
16
17 button {
18 width: 32px;
19 height: 32px;
20 border: 0;
21 margin: 4px;
22 cursor: pointer;
23 }
24 button.icon-plus { background: url(http://dahlström.net/tmp/sharp-icons/svg-icon-target.svg#plus) no-repeat; }
25 button.icon-chart { background: url(http://dahlström.net/tmp/sharp-icons/svg-icon-target.svg#chart) no-repeat; }
26
27 button:hover { background-color: #999; }
28 button:active { background-color: #666; }
29
30 @test_a: #eeeQQQ;//this is not a valid hex value and thus parsed as an element id
31 @test_b: #eeeFFF //this is a valid hex value but the declaration doesn't end with a semicolon and thus parsed as an element id
32
33 #eee aaa .box
34 {
35 #test bbb {
36 width: 500px;
37 height: 250px;
38 background-image: url(dir/output/sheep.png), url( betweengrassandsky.png );
39 background-position: center bottom, left top;
40 background-repeat: no-repeat;
41 }
42 }
43
44 @base: #f938ab;
45
46 .box-shadow(@style, @c) when (iscolor(@c)) {
47 box-shadow: @style @c;
48 -webkit-box-shadow: @style @c;
49 -moz-box-shadow: @style @c;
50 }
51 .box-shadow(@style, @alpha: 50%) when (isnumber(@alpha)) {
52 .box-shadow(@style, rgba(0, 0, 0, @alpha));
53 }
54
55 @color: #4D926F;
56
57 #header {
58 color: @color;
59 color: #000000;
60 }
61 h2 {
62 color: @color;
63 }
64
65 .rounded-corners (@radius: 5px) {
66 border-radius: @radius;
67 -webkit-border-radius: @radius;
68 -moz-border-radius: @radius;
69 }
70
71 #header {
72 .rounded-corners;
73 }
74 #footer {
75 .rounded-corners(10px);
76 }
77
78 .box-shadow (@x: 0, @y: 0, @blur: 1px, @alpha) {
79 @val: @x @y @blur rgba(0, 0, 0, @alpha);
80
81 box-shadow: @val;
82 -webkit-box-shadow: @val;
83 -moz-box-shadow: @val;
84 }
85 .box { @base: #f938ab;
86 color: saturate(@base, 5%);
87 border-color: lighten(@base, 30%);
88 div { .box-shadow(0, 0, 5px, 0.4) }
89 }
90
91 @import url("something.css");
92
93 @light-blue: hsl(190, 50%, 65%);
94 @light-yellow: desaturate(#fefec8, 10%);
95 @dark-yellow: desaturate(darken(@light-yellow, 10%), 40%);
96 @darkest: hsl(20, 0%, 15%);
97 @dark: hsl(190, 20%, 30%);
98 @medium: hsl(10, 60%, 30%);
99 @light: hsl(90, 40%, 20%);
100 @lightest: hsl(90, 20%, 90%);
101 @highlight: hsl(80, 50%, 90%);
102 @blue: hsl(210, 60%, 20%);
103 @alpha-blue: hsla(210, 60%, 40%, 0.5);
104
105 .box-shadow (@x, @y, @blur, @alpha) {
106 @value: @x @y @blur rgba(0, 0, 0, @alpha);
107 box-shadow: @value;
108 -moz-box-shadow: @value;
109 -webkit-box-shadow: @value;
110 }
111 .border-radius (@radius) {
112 border-radius: @radius;
113 -moz-border-radius: @radius;
114 -webkit-border-radius: @radius;
115 }
116
117 .border-radius (@radius, bottom) {
118 border-top-right-radius: 0;
119 border-top-left-radius: 0;
120 -moz-border-top-right-radius: 0;
121 -moz-border-top-left-radius: 0;
122 -webkit-border-top-left-radius: 0;
123 -webkit-border-top-right-radius: 0;
124 }
125 .border-radius (@radius, right) {
126 border-bottom-left-radius: 0;
127 border-top-left-radius: 0;
128 -moz-border-bottom-left-radius: 0;
129 -moz-border-top-left-radius: 0;
130 -webkit-border-bottom-left-radius: 0;
131 -webkit-border-top-left-radius: 0;
132 }
133 .box-shadow-inset (@x, @y, @blur, @color) {
134 box-shadow: @x @y @blur @color inset;
135 -moz-box-shadow: @x @y @blur @color inset;
136 -webkit-box-shadow: @x @y @blur @color inset;
137 }
138 .code () {
139 font-family: 'Bitstream Vera Sans Mono',
140 'DejaVu Sans Mono',
141 'Monaco',
142 Courier,
143 monospace !important;
144 }
145 .wrap () {
146 text-wrap: wrap;
147 white-space: pre-wrap; /* css-3 */
148 white-space: -moz-pre-wrap; /* Mozilla, since 1999 */
149 white-space: -pre-wrap; /* Opera 4-6 */
150 white-space: -o-pre-wrap; /* Opera 7 */
151 word-wrap: break-word; /* Internet Explorer 5.5+ */
152 }
153
154 html { margin: 0 }
155 body {
156 background-color: @darkest;
157 margin: 0 auto;
158 font-family: Arial, sans-serif;
159 font-size: 100%;
160 overflow-x: hidden;
161 }
162 nav, header, footer, section, article {
163 display: block;
164 }
165 a {
166 color: #b83000;
167 }
168 h1 a {
169 color: black;
170 text-decoration: none;
171 }
172 a:hover {
173 text-decoration: underline;
174 }
175 h1, h2, h3, h4 {
176 margin: 0;
177 font-weight: normal;
178 }
179 ul, li {
180 list-style-type: none;
181 }
182 code { .code; }
183 code {
184 .string, .regexp { color: @dark }
185 .keyword { font-weight: bold }
186 .comment { color: rgba(0, 0, 0, 0.5) }
187 .number { color: @blue }
188 .class, .special { color: rgba(0, 50, 100, 0.8) }
189 }
190 pre {
191 padding: 0 30px;
192 .wrap;
193 }
194 blockquote {
195 font-style: italic;
196 }
197 body > footer {
198 text-align: left;
199 margin-left: 10px;
200 font-style: italic;
201 font-size: 18px;
202 color: #888;
203 }
204
205 #logo {
206 margin-top: 30px;
207 margin-bottom: 30px;
208 display: block;
209 width: 199px;
210 height: 81px;
211 background: url(/images/logo.png) no-repeat;
212 }
213 nav {
214 margin-left: 15px;
215 }
216 nav a, #dropdown li {
217 display: inline-block;
218 color: white;
219 line-height: 42px;
220 margin: 0;
221 padding: 0px 15px;
222 text-shadow: -1px -1px 1px rgba(0, 0, 0, 0.5);
223 text-decoration: none;
224 border: 2px solid transparent;
225 border-width: 0 2px;
226 &:hover {
227 .dark-red;
228 text-decoration: none;
229 }
230 }
231 .dark-red {
232 @red: @medium;
233 border: 2px solid darken(@red, 25%);
234 border-left-color: darken(@red, 15%);
235 border-right-color: darken(@red, 15%);
236 border-bottom: 0;
237 border-top: 0;
238 background-color: darken(@red, 10%);
239 }
240
241 .content {
242 margin: 0 auto;
243 width: 980px;
244 }
245
246 #menu {
247 position: absolute;
248 width: 100%;
249 z-index: 3;
250 clear: both;
251 display: block;
252 background-color: @blue;
253 height: 42px;
254 border-top: 2px solid lighten(@alpha-blue, 20%);
255 border-bottom: 2px solid darken(@alpha-blue, 25%);
256 .box-shadow(0, 1px, 8px, 0.6);
257 -moz-box-shadow: 0 0 0 #000; // Because firefox sucks.
258
259 &.docked {
260 background-color: hsla(210, 60%, 40%, 0.4);
261 }
262 &:hover {
263 background-color: @blue;
264 }
265
266 #dropdown {
267 margin: 0 0 0 117px;
268 padding: 0;
269 padding-top: 5px;
270 display: none;
271 width: 190px;
272 border-top: 2px solid @medium;
273 color: @highlight;
274 border: 2px solid darken(@medium, 25%);
275 border-left-color: darken(@medium, 15%);
276 border-right-color: darken(@medium, 15%);
277 border-top-width: 0;
278 background-color: darken(@medium, 10%);
279 ul {
280 padding: 0px;
281 }
282 li {
283 font-size: 14px;
284 display: block;
285 text-align: left;
286 padding: 0;
287 border: 0;
288 a {
289 display: block;
290 padding: 0px 15px;
291 text-decoration: none;
292 color: white;
293 &:hover {
294 background-color: darken(@medium, 15%);
295 text-decoration: none;
296 }
297 }
298 }
299 .border-radius(5px, bottom);
300 .box-shadow(0, 6px, 8px, 0.5);
301 }
302 }
303
304 #main {
305 margin: 0 auto;
306 width: 100%;
307 background-color: @light-blue;
308 border-top: 8px solid darken(@light-blue, 5%);
309
310 #intro {
311 background-color: lighten(@light-blue, 25%);
312 float: left;
313 margin-top: -8px;
314 margin-right: 5px;
315
316 height: 380px;
317 position: relative;
318 z-index: 2;
319 font-family: 'Droid Serif', 'Georgia';
320 width: 395px;
321 padding: 45px 20px 23px 30px;
322 border: 2px dashed darken(@light-blue, 10%);
323 .box-shadow(1px, 0px, 6px, 0.5);
324 border-bottom: 0;
325 border-top: 0;
326 #download { color: transparent; border: 0; float: left; display: inline-block; margin: 15px 0 15px -5px; }
327 #download img { display: inline-block}
328 #download-info {
329 code {
330 font-size: 13px;
331 }
332 color: @blue + #333; display: inline; float: left; margin: 36px 0 0 15px }
333 }
334 h2 {
335 span {
336 color: @medium;
337 }
338 color: @blue;
339 margin: 20px 0;
340 font-size: 24px;
341 line-height: 1.2em;
342 }
343 h3 {
344 color: @blue;
345 line-height: 1.4em;
346 margin: 30px 0 15px 0;
347 font-size: 1em;
348 text-shadow: 0px 0px 0px @lightest;
349 span { color: @medium }
350 }
351 #example {
352 p {
353 font-size: 18px;
354 color: @blue;
355 font-weight: bold;
356 text-shadow: 0px 1px 1px @lightest;
357 }
358 pre {
359 margin: 0;
360 text-shadow: 0 -1px 1px @darkest;
361 margin-top: 20px;
362 background-color: desaturate(@darkest, 8%);
363 border: 0;
364 width: 450px;
365 color: lighten(@lightest, 2%);
366 background-repeat: repeat;
367 padding: 15px;
368 border: 1px dashed @lightest;
369 line-height: 15px;
370 .box-shadow(0, 0px, 15px, 0.5);
371 .code;
372 .border-radius(2px);
373 code .attribute { color: hsl(40, 50%, 70%) }
374 code .variable { color: hsl(120, 10%, 50%) }
375 code .element { color: hsl(170, 20%, 50%) }
376
377 code .string, .regexp { color: hsl(75, 50%, 65%) }
378 code .class { color: hsl(40, 40%, 60%); font-weight: normal }
379 code .id { color: hsl(50, 40%, 60%); font-weight: normal }
380 code .comment { color: rgba(255, 255, 255, 0.2) }
381 code .number, .color { color: hsl(10, 40%, 50%) }
382 code .class, code .mixin, .special { color: hsl(190, 20%, 50%) }
383 #time { color: #aaa }
384 }
385 float: right;
386 font-size: 12px;
387 margin: 0;
388 margin-top: 15px;
389 padding: 0;
390 width: 500px;
391 }
392 }
393
394
395 .page {
396 .content {
397 width: 870px;
398 padding: 45px;
399 }
400 margin: 0 auto;
401 font-family: 'Georgia', serif;
402 font-size: 18px;
403 line-height: 26px;
404 padding: 0 60px;
405 code {
406 font-size: 16px;
407 }
408 pre {
409 border-width: 1px;
410 border-style: dashed;
411 padding: 15px;
412 margin: 15px 0;
413 }
414 h1 {
415 text-align: left;
416 font-size: 40px;
417 margin-top: 15px;
418 margin-bottom: 35px;
419 }
420 p + h1 { margin-top: 60px }
421 h2, h3 {
422 margin: 30px 0 15px 0;
423 }
424 p + h2, pre + h2, code + h2 {
425 border-top: 6px solid rgba(255, 255, 255, 0.1);
426 padding-top: 30px;
427 }
428 h3 {
429 margin: 15px 0;
430 }
431 }
432
433
434 #docs {
435 @bg: lighten(@light-blue, 5%);
436 border-top: 2px solid lighten(@bg, 5%);
437 color: @blue;
438 background-color: @light-blue;
439 .box-shadow(0, -2px, 5px, 0.2);
440
441 h1 {
442 font-family: 'Droid Serif', 'Georgia', serif;
443 padding-top: 30px;
444 padding-left: 45px;
445 font-size: 44px;
446 text-align: left;
447 margin: 30px 0 !important;
448 text-shadow: 0px 1px 1px @lightest;
449 font-weight: bold;
450 }
451 .content {
452 clear: both;
453 border-color: transparent;
454 background-color: lighten(@light-blue, 25%);
455 .box-shadow(0, 5px, 5px, 0.4);
456 }
457 pre {
458 @background: lighten(@bg, 30%);
459 color: lighten(@blue, 10%);
460 background-color: @background;
461 border-color: lighten(@light-blue, 25%);
462 border-width: 2px;
463 code .attribute { color: hsl(40, 50%, 30%) }
464 code .variable { color: hsl(120, 10%, 30%) }
465 code .element { color: hsl(170, 20%, 30%) }
466
467 code .string, .regexp { color: hsl(75, 50%, 35%) }
468 code .class { color: hsl(40, 40%, 30%); font-weight: normal }
469 code .id { color: hsl(50, 40%, 30%); font-weight: normal }
470 code .comment { color: rgba(0, 0, 0, 0.4) }
471 code .number, .color { color: hsl(10, 40%, 30%) }
472 code .class, code .mixin, .special { color: hsl(190, 20%, 30%) }
473 }
474 pre code { font-size: 15px }
475 p + h2, pre + h2, code + h2 { border-top-color: rgba(0, 0, 0, 0.1) }
476 }
477
478 td {
479 padding-right: 30px;
480 }
481 #synopsis {
482 .box-shadow(0, 5px, 5px, 0.2);
483 }
484 #synopsis, #about {
485 h2 {
486 font-size: 30px;
487 padding: 10px 0;
488 }
489 h1 + h2 {
490 margin-top: 15px;
491 }
492 h3 { font-size: 22px }
493
494 .code-example {
495 border-spacing: 0;
496 border-width: 1px;
497 border-style: dashed;
498 padding: 0;
499 pre { border: 0; margin: 0 }
500 td {
501 border: 0;
502 margin: 0;
503 background-color: desaturate(darken(@darkest, 5%), 20%);
504 vertical-align: top;
505 padding: 0;
506 }
507 tr { padding: 0 }
508 }
509 .css-output {
510 td {
511 border-left: 0;
512 }
513 }
514 .less-example {
515 //border-right: 1px dotted rgba(255, 255, 255, 0.5) !important;
516 }
517 .css-output, .less-example {
518 width: 390px;
519 }
520 pre {
521 padding: 20px;
522 line-height: 20px;
523 font-size: 14px;
524 }
525 }
526 #about, #synopsis, #guide {
527 a {
528 text-decoration: none;
529 color: @light-yellow;
530 border-bottom: 1px dashed rgba(255, 255, 255, 0.2);
531 &:hover {
532 text-decoration: none;
533 border-bottom: 1px dashed @light-yellow;
534 }
535 }
536 @bg: desaturate(darken(@darkest, 5%), 20%);
537 text-shadow: 0 -1px 1px lighten(@bg, 5%);
538 color: @highlight;
539 background-color: @bg;
540 .content {
541 background-color: desaturate(@darkest, 20%);
542 clear: both;
543 .box-shadow(0, 5px, 5px, 0.4);
544 }
545 h1, h2, h3 {
546 color: @dark-yellow;
547 }
548 pre {
549 code .attribute { color: hsl(40, 50%, 70%) }
550 code .variable { color: hsl(120, 10%, 50%) }
551 code .element { color: hsl(170, 20%, 50%) }
552
553 code .string, .regexp { color: hsl(75, 50%, 65%) }
554 code .class { color: hsl(40, 40%, 60%); font-weight: normal }
555 code .id { color: hsl(50, 40%, 60%); font-weight: normal }
556 code .comment { color: rgba(255, 255, 255, 0.2) }
557 code .number, .color { color: hsl(10, 40%, 50%) }
558 code .class, code .mixin, .special { color: hsl(190, 20%, 50%) }
559 background-color: @bg;
560 border-color: darken(@light-yellow, 5%);
561 }
562 code {
563 color: darken(@dark-yellow, 5%);
564 .string, .regexp { color: desaturate(@light-blue, 15%) }
565 .keyword { color: hsl(40, 40%, 60%); font-weight: normal }
566 .comment { color: rgba(255, 255, 255, 0.2) }
567 .number { color: lighten(@blue, 10%) }
568 .class, .special { color: hsl(190, 20%, 50%) }
569 }
570 }
571 #guide {
572 background-color: @darkest;
573 .content {
574 background-color: transparent;
575 }
576
577 }
578
579 #about {
580 background-color: @darkest !important;
581 .content {
582 background-color: desaturate(lighten(@darkest, 3%), 5%);
583 }
584 }
585 #synopsis {
586 background-color: desaturate(lighten(@darkest, 3%), 5%) !important;
587 .content {
588 background-color: desaturate(lighten(@darkest, 3%), 5%);
589 }
590 pre {}
591 }
592 #synopsis, #guide {
593 .content {
594 .box-shadow(0, 0px, 0px, 0.0);
595 }
596 }
597 #about footer {
598 margin-top: 30px;
599 padding-top: 30px;
600 border-top: 6px solid rgba(0, 0, 0, 0.1);
601 text-align: center;
602 font-size: 16px;
603 color: rgba(255, 255, 255, 0.35);
604 #copy { font-size: 12px }
605 text-shadow: -1px -1px 1px rgba(0, 0, 0, 0.02);
606 }
607 </textarea></form>
608 <script>
609 var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
610 theme: "lesser-dark",
611 lineNumbers : true,
612 matchBrackets : true
613 });
614 </script>
615
616 <p><strong>MIME types defined:</strong> <code>text/x-less</code>, <code>text/css</code> (if not previously defined).</p>
617 </body>
618 </html>
@@ -0,0 +1,232
1 /*
2 LESS mode - http://www.lesscss.org/
3 Ported to CodeMirror by Peter Kroon
4 */
5
6 CodeMirror.defineMode("less", function(config) {
7 var indentUnit = config.indentUnit, type;
8 function ret(style, tp) {type = tp; return style;}
9 //html5 tags
10 var tags = ["a","abbr","acronym","address","applet","area","article","aside","audio","b","base","basefont","bdi","bdo","big","blockquote","body","br","button","canvas","caption","cite","code","col","colgroup","command","datalist","dd","del","details","dfn","dir","div","dl","dt","em","embed","fieldset","figcaption","figure","font","footer","form","frame","frameset","h1","h2","h3","h4","h5","h6","head","header","hgroup","hr","html","i","iframe","img","input","ins","keygen","kbd","label","legend","li","link","map","mark","menu","meta","meter","nav","noframes","noscript","object","ol","optgroup","option","output","p","param","pre","progress","q","rp","rt","ruby","s","samp","script","section","select","small","source","span","strike","strong","style","sub","summary","sup","table","tbody","td","textarea","tfoot","th","thead","time","title","tr","track","tt","u","ul","var","video","wbr"];
11
12 function inTagsArray(val){
13 for(var i=0; i<tags.length; i++){
14 if(val === tags[i]){
15 return true;
16 }
17 }
18 }
19
20 function tokenBase(stream, state) {
21 var ch = stream.next();
22
23 if (ch == "@") {stream.eatWhile(/[\w\-]/); return ret("meta", stream.current());}
24 else if (ch == "/" && stream.eat("*")) {
25 state.tokenize = tokenCComment;
26 return tokenCComment(stream, state);
27 }
28 else if (ch == "<" && stream.eat("!")) {
29 state.tokenize = tokenSGMLComment;
30 return tokenSGMLComment(stream, state);
31 }
32 else if (ch == "=") ret(null, "compare");
33 else if ((ch == "~" || ch == "|") && stream.eat("=")) return ret(null, "compare");
34 else if (ch == "\"" || ch == "'") {
35 state.tokenize = tokenString(ch);
36 return state.tokenize(stream, state);
37 }
38 else if (ch == "/") { // lesscss e.g.: .png will not be parsed as a class
39 if(stream.eat("/")){
40 state.tokenize = tokenSComment;
41 return tokenSComment(stream, state);
42 }else{
43 stream.eatWhile(/[\a-zA-Z0-9\-_.\s]/);
44 if(/\/|\)|#/.test(stream.peek() || stream.eol() || (stream.eatSpace() && stream.peek() == ")")))return ret("string", "string");//let url(/images/logo.png) without quotes return as string
45 return ret("number", "unit");
46 }
47 }
48 else if (ch == "!") {
49 stream.match(/^\s*\w*/);
50 return ret("keyword", "important");
51 }
52 else if (/\d/.test(ch)) {
53 stream.eatWhile(/[\w.%]/);
54 return ret("number", "unit");
55 }
56 else if (/[,+<>*\/]/.test(ch)) {//removed . dot character original was [,.+>*\/]
57 return ret(null, "select-op");
58 }
59 else if (/[;{}:\[\]()]/.test(ch)) { //added () char for lesscss original was [;{}:\[\]]
60 if(ch == ":"){
61 stream.eatWhile(/[active|hover|link|visited]/);
62 if( stream.current().match(/active|hover|link|visited/)){
63 return ret("tag", "tag");
64 }else{
65 return ret(null, ch);
66 }
67 }else{
68 return ret(null, ch);
69 }
70 }
71 else if (ch == ".") { // lesscss
72 stream.eatWhile(/[\a-zA-Z0-9\-_]/);
73 return ret("tag", "tag");
74 }
75 else if (ch == "#") { // lesscss
76 //we don't eat white-space, we want the hex color and or id only
77 stream.eatWhile(/[A-Za-z0-9]/);
78 //check if there is a proper hex color length e.g. #eee || #eeeEEE
79 if(stream.current().length ===4 || stream.current().length ===7){
80 if(stream.current().match(/[A-Fa-f0-9]{6}|[A-Fa-f0-9]{3}/,false) != null){//is there a valid hex color value present in the current stream
81 //when not a valid hex value, parse as id
82 if(stream.current().substring(1) != stream.current().match(/[A-Fa-f0-9]{6}|[A-Fa-f0-9]{3}/,false))return ret("atom", "tag");
83 //eat white-space
84 stream.eatSpace();
85 //when hex value declaration doesn't end with [;,] but is does with a slash/cc comment treat it as an id, just like the other hex values that don't end with[;,]
86 if( /[\/<>.(){!$%^&*_\-\\?=+\|#'~`]/.test(stream.peek()) )return ret("atom", "tag");
87 //#time { color: #aaa }
88 else if(stream.peek() == "}" )return ret("number", "unit");
89 //we have a valid hex color value, parse as id whenever an element/class is defined after the hex(id) value e.g. #eee aaa || #eee .aaa
90 else if( /[a-zA-Z\\]/.test(stream.peek()) )return ret("atom", "tag");
91 //when a hex value is on the end of a line, parse as id
92 else if(stream.eol())return ret("atom", "tag");
93 //default
94 else return ret("number", "unit");
95 }else{//when not a valid hexvalue in the current stream e.g. #footer
96 stream.eatWhile(/[\w\\\-]/);
97 return ret("atom", "tag");
98 }
99 }else{
100 stream.eatWhile(/[\w\\\-]/);
101 return ret("atom", "tag");
102 }
103 }
104 else if (ch == "&") {
105 stream.eatWhile(/[\w\-]/);
106 return ret(null, ch);
107 }
108 else {
109 stream.eatWhile(/[\w\\\-_%.{]/);
110 if(stream.current().match(/http|https/) != null){
111 stream.eatWhile(/[\w\\\-_%.{:\/]/);
112 return ret("string", "string");
113 }else if(stream.peek() == "<" || stream.peek() == ">"){
114 return ret("tag", "tag");
115 }else if( stream.peek().match(/\(/) != null ){// lessc
116 return ret(null, ch);
117 }else if (stream.peek() == "/" && state.stack[state.stack.length-1] != undefined){ // url(dir/center/image.png)
118 return ret("string", "string");
119 }else if( stream.current().match(/\-\d|\-.\d/) ){ // lesscss match e.g.: -5px -0.4 etc... only colorize the minus sign
120 //stream.backUp(stream.current().length-1); //commment out these 2 comment if you want the minus sign to be parsed as null -500px
121 //return ret(null, ch);
122 return ret("number", "unit");
123 }else if( inTagsArray(stream.current()) ){ // lesscss match html tags
124 return ret("tag", "tag");
125 }else if( /\/|[\s\)]/.test(stream.peek() || stream.eol() || (stream.eatSpace() && stream.peek() == "/")) && stream.current().indexOf(".") !== -1){
126 if(stream.current().substring(stream.current().length-1,stream.current().length) == "{"){
127 stream.backUp(1);
128 return ret("tag", "tag");
129 }//end if
130 if( (stream.eatSpace() && stream.peek().match(/[{<>.a-zA-Z]/) != null) || stream.eol() )return ret("tag", "tag");//e.g. button.icon-plus
131 return ret("string", "string");//let url(/images/logo.png) without quotes return as string
132 }else if( stream.eol() ){
133 if(stream.current().substring(stream.current().length-1,stream.current().length) == "{")stream.backUp(1);
134 return ret("tag", "tag");
135 }else{
136 return ret("variable", "variable");
137 }
138 }
139
140 }
141
142 function tokenSComment(stream, state) {// SComment = Slash comment
143 stream.skipToEnd();
144 state.tokenize = tokenBase;
145 return ret("comment", "comment");
146 }
147
148 function tokenCComment(stream, state) {
149 var maybeEnd = false, ch;
150 while ((ch = stream.next()) != null) {
151 if (maybeEnd && ch == "/") {
152 state.tokenize = tokenBase;
153 break;
154 }
155 maybeEnd = (ch == "*");
156 }
157 return ret("comment", "comment");
158 }
159
160 function tokenSGMLComment(stream, state) {
161 var dashes = 0, ch;
162 while ((ch = stream.next()) != null) {
163 if (dashes >= 2 && ch == ">") {
164 state.tokenize = tokenBase;
165 break;
166 }
167 dashes = (ch == "-") ? dashes + 1 : 0;
168 }
169 return ret("comment", "comment");
170 }
171
172 function tokenString(quote) {
173 return function(stream, state) {
174 var escaped = false, ch;
175 while ((ch = stream.next()) != null) {
176 if (ch == quote && !escaped)
177 break;
178 escaped = !escaped && ch == "\\";
179 }
180 if (!escaped) state.tokenize = tokenBase;
181 return ret("string", "string");
182 };
183 }
184
185 return {
186 startState: function(base) {
187 return {tokenize: tokenBase,
188 baseIndent: base || 0,
189 stack: []};
190 },
191
192 token: function(stream, state) {
193 if (stream.eatSpace()) return null;
194 var style = state.tokenize(stream, state);
195
196 var context = state.stack[state.stack.length-1];
197 if (type == "hash" && context == "rule") style = "atom";
198 else if (style == "variable") {
199 if (context == "rule") style = null; //"tag"
200 else if (!context || context == "@media{"){
201 style = stream.current() == "when" ? "variable" :
202 stream.string.match(/#/g) != undefined ? null :
203 /[\s,|\s\)]/.test(stream.peek()) ? "tag" : null;
204 }
205 }
206
207 if (context == "rule" && /^[\{\};]$/.test(type))
208 state.stack.pop();
209 if (type == "{") {
210 if (context == "@media") state.stack[state.stack.length-1] = "@media{";
211 else state.stack.push("{");
212 }
213 else if (type == "}") state.stack.pop();
214 else if (type == "@media") state.stack.push("@media");
215 else if (context == "{" && type != "comment") state.stack.push("rule");
216 return style;
217 },
218
219 indent: function(state, textAfter) {
220 var n = state.stack.length;
221 if (/^\}/.test(textAfter))
222 n -= state.stack[state.stack.length-1] == "rule" ? 2 : 1;
223 return state.baseIndent + n * indentUnit;
224 },
225
226 electricChars: "}"
227 };
228 });
229
230 CodeMirror.defineMIME("text/x-less", "less");
231 if (!CodeMirror.mimeModes.hasOwnProperty("text/css"))
232 CodeMirror.defineMIME("text/css", "less");
@@ -0,0 +1,72
1 <!doctype html>
2 <html>
3 <head>
4 <title>CodeMirror: Lua mode</title>
5 <link rel="stylesheet" href="../../lib/codemirror.css">
6 <script src="../../lib/codemirror.js"></script>
7 <script src="lua.js"></script>
8 <link rel="stylesheet" href="../../theme/neat.css">
9 <style>.CodeMirror {border: 1px solid black;}</style>
10 <link rel="stylesheet" href="../../doc/docs.css">
11 </head>
12 <body>
13 <h1>CodeMirror: Lua mode</h1>
14 <form><textarea id="code" name="code">
15 --[[
16 example useless code to show lua syntax highlighting
17 this is multiline comment
18 ]]
19
20 function blahblahblah(x)
21
22 local table = {
23 "asd" = 123,
24 "x" = 0.34,
25 }
26 if x ~= 3 then
27 print( x )
28 elseif x == "string"
29 my_custom_function( 0x34 )
30 else
31 unknown_function( "some string" )
32 end
33
34 --single line comment
35
36 end
37
38 function blablabla3()
39
40 for k,v in ipairs( table ) do
41 --abcde..
42 y=[=[
43 x=[[
44 x is a multi line string
45 ]]
46 but its definition is iside a highest level string!
47 ]=]
48 print(" \"\" ")
49
50 s = math.sin( x )
51 end
52
53 end
54 </textarea></form>
55 <script>
56 var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
57 tabMode: "indent",
58 matchBrackets: true,
59 theme: "neat"
60 });
61 </script>
62
63 <p>Loosely based on Franciszek
64 Wawrzak's <a href="http://codemirror.net/1/contrib/lua">CodeMirror
65 1 mode</a>. One configuration parameter is
66 supported, <code>specials</code>, to which you can provide an
67 array of strings to have those identifiers highlighted with
68 the <code>lua-special</code> style.</p>
69 <p><strong>MIME types defined:</strong> <code>text/x-lua</code>.</p>
70
71 </body>
72 </html>
@@ -0,0 +1,140
1 // LUA mode. Ported to CodeMirror 2 from Franciszek Wawrzak's
2 // CodeMirror 1 mode.
3 // highlights keywords, strings, comments (no leveling supported! ("[==[")), tokens, basic indenting
4
5 CodeMirror.defineMode("lua", function(config, parserConfig) {
6 var indentUnit = config.indentUnit;
7
8 function prefixRE(words) {
9 return new RegExp("^(?:" + words.join("|") + ")", "i");
10 }
11 function wordRE(words) {
12 return new RegExp("^(?:" + words.join("|") + ")$", "i");
13 }
14 var specials = wordRE(parserConfig.specials || []);
15
16 // long list of standard functions from lua manual
17 var builtins = wordRE([
18 "_G","_VERSION","assert","collectgarbage","dofile","error","getfenv","getmetatable","ipairs","load",
19 "loadfile","loadstring","module","next","pairs","pcall","print","rawequal","rawget","rawset","require",
20 "select","setfenv","setmetatable","tonumber","tostring","type","unpack","xpcall",
21
22 "coroutine.create","coroutine.resume","coroutine.running","coroutine.status","coroutine.wrap","coroutine.yield",
23
24 "debug.debug","debug.getfenv","debug.gethook","debug.getinfo","debug.getlocal","debug.getmetatable",
25 "debug.getregistry","debug.getupvalue","debug.setfenv","debug.sethook","debug.setlocal","debug.setmetatable",
26 "debug.setupvalue","debug.traceback",
27
28 "close","flush","lines","read","seek","setvbuf","write",
29
30 "io.close","io.flush","io.input","io.lines","io.open","io.output","io.popen","io.read","io.stderr","io.stdin",
31 "io.stdout","io.tmpfile","io.type","io.write",
32
33 "math.abs","math.acos","math.asin","math.atan","math.atan2","math.ceil","math.cos","math.cosh","math.deg",
34 "math.exp","math.floor","math.fmod","math.frexp","math.huge","math.ldexp","math.log","math.log10","math.max",
35 "math.min","math.modf","math.pi","math.pow","math.rad","math.random","math.randomseed","math.sin","math.sinh",
36 "math.sqrt","math.tan","math.tanh",
37
38 "os.clock","os.date","os.difftime","os.execute","os.exit","os.getenv","os.remove","os.rename","os.setlocale",
39 "os.time","os.tmpname",
40
41 "package.cpath","package.loaded","package.loaders","package.loadlib","package.path","package.preload",
42 "package.seeall",
43
44 "string.byte","string.char","string.dump","string.find","string.format","string.gmatch","string.gsub",
45 "string.len","string.lower","string.match","string.rep","string.reverse","string.sub","string.upper",
46
47 "table.concat","table.insert","table.maxn","table.remove","table.sort"
48 ]);
49 var keywords = wordRE(["and","break","elseif","false","nil","not","or","return",
50 "true","function", "end", "if", "then", "else", "do",
51 "while", "repeat", "until", "for", "in", "local" ]);
52
53 var indentTokens = wordRE(["function", "if","repeat","do", "\\(", "{"]);
54 var dedentTokens = wordRE(["end", "until", "\\)", "}"]);
55 var dedentPartial = prefixRE(["end", "until", "\\)", "}", "else", "elseif"]);
56
57 function readBracket(stream) {
58 var level = 0;
59 while (stream.eat("=")) ++level;
60 stream.eat("[");
61 return level;
62 }
63
64 function normal(stream, state) {
65 var ch = stream.next();
66 if (ch == "-" && stream.eat("-")) {
67 if (stream.eat("["))
68 return (state.cur = bracketed(readBracket(stream), "comment"))(stream, state);
69 stream.skipToEnd();
70 return "comment";
71 }
72 if (ch == "\"" || ch == "'")
73 return (state.cur = string(ch))(stream, state);
74 if (ch == "[" && /[\[=]/.test(stream.peek()))
75 return (state.cur = bracketed(readBracket(stream), "string"))(stream, state);
76 if (/\d/.test(ch)) {
77 stream.eatWhile(/[\w.%]/);
78 return "number";
79 }
80 if (/[\w_]/.test(ch)) {
81 stream.eatWhile(/[\w\\\-_.]/);
82 return "variable";
83 }
84 return null;
85 }
86
87 function bracketed(level, style) {
88 return function(stream, state) {
89 var curlev = null, ch;
90 while ((ch = stream.next()) != null) {
91 if (curlev == null) {if (ch == "]") curlev = 0;}
92 else if (ch == "=") ++curlev;
93 else if (ch == "]" && curlev == level) { state.cur = normal; break; }
94 else curlev = null;
95 }
96 return style;
97 };
98 }
99
100 function string(quote) {
101 return function(stream, state) {
102 var escaped = false, ch;
103 while ((ch = stream.next()) != null) {
104 if (ch == quote && !escaped) break;
105 escaped = !escaped && ch == "\\";
106 }
107 if (!escaped) state.cur = normal;
108 return "string";
109 };
110 }
111
112 return {
113 startState: function(basecol) {
114 return {basecol: basecol || 0, indentDepth: 0, cur: normal};
115 },
116
117 token: function(stream, state) {
118 if (stream.eatSpace()) return null;
119 var style = state.cur(stream, state);
120 var word = stream.current();
121 if (style == "variable") {
122 if (keywords.test(word)) style = "keyword";
123 else if (builtins.test(word)) style = "builtin";
124 else if (specials.test(word)) style = "variable-2";
125 }
126 if ((style != "comment") && (style != "string")){
127 if (indentTokens.test(word)) ++state.indentDepth;
128 else if (dedentTokens.test(word)) --state.indentDepth;
129 }
130 return style;
131 },
132
133 indent: function(state, textAfter) {
134 var closing = dedentPartial.test(textAfter);
135 return state.basecol + indentUnit * (state.indentDepth - (closing ? 1 : 0));
136 }
137 };
138 });
139
140 CodeMirror.defineMIME("text/x-lua", "lua");
@@ -0,0 +1,41
1 <!doctype html>
2 <html>
3 <head>
4 <title>CodeMirror: MySQL mode</title>
5 <link rel="stylesheet" href="../../lib/codemirror.css">
6 <script src="../../lib/codemirror.js"></script>
7 <script src="mysql.js"></script>
8 <style>.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
9 <link rel="stylesheet" href="../../doc/docs.css">
10 </head>
11 <body>
12 <h1>CodeMirror: MySQL mode</h1>
13 <form><textarea id="code" name="code">
14 -- Comment for the code
15 -- MySQL Mode for CodeMirror2 by MySQLTools http://github.com/partydroid/MySQL-Tools
16 SELECT UNIQUE `var1` as `variable`,
17 MAX(`var5`) as `max`,
18 MIN(`var5`) as `min`,
19 STDEV(`var5`) as `dev`
20 FROM `table`
21
22 LEFT JOIN `table2` ON `var2` = `variable`
23
24 ORDER BY `var3` DESC
25 GROUP BY `groupvar`
26
27 LIMIT 0,30;
28
29 </textarea></form>
30 <script>
31 var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
32 mode: "text/x-mysql",
33 tabMode: "indent",
34 matchBrackets: true
35 });
36 </script>
37
38 <p><strong>MIME types defined:</strong> <code>text/x-mysql</code>.</p>
39
40 </body>
41 </html>
@@ -0,0 +1,186
1 /*
2 * MySQL Mode for CodeMirror 2 by MySQL-Tools
3 * @author James Thorne (partydroid)
4 * @link http://github.com/partydroid/MySQL-Tools
5 * @link http://mysqltools.org
6 * @version 02/Jan/2012
7 */
8 CodeMirror.defineMode("mysql", function(config) {
9 var indentUnit = config.indentUnit;
10 var curPunc;
11
12 function wordRegexp(words) {
13 return new RegExp("^(?:" + words.join("|") + ")$", "i");
14 }
15 var ops = wordRegexp(["str", "lang", "langmatches", "datatype", "bound", "sameterm", "isiri", "isuri",
16 "isblank", "isliteral", "union", "a"]);
17 var keywords = wordRegexp([
18 ('ACCESSIBLE'),('ALTER'),('AS'),('BEFORE'),('BINARY'),('BY'),('CASE'),('CHARACTER'),('COLUMN'),('CONTINUE'),('CROSS'),('CURRENT_TIMESTAMP'),('DATABASE'),('DAY_MICROSECOND'),('DEC'),('DEFAULT'),
19 ('DESC'),('DISTINCT'),('DOUBLE'),('EACH'),('ENCLOSED'),('EXIT'),('FETCH'),('FLOAT8'),('FOREIGN'),('GRANT'),('HIGH_PRIORITY'),('HOUR_SECOND'),('IN'),('INNER'),('INSERT'),('INT2'),('INT8'),
20 ('INTO'),('JOIN'),('KILL'),('LEFT'),('LINEAR'),('LOCALTIME'),('LONG'),('LOOP'),('MATCH'),('MEDIUMTEXT'),('MINUTE_SECOND'),('NATURAL'),('NULL'),('OPTIMIZE'),('OR'),('OUTER'),('PRIMARY'),
21 ('RANGE'),('READ_WRITE'),('REGEXP'),('REPEAT'),('RESTRICT'),('RIGHT'),('SCHEMAS'),('SENSITIVE'),('SHOW'),('SPECIFIC'),('SQLSTATE'),('SQL_CALC_FOUND_ROWS'),('STARTING'),('TERMINATED'),
22 ('TINYINT'),('TRAILING'),('UNDO'),('UNLOCK'),('USAGE'),('UTC_DATE'),('VALUES'),('VARCHARACTER'),('WHERE'),('WRITE'),('ZEROFILL'),('ALL'),('AND'),('ASENSITIVE'),('BIGINT'),('BOTH'),('CASCADE'),
23 ('CHAR'),('COLLATE'),('CONSTRAINT'),('CREATE'),('CURRENT_TIME'),('CURSOR'),('DAY_HOUR'),('DAY_SECOND'),('DECLARE'),('DELETE'),('DETERMINISTIC'),('DIV'),('DUAL'),('ELSEIF'),('EXISTS'),('FALSE'),
24 ('FLOAT4'),('FORCE'),('FULLTEXT'),('HAVING'),('HOUR_MINUTE'),('IGNORE'),('INFILE'),('INSENSITIVE'),('INT1'),('INT4'),('INTERVAL'),('ITERATE'),('KEYS'),('LEAVE'),('LIMIT'),('LOAD'),('LOCK'),
25 ('LONGTEXT'),('MASTER_SSL_VERIFY_SERVER_CERT'),('MEDIUMINT'),('MINUTE_MICROSECOND'),('MODIFIES'),('NO_WRITE_TO_BINLOG'),('ON'),('OPTIONALLY'),('OUT'),('PRECISION'),('PURGE'),('READS'),
26 ('REFERENCES'),('RENAME'),('REQUIRE'),('REVOKE'),('SCHEMA'),('SELECT'),('SET'),('SPATIAL'),('SQLEXCEPTION'),('SQL_BIG_RESULT'),('SSL'),('TABLE'),('TINYBLOB'),('TO'),('TRUE'),('UNIQUE'),
27 ('UPDATE'),('USING'),('UTC_TIMESTAMP'),('VARCHAR'),('WHEN'),('WITH'),('YEAR_MONTH'),('ADD'),('ANALYZE'),('ASC'),('BETWEEN'),('BLOB'),('CALL'),('CHANGE'),('CHECK'),('CONDITION'),('CONVERT'),
28 ('CURRENT_DATE'),('CURRENT_USER'),('DATABASES'),('DAY_MINUTE'),('DECIMAL'),('DELAYED'),('DESCRIBE'),('DISTINCTROW'),('DROP'),('ELSE'),('ESCAPED'),('EXPLAIN'),('FLOAT'),('FOR'),('FROM'),
29 ('GROUP'),('HOUR_MICROSECOND'),('IF'),('INDEX'),('INOUT'),('INT'),('INT3'),('INTEGER'),('IS'),('KEY'),('LEADING'),('LIKE'),('LINES'),('LOCALTIMESTAMP'),('LONGBLOB'),('LOW_PRIORITY'),
30 ('MEDIUMBLOB'),('MIDDLEINT'),('MOD'),('NOT'),('NUMERIC'),('OPTION'),('ORDER'),('OUTFILE'),('PROCEDURE'),('READ'),('REAL'),('RELEASE'),('REPLACE'),('RETURN'),('RLIKE'),('SECOND_MICROSECOND'),
31 ('SEPARATOR'),('SMALLINT'),('SQL'),('SQLWARNING'),('SQL_SMALL_RESULT'),('STRAIGHT_JOIN'),('THEN'),('TINYTEXT'),('TRIGGER'),('UNION'),('UNSIGNED'),('USE'),('UTC_TIME'),('VARBINARY'),('VARYING'),
32 ('WHILE'),('XOR'),('FULL'),('COLUMNS'),('MIN'),('MAX'),('STDEV'),('COUNT')
33 ]);
34 var operatorChars = /[*+\-<>=&|]/;
35
36 function tokenBase(stream, state) {
37 var ch = stream.next();
38 curPunc = null;
39 if (ch == "$" || ch == "?") {
40 stream.match(/^[\w\d]*/);
41 return "variable-2";
42 }
43 else if (ch == "<" && !stream.match(/^[\s\u00a0=]/, false)) {
44 stream.match(/^[^\s\u00a0>]*>?/);
45 return "atom";
46 }
47 else if (ch == "\"" || ch == "'") {
48 state.tokenize = tokenLiteral(ch);
49 return state.tokenize(stream, state);
50 }
51 else if (ch == "`") {
52 state.tokenize = tokenOpLiteral(ch);
53 return state.tokenize(stream, state);
54 }
55 else if (/[{}\(\),\.;\[\]]/.test(ch)) {
56 curPunc = ch;
57 return null;
58 }
59 else if (ch == "-") {
60 var ch2 = stream.next();
61 if (ch2=="-") {
62 stream.skipToEnd();
63 return "comment";
64 }
65 }
66 else if (operatorChars.test(ch)) {
67 stream.eatWhile(operatorChars);
68 return null;
69 }
70 else if (ch == ":") {
71 stream.eatWhile(/[\w\d\._\-]/);
72 return "atom";
73 }
74 else {
75 stream.eatWhile(/[_\w\d]/);
76 if (stream.eat(":")) {
77 stream.eatWhile(/[\w\d_\-]/);
78 return "atom";
79 }
80 var word = stream.current(), type;
81 if (ops.test(word))
82 return null;
83 else if (keywords.test(word))
84 return "keyword";
85 else
86 return "variable";
87 }
88 }
89
90 function tokenLiteral(quote) {
91 return function(stream, state) {
92 var escaped = false, ch;
93 while ((ch = stream.next()) != null) {
94 if (ch == quote && !escaped) {
95 state.tokenize = tokenBase;
96 break;
97 }
98 escaped = !escaped && ch == "\\";
99 }
100 return "string";
101 };
102 }
103
104 function tokenOpLiteral(quote) {
105 return function(stream, state) {
106 var escaped = false, ch;
107 while ((ch = stream.next()) != null) {
108 if (ch == quote && !escaped) {
109 state.tokenize = tokenBase;
110 break;
111 }
112 escaped = !escaped && ch == "\\";
113 }
114 return "variable-2";
115 };
116 }
117
118
119 function pushContext(state, type, col) {
120 state.context = {prev: state.context, indent: state.indent, col: col, type: type};
121 }
122 function popContext(state) {
123 state.indent = state.context.indent;
124 state.context = state.context.prev;
125 }
126
127 return {
128 startState: function(base) {
129 return {tokenize: tokenBase,
130 context: null,
131 indent: 0,
132 col: 0};
133 },
134
135 token: function(stream, state) {
136 if (stream.sol()) {
137 if (state.context && state.context.align == null) state.context.align = false;
138 state.indent = stream.indentation();
139 }
140 if (stream.eatSpace()) return null;
141 var style = state.tokenize(stream, state);
142
143 if (style != "comment" && state.context && state.context.align == null && state.context.type != "pattern") {
144 state.context.align = true;
145 }
146
147 if (curPunc == "(") pushContext(state, ")", stream.column());
148 else if (curPunc == "[") pushContext(state, "]", stream.column());
149 else if (curPunc == "{") pushContext(state, "}", stream.column());
150 else if (/[\]\}\)]/.test(curPunc)) {
151 while (state.context && state.context.type == "pattern") popContext(state);
152 if (state.context && curPunc == state.context.type) popContext(state);
153 }
154 else if (curPunc == "." && state.context && state.context.type == "pattern") popContext(state);
155 else if (/atom|string|variable/.test(style) && state.context) {
156 if (/[\}\]]/.test(state.context.type))
157 pushContext(state, "pattern", stream.column());
158 else if (state.context.type == "pattern" && !state.context.align) {
159 state.context.align = true;
160 state.context.col = stream.column();
161 }
162 }
163
164 return style;
165 },
166
167 indent: function(state, textAfter) {
168 var firstChar = textAfter && textAfter.charAt(0);
169 var context = state.context;
170 if (/[\]\}]/.test(firstChar))
171 while (context && context.type == "pattern") context = context.prev;
172
173 var closing = context && firstChar == context.type;
174 if (!context)
175 return 0;
176 else if (context.type == "pattern")
177 return context.col;
178 else if (context.align)
179 return context.col + (closing ? 0 : 1);
180 else
181 return context.indent + (closing ? 0 : indentUnit);
182 }
183 };
184 });
185
186 CodeMirror.defineMIME("text/x-mysql", "mysql");
@@ -0,0 +1,32
1 <!doctype html>
2 <html>
3 <head>
4 <title>CodeMirror: NTriples mode</title>
5 <link rel="stylesheet" href="../../lib/codemirror.css">
6 <script src="../../lib/codemirror.js"></script>
7 <script src="ntriples.js"></script>
8 <link rel="stylesheet" href="../../doc/docs.css">
9 <style type="text/css">
10 .CodeMirror {
11 border: 1px solid #eee;
12 }
13 </style>
14 </head>
15 <body>
16 <h1>CodeMirror: NTriples mode</h1>
17 <form>
18 <textarea id="ntriples" name="ntriples">
19 <http://Sub1> <http://pred1> <http://obj> .
20 <http://Sub2> <http://pred2#an2> "literal 1" .
21 <http://Sub3#an3> <http://pred3> _:bnode3 .
22 _:bnode4 <http://pred4> "literal 2"@lang .
23 _:bnode5 <http://pred5> "literal 3"^^<http://type> .
24 </textarea>
25 </form>
26
27 <script>
28 var editor = CodeMirror.fromTextArea(document.getElementById("ntriples"), {});
29 </script>
30 <p><strong>MIME types defined:</strong> <code>text/n-triples</code>.</p>
31 </body>
32 </html>
@@ -0,0 +1,172
1 /**********************************************************
2 * This script provides syntax highlighting support for
3 * the Ntriples format.
4 * Ntriples format specification:
5 * http://www.w3.org/TR/rdf-testcases/#ntriples
6 ***********************************************************/
7
8 /*
9 The following expression defines the defined ASF grammar transitions.
10
11 pre_subject ->
12 {
13 ( writing_subject_uri | writing_bnode_uri )
14 -> pre_predicate
15 -> writing_predicate_uri
16 -> pre_object
17 -> writing_object_uri | writing_object_bnode |
18 (
19 writing_object_literal
20 -> writing_literal_lang | writing_literal_type
21 )
22 -> post_object
23 -> BEGIN
24 } otherwise {
25 -> ERROR
26 }
27 */
28 CodeMirror.defineMode("ntriples", function() {
29
30 Location = {
31 PRE_SUBJECT : 0,
32 WRITING_SUB_URI : 1,
33 WRITING_BNODE_URI : 2,
34 PRE_PRED : 3,
35 WRITING_PRED_URI : 4,
36 PRE_OBJ : 5,
37 WRITING_OBJ_URI : 6,
38 WRITING_OBJ_BNODE : 7,
39 WRITING_OBJ_LITERAL : 8,
40 WRITING_LIT_LANG : 9,
41 WRITING_LIT_TYPE : 10,
42 POST_OBJ : 11,
43 ERROR : 12
44 };
45 function transitState(currState, c) {
46 var currLocation = currState.location;
47 var ret;
48
49 // Opening.
50 if (currLocation == Location.PRE_SUBJECT && c == '<') ret = Location.WRITING_SUB_URI;
51 else if(currLocation == Location.PRE_SUBJECT && c == '_') ret = Location.WRITING_BNODE_URI;
52 else if(currLocation == Location.PRE_PRED && c == '<') ret = Location.WRITING_PRED_URI;
53 else if(currLocation == Location.PRE_OBJ && c == '<') ret = Location.WRITING_OBJ_URI;
54 else if(currLocation == Location.PRE_OBJ && c == '_') ret = Location.WRITING_OBJ_BNODE;
55 else if(currLocation == Location.PRE_OBJ && c == '"') ret = Location.WRITING_OBJ_LITERAL;
56
57 // Closing.
58 else if(currLocation == Location.WRITING_SUB_URI && c == '>') ret = Location.PRE_PRED;
59 else if(currLocation == Location.WRITING_BNODE_URI && c == ' ') ret = Location.PRE_PRED;
60 else if(currLocation == Location.WRITING_PRED_URI && c == '>') ret = Location.PRE_OBJ;
61 else if(currLocation == Location.WRITING_OBJ_URI && c == '>') ret = Location.POST_OBJ;
62 else if(currLocation == Location.WRITING_OBJ_BNODE && c == ' ') ret = Location.POST_OBJ;
63 else if(currLocation == Location.WRITING_OBJ_LITERAL && c == '"') ret = Location.POST_OBJ;
64 else if(currLocation == Location.WRITING_LIT_LANG && c == ' ') ret = Location.POST_OBJ;
65 else if(currLocation == Location.WRITING_LIT_TYPE && c == '>') ret = Location.POST_OBJ;
66
67 // Closing typed and language literal.
68 else if(currLocation == Location.WRITING_OBJ_LITERAL && c == '@') ret = Location.WRITING_LIT_LANG;
69 else if(currLocation == Location.WRITING_OBJ_LITERAL && c == '^') ret = Location.WRITING_LIT_TYPE;
70
71 // Spaces.
72 else if( c == ' ' &&
73 (
74 currLocation == Location.PRE_SUBJECT ||
75 currLocation == Location.PRE_PRED ||
76 currLocation == Location.PRE_OBJ ||
77 currLocation == Location.POST_OBJ
78 )
79 ) ret = currLocation;
80
81 // Reset.
82 else if(currLocation == Location.POST_OBJ && c == '.') ret = Location.PRE_SUBJECT;
83
84 // Error
85 else ret = Location.ERROR;
86
87 currState.location=ret;
88 }
89
90 untilSpace = function(c) { return c != ' '; };
91 untilEndURI = function(c) { return c != '>'; };
92 return {
93 startState: function() {
94 return {
95 location : Location.PRE_SUBJECT,
96 uris : [],
97 anchors : [],
98 bnodes : [],
99 langs : [],
100 types : []
101 };
102 },
103 token: function(stream, state) {
104 var ch = stream.next();
105 if(ch == '<') {
106 transitState(state, ch);
107 var parsedURI = '';
108 stream.eatWhile( function(c) { if( c != '#' && c != '>' ) { parsedURI += c; return true; } return false;} );
109 state.uris.push(parsedURI);
110 if( stream.match('#', false) ) return 'variable';
111 stream.next();
112 transitState(state, '>');
113 return 'variable';
114 }
115 if(ch == '#') {
116 var parsedAnchor = '';
117 stream.eatWhile(function(c) { if(c != '>' && c != ' ') { parsedAnchor+= c; return true; } return false});
118 state.anchors.push(parsedAnchor);
119 return 'variable-2';
120 }
121 if(ch == '>') {
122 transitState(state, '>');
123 return 'variable';
124 }
125 if(ch == '_') {
126 transitState(state, ch);
127 var parsedBNode = '';
128 stream.eatWhile(function(c) { if( c != ' ' ) { parsedBNode += c; return true; } return false;});
129 state.bnodes.push(parsedBNode);
130 stream.next();
131 transitState(state, ' ');
132 return 'builtin';
133 }
134 if(ch == '"') {
135 transitState(state, ch);
136 stream.eatWhile( function(c) { return c != '"'; } );
137 stream.next();
138 if( stream.peek() != '@' && stream.peek() != '^' ) {
139 transitState(state, '"');
140 }
141 return 'string';
142 }
143 if( ch == '@' ) {
144 transitState(state, '@');
145 var parsedLang = '';
146 stream.eatWhile(function(c) { if( c != ' ' ) { parsedLang += c; return true; } return false;});
147 state.langs.push(parsedLang);
148 stream.next();
149 transitState(state, ' ');
150 return 'string-2';
151 }
152 if( ch == '^' ) {
153 stream.next();
154 transitState(state, '^');
155 var parsedType = '';
156 stream.eatWhile(function(c) { if( c != '>' ) { parsedType += c; return true; } return false;} );
157 state.types.push(parsedType);
158 stream.next();
159 transitState(state, '>');
160 return 'variable';
161 }
162 if( ch == ' ' ) {
163 transitState(state, ch);
164 }
165 if( ch == '.' ) {
166 transitState(state, ch);
167 }
168 }
169 };
170 });
171
172 CodeMirror.defineMIME("text/n-triples", "ntriples");
@@ -0,0 +1,130
1 <!doctype html>
2 <meta charset=utf-8>
3 <title>CodeMirror: OCaml mode</title>
4
5 <link rel=stylesheet href=../../lib/codemirror.css>
6 <link rel=stylesheet href=../../doc/docs.css>
7
8 <style type=text/css>
9 .CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}
10 </style>
11
12 <script src=../../lib/codemirror.js></script>
13 <script src=ocaml.js></script>
14
15 <h1>CodeMirror: OCaml mode</h1>
16
17 <textarea id=code>
18 (* Summing a list of integers *)
19 let rec sum xs =
20 match xs with
21 | [] -&gt; 0
22 | x :: xs' -&gt; x + sum xs'
23
24 (* Quicksort *)
25 let rec qsort = function
26 | [] -&gt; []
27 | pivot :: rest -&gt;
28 let is_less x = x &lt; pivot in
29 let left, right = List.partition is_less rest in
30 qsort left @ [pivot] @ qsort right
31
32 (* Fibonacci Sequence *)
33 let rec fib_aux n a b =
34 match n with
35 | 0 -&gt; a
36 | _ -&gt; fib_aux (n - 1) (a + b) a
37 let fib n = fib_aux n 0 1
38
39 (* Birthday paradox *)
40 let year_size = 365.
41
42 let rec birthday_paradox prob people =
43 let prob' = (year_size -. float people) /. year_size *. prob in
44 if prob' &lt; 0.5 then
45 Printf.printf "answer = %d\n" (people+1)
46 else
47 birthday_paradox prob' (people+1) ;;
48
49 birthday_paradox 1.0 1
50
51 (* Church numerals *)
52 let zero f x = x
53 let succ n f x = f (n f x)
54 let one = succ zero
55 let two = succ (succ zero)
56 let add n1 n2 f x = n1 f (n2 f x)
57 let to_string n = n (fun k -&gt; "S" ^ k) "0"
58 let _ = to_string (add (succ two) two)
59
60 (* Elementary functions *)
61 let square x = x * x;;
62 let rec fact x =
63 if x &lt;= 1 then 1 else x * fact (x - 1);;
64
65 (* Automatic memory management *)
66 let l = 1 :: 2 :: 3 :: [];;
67 [1; 2; 3];;
68 5 :: l;;
69
70 (* Polymorphism: sorting lists *)
71 let rec sort = function
72 | [] -&gt; []
73 | x :: l -&gt; insert x (sort l)
74
75 and insert elem = function
76 | [] -&gt; [elem]
77 | x :: l -&gt;
78 if elem &lt; x then elem :: x :: l else x :: insert elem l;;
79
80 (* Imperative features *)
81 let add_polynom p1 p2 =
82 let n1 = Array.length p1
83 and n2 = Array.length p2 in
84 let result = Array.create (max n1 n2) 0 in
85 for i = 0 to n1 - 1 do result.(i) &lt;- p1.(i) done;
86 for i = 0 to n2 - 1 do result.(i) &lt;- result.(i) + p2.(i) done;
87 result;;
88 add_polynom [| 1; 2 |] [| 1; 2; 3 |];;
89
90 (* We may redefine fact using a reference cell and a for loop *)
91 let fact n =
92 let result = ref 1 in
93 for i = 2 to n do
94 result := i * !result
95 done;
96 !result;;
97 fact 5;;
98
99 (* Triangle (graphics) *)
100 let () =
101 ignore( Glut.init Sys.argv );
102 Glut.initDisplayMode ~double_buffer:true ();
103 ignore (Glut.createWindow ~title:"OpenGL Demo");
104 let angle t = 10. *. t *. t in
105 let render () =
106 GlClear.clear [ `color ];
107 GlMat.load_identity ();
108 GlMat.rotate ~angle: (angle (Sys.time ())) ~z:1. ();
109 GlDraw.begins `triangles;
110 List.iter GlDraw.vertex2 [-1., -1.; 0., 1.; 1., -1.];
111 GlDraw.ends ();
112 Glut.swapBuffers () in
113 GlMat.mode `modelview;
114 Glut.displayFunc ~cb:render;
115 Glut.idleFunc ~cb:(Some Glut.postRedisplay);
116 Glut.mainLoop ()
117
118 (* A Hundred Lines of Caml - http://caml.inria.fr/about/taste.en.html *)
119 (* OCaml page on Wikipedia - http://en.wikipedia.org/wiki/OCaml *)
120 </textarea>
121
122 <script>
123 var editor = CodeMirror.fromTextArea(document.getElementById('code'), {
124 mode: 'ocaml',
125 lineNumbers: true,
126 matchBrackets: true
127 });
128 </script>
129
130 <p><strong>MIME types defined:</strong> <code>text/x-ocaml</code>.</p>
@@ -0,0 +1,114
1 CodeMirror.defineMode('ocaml', function(config) {
2
3 var words = {
4 'true': 'atom',
5 'false': 'atom',
6 'let': 'keyword',
7 'rec': 'keyword',
8 'in': 'keyword',
9 'of': 'keyword',
10 'and': 'keyword',
11 'succ': 'keyword',
12 'if': 'keyword',
13 'then': 'keyword',
14 'else': 'keyword',
15 'for': 'keyword',
16 'to': 'keyword',
17 'while': 'keyword',
18 'do': 'keyword',
19 'done': 'keyword',
20 'fun': 'keyword',
21 'function': 'keyword',
22 'val': 'keyword',
23 'type': 'keyword',
24 'mutable': 'keyword',
25 'match': 'keyword',
26 'with': 'keyword',
27 'try': 'keyword',
28 'raise': 'keyword',
29 'begin': 'keyword',
30 'end': 'keyword',
31 'open': 'builtin',
32 'trace': 'builtin',
33 'ignore': 'builtin',
34 'exit': 'builtin',
35 'print_string': 'builtin',
36 'print_endline': 'builtin'
37 };
38
39 function tokenBase(stream, state) {
40 var sol = stream.sol();
41 var ch = stream.next();
42
43 if (ch === '"') {
44 state.tokenize = tokenString;
45 return state.tokenize(stream, state);
46 }
47 if (ch === '(') {
48 if (stream.eat('*')) {
49 state.commentLevel++;
50 state.tokenize = tokenComment;
51 return state.tokenize(stream, state);
52 }
53 }
54 if (ch === '~') {
55 stream.eatWhile(/\w/);
56 return 'variable-2';
57 }
58 if (ch === '`') {
59 stream.eatWhile(/\w/);
60 return 'quote';
61 }
62 if (/\d/.test(ch)) {
63 stream.eatWhile(/[\d]/);
64 if (stream.eat('.')) {
65 stream.eatWhile(/[\d]/);
66 }
67 return 'number';
68 }
69 if ( /[+\-*&%=<>!?|]/.test(ch)) {
70 return 'operator';
71 }
72 stream.eatWhile(/\w/);
73 var cur = stream.current();
74 return words[cur] || 'variable';
75 }
76
77 function tokenString(stream, state) {
78 var next, end = false, escaped = false;
79 while ((next = stream.next()) != null) {
80 if (next === '"' && !escaped) {
81 end = true;
82 break;
83 }
84 escaped = !escaped && next === '\\';
85 }
86 if (end && !escaped) {
87 state.tokenize = tokenBase;
88 }
89 return 'string';
90 };
91
92 function tokenComment(stream, state) {
93 var prev, next;
94 while(state.commentLevel > 0 && (next = stream.next()) != null) {
95 if (prev === '(' && next === '*') state.commentLevel++;
96 if (prev === '*' && next === ')') state.commentLevel--;
97 prev = next;
98 }
99 if (state.commentLevel <= 0) {
100 state.tokenize = tokenBase;
101 }
102 return 'comment';
103 }
104
105 return {
106 startState: function() {return {tokenize: tokenBase, commentLevel: 0}},
107 token: function(stream, state) {
108 if (stream.eatSpace()) return null;
109 return state.tokenize(stream, state);
110 }
111 };
112 });
113
114 CodeMirror.defineMIME('text/x-ocaml', 'ocaml');
@@ -0,0 +1,7
1 Copyright (c) 2011 souceLair <support@sourcelair.com>
2
3 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
5 The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
7 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,48
1 <!doctype html>
2 <html>
3 <head>
4 <title>CodeMirror: Pascal mode</title>
5 <link rel="stylesheet" href="../../lib/codemirror.css">
6 <script src="../../lib/codemirror.js"></script>
7 <script src="pascal.js"></script>
8 <link rel="stylesheet" href="../../doc/docs.css">
9 <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
10 </head>
11 <body>
12 <h1>CodeMirror: Pascal mode</h1>
13
14 <div><textarea id="code" name="code">
15 (* Example Pascal code *)
16
17 while a <> b do writeln('Waiting');
18
19 if a > b then
20 writeln('Condition met')
21 else
22 writeln('Condition not met');
23
24 for i := 1 to 10 do
25 writeln('Iteration: ', i:1);
26
27 repeat
28 a := a + 1
29 until a = 10;
30
31 case i of
32 0: write('zero');
33 1: write('one');
34 2: write('two')
35 end;
36 </textarea></div>
37
38 <script>
39 var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
40 lineNumbers: true,
41 matchBrackets: true,
42 mode: "text/x-pascal"
43 });
44 </script>
45
46 <p><strong>MIME types defined:</strong> <code>text/x-pascal</code>.</p>
47 </body>
48 </html>
@@ -0,0 +1,94
1 CodeMirror.defineMode("pascal", function(config) {
2 function words(str) {
3 var obj = {}, words = str.split(" ");
4 for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
5 return obj;
6 }
7 var keywords = words("and array begin case const div do downto else end file for forward integer " +
8 "boolean char function goto if in label mod nil not of or packed procedure " +
9 "program record repeat set string then to type until var while with");
10 var atoms = {"null": true};
11
12 var isOperatorChar = /[+\-*&%=<>!?|\/]/;
13
14 function tokenBase(stream, state) {
15 var ch = stream.next();
16 if (ch == "#" && state.startOfLine) {
17 stream.skipToEnd();
18 return "meta";
19 }
20 if (ch == '"' || ch == "'") {
21 state.tokenize = tokenString(ch);
22 return state.tokenize(stream, state);
23 }
24 if (ch == "(" && stream.eat("*")) {
25 state.tokenize = tokenComment;
26 return tokenComment(stream, state);
27 }
28 if (/[\[\]{}\(\),;\:\.]/.test(ch)) {
29 return null
30 }
31 if (/\d/.test(ch)) {
32 stream.eatWhile(/[\w\.]/);
33 return "number";
34 }
35 if (ch == "/") {
36 if (stream.eat("/")) {
37 stream.skipToEnd();
38 return "comment";
39 }
40 }
41 if (isOperatorChar.test(ch)) {
42 stream.eatWhile(isOperatorChar);
43 return "operator";
44 }
45 stream.eatWhile(/[\w\$_]/);
46 var cur = stream.current();
47 if (keywords.propertyIsEnumerable(cur)) return "keyword";
48 if (atoms.propertyIsEnumerable(cur)) return "atom";
49 return "variable";
50 }
51
52 function tokenString(quote) {
53 return function(stream, state) {
54 var escaped = false, next, end = false;
55 while ((next = stream.next()) != null) {
56 if (next == quote && !escaped) {end = true; break;}
57 escaped = !escaped && next == "\\";
58 }
59 if (end || !escaped) state.tokenize = null;
60 return "string";
61 };
62 }
63
64 function tokenComment(stream, state) {
65 var maybeEnd = false, ch;
66 while (ch = stream.next()) {
67 if (ch == ")" && maybeEnd) {
68 state.tokenize = null;
69 break;
70 }
71 maybeEnd = (ch == "*");
72 }
73 return "comment";
74 }
75
76 // Interface
77
78 return {
79 startState: function(basecolumn) {
80 return {tokenize: null};
81 },
82
83 token: function(stream, state) {
84 if (stream.eatSpace()) return null;
85 var style = (state.tokenize || tokenBase)(stream, state);
86 if (style == "comment" || style == "meta") return style;
87 return style;
88 },
89
90 electricChars: "{}"
91 };
92 });
93
94 CodeMirror.defineMIME("text/x-pascal", "pascal");
@@ -0,0 +1,19
1 Copyright (C) 2011 by Sabaca <mail@sabaca.com> under the MIT license.
2
3 Permission is hereby granted, free of charge, to any person obtaining a copy
4 of this software and associated documentation files (the "Software"), to deal
5 in the Software without restriction, including without limitation the rights
6 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 copies of the Software, and to permit persons to whom the Software is
8 furnished to do so, subject to the following conditions:
9
10 The above copyright notice and this permission notice shall be included in
11 all copies or substantial portions of the Software.
12
13 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 THE SOFTWARE.
@@ -0,0 +1,62
1 <!doctype html>
2 <html>
3 <head>
4 <title>CodeMirror: Perl mode</title>
5 <link rel="stylesheet" href="../../lib/codemirror.css">
6 <script src="../../lib/codemirror.js"></script>
7 <script src="perl.js"></script>
8 <link rel="stylesheet" href="../../doc/docs.css">
9 <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
10 </head>
11 <body>
12 <h1>CodeMirror: Perl mode</h1>
13
14 <div><textarea id="code" name="code">
15 #!/usr/bin/perl
16
17 use Something qw(func1 func2);
18
19 # strings
20 my $s1 = qq'single line';
21 our $s2 = q(multi-
22 line);
23
24 =item Something
25 Example.
26 =cut
27
28 my $html=<<'HTML'
29 <html>
30 <title>hi!</title>
31 </html>
32 HTML
33
34 print "first,".join(',', 'second', qq~third~);
35
36 if($s1 =~ m[(?<!\s)(l.ne)\z]o) {
37 $h->{$1}=$$.' predefined variables';
38 $s2 =~ s/\-line//ox;
39 $s1 =~ s[
40 line ]
41 [
42 block
43 ]ox;
44 }
45
46 1; # numbers and comments
47
48 __END__
49 something...
50
51 </textarea></div>
52
53 <script>
54 var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
55 lineNumbers: true,
56 matchBrackets: true
57 });
58 </script>
59
60 <p><strong>MIME types defined:</strong> <code>text/x-perl</code>.</p>
61 </body>
62 </html>
This diff has been collapsed as it changes many lines, (816 lines changed) Show them Hide them
@@ -0,0 +1,816
1 // CodeMirror2 mode/perl/perl.js (text/x-perl) beta 0.10 (2011-11-08)
2 // This is a part of CodeMirror from https://github.com/sabaca/CodeMirror_mode_perl (mail@sabaca.com)
3 CodeMirror.defineMode("perl",function(config,parserConfig){
4 // http://perldoc.perl.org
5 var PERL={ // null - magic touch
6 // 1 - keyword
7 // 2 - def
8 // 3 - atom
9 // 4 - operator
10 // 5 - variable-2 (predefined)
11 // [x,y] - x=1,2,3; y=must be defined if x{...}
12 // PERL operators
13 '->' : 4,
14 '++' : 4,
15 '--' : 4,
16 '**' : 4,
17 // ! ~ \ and unary + and -
18 '=~' : 4,
19 '!~' : 4,
20 '*' : 4,
21 '/' : 4,
22 '%' : 4,
23 'x' : 4,
24 '+' : 4,
25 '-' : 4,
26 '.' : 4,
27 '<<' : 4,
28 '>>' : 4,
29 // named unary operators
30 '<' : 4,
31 '>' : 4,
32 '<=' : 4,
33 '>=' : 4,
34 'lt' : 4,
35 'gt' : 4,
36 'le' : 4,
37 'ge' : 4,
38 '==' : 4,
39 '!=' : 4,
40 '<=>' : 4,
41 'eq' : 4,
42 'ne' : 4,
43 'cmp' : 4,
44 '~~' : 4,
45 '&' : 4,
46 '|' : 4,
47 '^' : 4,
48 '&&' : 4,
49 '||' : 4,
50 '//' : 4,
51 '..' : 4,
52 '...' : 4,
53 '?' : 4,
54 ':' : 4,
55 '=' : 4,
56 '+=' : 4,
57 '-=' : 4,
58 '*=' : 4, // etc. ???
59 ',' : 4,
60 '=>' : 4,
61 '::' : 4,
62 // list operators (rightward)
63 'not' : 4,
64 'and' : 4,
65 'or' : 4,
66 'xor' : 4,
67 // PERL predefined variables (I know, what this is a paranoid idea, but may be needed for people, who learn PERL, and for me as well, ...and may be for you?;)
68 'BEGIN' : [5,1],
69 'END' : [5,1],
70 'PRINT' : [5,1],
71 'PRINTF' : [5,1],
72 'GETC' : [5,1],
73 'READ' : [5,1],
74 'READLINE' : [5,1],
75 'DESTROY' : [5,1],
76 'TIE' : [5,1],
77 'TIEHANDLE' : [5,1],
78 'UNTIE' : [5,1],
79 'STDIN' : 5,
80 'STDIN_TOP' : 5,
81 'STDOUT' : 5,
82 'STDOUT_TOP' : 5,
83 'STDERR' : 5,
84 'STDERR_TOP' : 5,
85 '$ARG' : 5,
86 '$_' : 5,
87 '@ARG' : 5,
88 '@_' : 5,
89 '$LIST_SEPARATOR' : 5,
90 '$"' : 5,
91 '$PROCESS_ID' : 5,
92 '$PID' : 5,
93 '$$' : 5,
94 '$REAL_GROUP_ID' : 5,
95 '$GID' : 5,
96 '$(' : 5,
97 '$EFFECTIVE_GROUP_ID' : 5,
98 '$EGID' : 5,
99 '$)' : 5,
100 '$PROGRAM_NAME' : 5,
101 '$0' : 5,
102 '$SUBSCRIPT_SEPARATOR' : 5,
103 '$SUBSEP' : 5,
104 '$;' : 5,
105 '$REAL_USER_ID' : 5,
106 '$UID' : 5,
107 '$<' : 5,
108 '$EFFECTIVE_USER_ID' : 5,
109 '$EUID' : 5,
110 '$>' : 5,
111 '$a' : 5,
112 '$b' : 5,
113 '$COMPILING' : 5,
114 '$^C' : 5,
115 '$DEBUGGING' : 5,
116 '$^D' : 5,
117 '${^ENCODING}' : 5,
118 '$ENV' : 5,
119 '%ENV' : 5,
120 '$SYSTEM_FD_MAX' : 5,
121 '$^F' : 5,
122 '@F' : 5,
123 '${^GLOBAL_PHASE}' : 5,
124 '$^H' : 5,
125 '%^H' : 5,
126 '@INC' : 5,
127 '%INC' : 5,
128 '$INPLACE_EDIT' : 5,
129 '$^I' : 5,
130 '$^M' : 5,
131 '$OSNAME' : 5,
132 '$^O' : 5,
133 '${^OPEN}' : 5,
134 '$PERLDB' : 5,
135 '$^P' : 5,
136 '$SIG' : 5,
137 '%SIG' : 5,
138 '$BASETIME' : 5,
139 '$^T' : 5,
140 '${^TAINT}' : 5,
141 '${^UNICODE}' : 5,
142 '${^UTF8CACHE}' : 5,
143 '${^UTF8LOCALE}' : 5,
144 '$PERL_VERSION' : 5,
145 '$^V' : 5,
146 '${^WIN32_SLOPPY_STAT}' : 5,
147 '$EXECUTABLE_NAME' : 5,
148 '$^X' : 5,
149 '$1' : 5, // - regexp $1, $2...
150 '$MATCH' : 5,
151 '$&' : 5,
152 '${^MATCH}' : 5,
153 '$PREMATCH' : 5,
154 '$`' : 5,
155 '${^PREMATCH}' : 5,
156 '$POSTMATCH' : 5,
157 "$'" : 5,
158 '${^POSTMATCH}' : 5,
159 '$LAST_PAREN_MATCH' : 5,
160 '$+' : 5,
161 '$LAST_SUBMATCH_RESULT' : 5,
162 '$^N' : 5,
163 '@LAST_MATCH_END' : 5,
164 '@+' : 5,
165 '%LAST_PAREN_MATCH' : 5,
166 '%+' : 5,
167 '@LAST_MATCH_START' : 5,
168 '@-' : 5,
169 '%LAST_MATCH_START' : 5,
170 '%-' : 5,
171 '$LAST_REGEXP_CODE_RESULT' : 5,
172 '$^R' : 5,
173 '${^RE_DEBUG_FLAGS}' : 5,
174 '${^RE_TRIE_MAXBUF}' : 5,
175 '$ARGV' : 5,
176 '@ARGV' : 5,
177 'ARGV' : 5,
178 'ARGVOUT' : 5,
179 '$OUTPUT_FIELD_SEPARATOR' : 5,
180 '$OFS' : 5,
181 '$,' : 5,
182 '$INPUT_LINE_NUMBER' : 5,
183 '$NR' : 5,
184 '$.' : 5,
185 '$INPUT_RECORD_SEPARATOR' : 5,
186 '$RS' : 5,
187 '$/' : 5,
188 '$OUTPUT_RECORD_SEPARATOR' : 5,
189 '$ORS' : 5,
190 '$\\' : 5,
191 '$OUTPUT_AUTOFLUSH' : 5,
192 '$|' : 5,
193 '$ACCUMULATOR' : 5,
194 '$^A' : 5,
195 '$FORMAT_FORMFEED' : 5,
196 '$^L' : 5,
197 '$FORMAT_PAGE_NUMBER' : 5,
198 '$%' : 5,
199 '$FORMAT_LINES_LEFT' : 5,
200 '$-' : 5,
201 '$FORMAT_LINE_BREAK_CHARACTERS' : 5,
202 '$:' : 5,
203 '$FORMAT_LINES_PER_PAGE' : 5,
204 '$=' : 5,
205 '$FORMAT_TOP_NAME' : 5,
206 '$^' : 5,
207 '$FORMAT_NAME' : 5,
208 '$~' : 5,
209 '${^CHILD_ERROR_NATIVE}' : 5,
210 '$EXTENDED_OS_ERROR' : 5,
211 '$^E' : 5,
212 '$EXCEPTIONS_BEING_CAUGHT' : 5,
213 '$^S' : 5,
214 '$WARNING' : 5,
215 '$^W' : 5,
216 '${^WARNING_BITS}' : 5,
217 '$OS_ERROR' : 5,
218 '$ERRNO' : 5,
219 '$!' : 5,
220 '%OS_ERROR' : 5,
221 '%ERRNO' : 5,
222 '%!' : 5,
223 '$CHILD_ERROR' : 5,
224 '$?' : 5,
225 '$EVAL_ERROR' : 5,
226 '$@' : 5,
227 '$OFMT' : 5,
228 '$#' : 5,
229 '$*' : 5,
230 '$ARRAY_BASE' : 5,
231 '$[' : 5,
232 '$OLD_PERL_VERSION' : 5,
233 '$]' : 5,
234 // PERL blocks
235 'if' :[1,1],
236 elsif :[1,1],
237 'else' :[1,1],
238 'while' :[1,1],
239 unless :[1,1],
240 'for' :[1,1],
241 foreach :[1,1],
242 // PERL functions
243 'abs' :1, // - absolute value function
244 accept :1, // - accept an incoming socket connect
245 alarm :1, // - schedule a SIGALRM
246 'atan2' :1, // - arctangent of Y/X in the range -PI to PI
247 bind :1, // - binds an address to a socket
248 binmode :1, // - prepare binary files for I/O
249 bless :1, // - create an object
250 bootstrap :1, //
251 'break' :1, // - break out of a "given" block
252 caller :1, // - get context of the current subroutine call
253 chdir :1, // - change your current working directory
254 chmod :1, // - changes the permissions on a list of files
255 chomp :1, // - remove a trailing record separator from a string
256 chop :1, // - remove the last character from a string
257 chown :1, // - change the owership on a list of files
258 chr :1, // - get character this number represents
259 chroot :1, // - make directory new root for path lookups
260 close :1, // - close file (or pipe or socket) handle
261 closedir :1, // - close directory handle
262 connect :1, // - connect to a remote socket
263 'continue' :[1,1], // - optional trailing block in a while or foreach
264 'cos' :1, // - cosine function
265 crypt :1, // - one-way passwd-style encryption
266 dbmclose :1, // - breaks binding on a tied dbm file
267 dbmopen :1, // - create binding on a tied dbm file
268 'default' :1, //
269 defined :1, // - test whether a value, variable, or function is defined
270 'delete' :1, // - deletes a value from a hash
271 die :1, // - raise an exception or bail out
272 'do' :1, // - turn a BLOCK into a TERM
273 dump :1, // - create an immediate core dump
274 each :1, // - retrieve the next key/value pair from a hash
275 endgrent :1, // - be done using group file
276 endhostent :1, // - be done using hosts file
277 endnetent :1, // - be done using networks file
278 endprotoent :1, // - be done using protocols file
279 endpwent :1, // - be done using passwd file
280 endservent :1, // - be done using services file
281 eof :1, // - test a filehandle for its end
282 'eval' :1, // - catch exceptions or compile and run code
283 'exec' :1, // - abandon this program to run another
284 exists :1, // - test whether a hash key is present
285 exit :1, // - terminate this program
286 'exp' :1, // - raise I to a power
287 fcntl :1, // - file control system call
288 fileno :1, // - return file descriptor from filehandle
289 flock :1, // - lock an entire file with an advisory lock
290 fork :1, // - create a new process just like this one
291 format :1, // - declare a picture format with use by the write() function
292 formline :1, // - internal function used for formats
293 getc :1, // - get the next character from the filehandle
294 getgrent :1, // - get next group record
295 getgrgid :1, // - get group record given group user ID
296 getgrnam :1, // - get group record given group name
297 gethostbyaddr :1, // - get host record given its address
298 gethostbyname :1, // - get host record given name
299 gethostent :1, // - get next hosts record
300 getlogin :1, // - return who logged in at this tty
301 getnetbyaddr :1, // - get network record given its address
302 getnetbyname :1, // - get networks record given name
303 getnetent :1, // - get next networks record
304 getpeername :1, // - find the other end of a socket connection
305 getpgrp :1, // - get process group
306 getppid :1, // - get parent process ID
307 getpriority :1, // - get current nice value
308 getprotobyname :1, // - get protocol record given name
309 getprotobynumber :1, // - get protocol record numeric protocol
310 getprotoent :1, // - get next protocols record
311 getpwent :1, // - get next passwd record
312 getpwnam :1, // - get passwd record given user login name
313 getpwuid :1, // - get passwd record given user ID
314 getservbyname :1, // - get services record given its name
315 getservbyport :1, // - get services record given numeric port
316 getservent :1, // - get next services record
317 getsockname :1, // - retrieve the sockaddr for a given socket
318 getsockopt :1, // - get socket options on a given socket
319 given :1, //
320 glob :1, // - expand filenames using wildcards
321 gmtime :1, // - convert UNIX time into record or string using Greenwich time
322 'goto' :1, // - create spaghetti code
323 grep :1, // - locate elements in a list test true against a given criterion
324 hex :1, // - convert a string to a hexadecimal number
325 'import' :1, // - patch a module's namespace into your own
326 index :1, // - find a substring within a string
327 'int' :1, // - get the integer portion of a number
328 ioctl :1, // - system-dependent device control system call
329 'join' :1, // - join a list into a string using a separator
330 keys :1, // - retrieve list of indices from a hash
331 kill :1, // - send a signal to a process or process group
332 last :1, // - exit a block prematurely
333 lc :1, // - return lower-case version of a string
334 lcfirst :1, // - return a string with just the next letter in lower case
335 length :1, // - return the number of bytes in a string
336 'link' :1, // - create a hard link in the filesytem
337 listen :1, // - register your socket as a server
338 local : 2, // - create a temporary value for a global variable (dynamic scoping)
339 localtime :1, // - convert UNIX time into record or string using local time
340 lock :1, // - get a thread lock on a variable, subroutine, or method
341 'log' :1, // - retrieve the natural logarithm for a number
342 lstat :1, // - stat a symbolic link
343 m :null, // - match a string with a regular expression pattern
344 map :1, // - apply a change to a list to get back a new list with the changes
345 mkdir :1, // - create a directory
346 msgctl :1, // - SysV IPC message control operations
347 msgget :1, // - get SysV IPC message queue
348 msgrcv :1, // - receive a SysV IPC message from a message queue
349 msgsnd :1, // - send a SysV IPC message to a message queue
350 my : 2, // - declare and assign a local variable (lexical scoping)
351 'new' :1, //
352 next :1, // - iterate a block prematurely
353 no :1, // - unimport some module symbols or semantics at compile time
354 oct :1, // - convert a string to an octal number
355 open :1, // - open a file, pipe, or descriptor
356 opendir :1, // - open a directory
357 ord :1, // - find a character's numeric representation
358 our : 2, // - declare and assign a package variable (lexical scoping)
359 pack :1, // - convert a list into a binary representation
360 'package' :1, // - declare a separate global namespace
361 pipe :1, // - open a pair of connected filehandles
362 pop :1, // - remove the last element from an array and return it
363 pos :1, // - find or set the offset for the last/next m//g search
364 print :1, // - output a list to a filehandle
365 printf :1, // - output a formatted list to a filehandle
366 prototype :1, // - get the prototype (if any) of a subroutine
367 push :1, // - append one or more elements to an array
368 q :null, // - singly quote a string
369 qq :null, // - doubly quote a string
370 qr :null, // - Compile pattern
371 quotemeta :null, // - quote regular expression magic characters
372 qw :null, // - quote a list of words
373 qx :null, // - backquote quote a string
374 rand :1, // - retrieve the next pseudorandom number
375 read :1, // - fixed-length buffered input from a filehandle
376 readdir :1, // - get a directory from a directory handle
377 readline :1, // - fetch a record from a file
378 readlink :1, // - determine where a symbolic link is pointing
379 readpipe :1, // - execute a system command and collect standard output
380 recv :1, // - receive a message over a Socket
381 redo :1, // - start this loop iteration over again
382 ref :1, // - find out the type of thing being referenced
383 rename :1, // - change a filename
384 require :1, // - load in external functions from a library at runtime
385 reset :1, // - clear all variables of a given name
386 'return' :1, // - get out of a function early
387 reverse :1, // - flip a string or a list
388 rewinddir :1, // - reset directory handle
389 rindex :1, // - right-to-left substring search
390 rmdir :1, // - remove a directory
391 s :null, // - replace a pattern with a string
392 say :1, // - print with newline
393 scalar :1, // - force a scalar context
394 seek :1, // - reposition file pointer for random-access I/O
395 seekdir :1, // - reposition directory pointer
396 select :1, // - reset default output or do I/O multiplexing
397 semctl :1, // - SysV semaphore control operations
398 semget :1, // - get set of SysV semaphores
399 semop :1, // - SysV semaphore operations
400 send :1, // - send a message over a socket
401 setgrent :1, // - prepare group file for use
402 sethostent :1, // - prepare hosts file for use
403 setnetent :1, // - prepare networks file for use
404 setpgrp :1, // - set the process group of a process
405 setpriority :1, // - set a process's nice value
406 setprotoent :1, // - prepare protocols file for use
407 setpwent :1, // - prepare passwd file for use
408 setservent :1, // - prepare services file for use
409 setsockopt :1, // - set some socket options
410 shift :1, // - remove the first element of an array, and return it
411 shmctl :1, // - SysV shared memory operations
412 shmget :1, // - get SysV shared memory segment identifier
413 shmread :1, // - read SysV shared memory
414 shmwrite :1, // - write SysV shared memory
415 shutdown :1, // - close down just half of a socket connection
416 'sin' :1, // - return the sine of a number
417 sleep :1, // - block for some number of seconds
418 socket :1, // - create a socket
419 socketpair :1, // - create a pair of sockets
420 'sort' :1, // - sort a list of values
421 splice :1, // - add or remove elements anywhere in an array
422 'split' :1, // - split up a string using a regexp delimiter
423 sprintf :1, // - formatted print into a string
424 'sqrt' :1, // - square root function
425 srand :1, // - seed the random number generator
426 stat :1, // - get a file's status information
427 state :1, // - declare and assign a state variable (persistent lexical scoping)
428 study :1, // - optimize input data for repeated searches
429 'sub' :1, // - declare a subroutine, possibly anonymously
430 'substr' :1, // - get or alter a portion of a stirng
431 symlink :1, // - create a symbolic link to a file
432 syscall :1, // - execute an arbitrary system call
433 sysopen :1, // - open a file, pipe, or descriptor
434 sysread :1, // - fixed-length unbuffered input from a filehandle
435 sysseek :1, // - position I/O pointer on handle used with sysread and syswrite
436 system :1, // - run a separate program
437 syswrite :1, // - fixed-length unbuffered output to a filehandle
438 tell :1, // - get current seekpointer on a filehandle
439 telldir :1, // - get current seekpointer on a directory handle
440 tie :1, // - bind a variable to an object class
441 tied :1, // - get a reference to the object underlying a tied variable
442 time :1, // - return number of seconds since 1970
443 times :1, // - return elapsed time for self and child processes
444 tr :null, // - transliterate a string
445 truncate :1, // - shorten a file
446 uc :1, // - return upper-case version of a string
447 ucfirst :1, // - return a string with just the next letter in upper case
448 umask :1, // - set file creation mode mask
449 undef :1, // - remove a variable or function definition
450 unlink :1, // - remove one link to a file
451 unpack :1, // - convert binary structure into normal perl variables
452 unshift :1, // - prepend more elements to the beginning of a list
453 untie :1, // - break a tie binding to a variable
454 use :1, // - load in a module at compile time
455 utime :1, // - set a file's last access and modify times
456 values :1, // - return a list of the values in a hash
457 vec :1, // - test or set particular bits in a string
458 wait :1, // - wait for any child process to die
459 waitpid :1, // - wait for a particular child process to die
460 wantarray :1, // - get void vs scalar vs list context of current subroutine call
461 warn :1, // - print debugging info
462 when :1, //
463 write :1, // - print a picture record
464 y :null}; // - transliterate a string
465
466 var RXstyle="string-2";
467 var RXmodifiers=/[goseximacplud]/; // NOTE: "m", "s", "y" and "tr" need to correct real modifiers for each regexp type
468
469 function tokenChain(stream,state,chain,style,tail){ // NOTE: chain.length > 2 is not working now (it's for s[...][...]geos;)
470 state.chain=null; // 12 3tail
471 state.style=null;
472 state.tail=null;
473 state.tokenize=function(stream,state){
474 var e=false,c,i=0;
475 while(c=stream.next()){
476 if(c===chain[i]&&!e){
477 if(chain[++i]!==undefined){
478 state.chain=chain[i];
479 state.style=style;
480 state.tail=tail}
481 else if(tail)
482 stream.eatWhile(tail);
483 state.tokenize=tokenPerl;
484 return style}
485 e=!e&&c=="\\"}
486 return style};
487 return state.tokenize(stream,state)}
488
489 function tokenSOMETHING(stream,state,string){
490 state.tokenize=function(stream,state){
491 if(stream.string==string)
492 state.tokenize=tokenPerl;
493 stream.skipToEnd();
494 return "string"};
495 return state.tokenize(stream,state)}
496
497 function tokenPerl(stream,state){
498 if(stream.eatSpace())
499 return null;
500 if(state.chain)
501 return tokenChain(stream,state,state.chain,state.style,state.tail);
502 if(stream.match(/^\-?[\d\.]/,false))
503 if(stream.match(/^(\-?(\d*\.\d+(e[+-]?\d+)?|\d+\.\d*)|0x[\da-fA-F]+|0b[01]+|\d+(e[+-]?\d+)?)/))
504 return 'number';
505 if(stream.match(/^<<(?=\w)/)){ // NOTE: <<SOMETHING\n...\nSOMETHING\n
506 stream.eatWhile(/\w/);
507 return tokenSOMETHING(stream,state,stream.current().substr(2))}
508 if(stream.sol()&&stream.match(/^\=item(?!\w)/)){// NOTE: \n=item...\n=cut\n
509 return tokenSOMETHING(stream,state,'=cut')}
510 var ch=stream.next();
511 if(ch=='"'||ch=="'"){ // NOTE: ' or " or <<'SOMETHING'\n...\nSOMETHING\n or <<"SOMETHING"\n...\nSOMETHING\n
512 if(stream.prefix(3)=="<<"+ch){
513 var p=stream.pos;
514 stream.eatWhile(/\w/);
515 var n=stream.current().substr(1);
516 if(n&&stream.eat(ch))
517 return tokenSOMETHING(stream,state,n);
518 stream.pos=p}
519 return tokenChain(stream,state,[ch],"string")}
520 if(ch=="q"){
521 var c=stream.look(-2);
522 if(!(c&&/\w/.test(c))){
523 c=stream.look(0);
524 if(c=="x"){
525 c=stream.look(1);
526 if(c=="("){
527 stream.eatSuffix(2);
528 return tokenChain(stream,state,[")"],RXstyle,RXmodifiers)}
529 if(c=="["){
530 stream.eatSuffix(2);
531 return tokenChain(stream,state,["]"],RXstyle,RXmodifiers)}
532 if(c=="{"){
533 stream.eatSuffix(2);
534 return tokenChain(stream,state,["}"],RXstyle,RXmodifiers)}
535 if(c=="<"){
536 stream.eatSuffix(2);
537 return tokenChain(stream,state,[">"],RXstyle,RXmodifiers)}
538 if(/[\^'"!~\/]/.test(c)){
539 stream.eatSuffix(1);
540 return tokenChain(stream,state,[stream.eat(c)],RXstyle,RXmodifiers)}}
541 else if(c=="q"){
542 c=stream.look(1);
543 if(c=="("){
544 stream.eatSuffix(2);
545 return tokenChain(stream,state,[")"],"string")}
546 if(c=="["){
547 stream.eatSuffix(2);
548 return tokenChain(stream,state,["]"],"string")}
549 if(c=="{"){
550 stream.eatSuffix(2);
551 return tokenChain(stream,state,["}"],"string")}
552 if(c=="<"){
553 stream.eatSuffix(2);
554 return tokenChain(stream,state,[">"],"string")}
555 if(/[\^'"!~\/]/.test(c)){
556 stream.eatSuffix(1);
557 return tokenChain(stream,state,[stream.eat(c)],"string")}}
558 else if(c=="w"){
559 c=stream.look(1);
560 if(c=="("){
561 stream.eatSuffix(2);
562 return tokenChain(stream,state,[")"],"bracket")}
563 if(c=="["){
564 stream.eatSuffix(2);
565 return tokenChain(stream,state,["]"],"bracket")}
566 if(c=="{"){
567 stream.eatSuffix(2);
568 return tokenChain(stream,state,["}"],"bracket")}
569 if(c=="<"){
570 stream.eatSuffix(2);
571 return tokenChain(stream,state,[">"],"bracket")}
572 if(/[\^'"!~\/]/.test(c)){
573 stream.eatSuffix(1);
574 return tokenChain(stream,state,[stream.eat(c)],"bracket")}}
575 else if(c=="r"){
576 c=stream.look(1);
577 if(c=="("){
578 stream.eatSuffix(2);
579 return tokenChain(stream,state,[")"],RXstyle,RXmodifiers)}
580 if(c=="["){
581 stream.eatSuffix(2);
582 return tokenChain(stream,state,["]"],RXstyle,RXmodifiers)}
583 if(c=="{"){
584 stream.eatSuffix(2);
585 return tokenChain(stream,state,["}"],RXstyle,RXmodifiers)}
586 if(c=="<"){
587 stream.eatSuffix(2);
588 return tokenChain(stream,state,[">"],RXstyle,RXmodifiers)}
589 if(/[\^'"!~\/]/.test(c)){
590 stream.eatSuffix(1);
591 return tokenChain(stream,state,[stream.eat(c)],RXstyle,RXmodifiers)}}
592 else if(/[\^'"!~\/(\[{<]/.test(c)){
593 if(c=="("){
594 stream.eatSuffix(1);
595 return tokenChain(stream,state,[")"],"string")}
596 if(c=="["){
597 stream.eatSuffix(1);
598 return tokenChain(stream,state,["]"],"string")}
599 if(c=="{"){
600 stream.eatSuffix(1);
601 return tokenChain(stream,state,["}"],"string")}
602 if(c=="<"){
603 stream.eatSuffix(1);
604 return tokenChain(stream,state,[">"],"string")}
605 if(/[\^'"!~\/]/.test(c)){
606 return tokenChain(stream,state,[stream.eat(c)],"string")}}}}
607 if(ch=="m"){
608 var c=stream.look(-2);
609 if(!(c&&/\w/.test(c))){
610 c=stream.eat(/[(\[{<\^'"!~\/]/);
611 if(c){
612 if(/[\^'"!~\/]/.test(c)){
613 return tokenChain(stream,state,[c],RXstyle,RXmodifiers)}
614 if(c=="("){
615 return tokenChain(stream,state,[")"],RXstyle,RXmodifiers)}
616 if(c=="["){
617 return tokenChain(stream,state,["]"],RXstyle,RXmodifiers)}
618 if(c=="{"){
619 return tokenChain(stream,state,["}"],RXstyle,RXmodifiers)}
620 if(c=="<"){
621 return tokenChain(stream,state,[">"],RXstyle,RXmodifiers)}}}}
622 if(ch=="s"){
623 var c=/[\/>\]})\w]/.test(stream.look(-2));
624 if(!c){
625 c=stream.eat(/[(\[{<\^'"!~\/]/);
626 if(c){
627 if(c=="[")
628 return tokenChain(stream,state,["]","]"],RXstyle,RXmodifiers);
629 if(c=="{")
630 return tokenChain(stream,state,["}","}"],RXstyle,RXmodifiers);
631 if(c=="<")
632 return tokenChain(stream,state,[">",">"],RXstyle,RXmodifiers);
633 if(c=="(")
634 return tokenChain(stream,state,[")",")"],RXstyle,RXmodifiers);
635 return tokenChain(stream,state,[c,c],RXstyle,RXmodifiers)}}}
636 if(ch=="y"){
637 var c=/[\/>\]})\w]/.test(stream.look(-2));
638 if(!c){
639 c=stream.eat(/[(\[{<\^'"!~\/]/);
640 if(c){
641 if(c=="[")
642 return tokenChain(stream,state,["]","]"],RXstyle,RXmodifiers);
643 if(c=="{")
644 return tokenChain(stream,state,["}","}"],RXstyle,RXmodifiers);
645 if(c=="<")
646 return tokenChain(stream,state,[">",">"],RXstyle,RXmodifiers);
647 if(c=="(")
648 return tokenChain(stream,state,[")",")"],RXstyle,RXmodifiers);
649 return tokenChain(stream,state,[c,c],RXstyle,RXmodifiers)}}}
650 if(ch=="t"){
651 var c=/[\/>\]})\w]/.test(stream.look(-2));
652 if(!c){
653 c=stream.eat("r");if(c){
654 c=stream.eat(/[(\[{<\^'"!~\/]/);
655 if(c){
656 if(c=="[")
657 return tokenChain(stream,state,["]","]"],RXstyle,RXmodifiers);
658 if(c=="{")
659 return tokenChain(stream,state,["}","}"],RXstyle,RXmodifiers);
660 if(c=="<")
661 return tokenChain(stream,state,[">",">"],RXstyle,RXmodifiers);
662 if(c=="(")
663 return tokenChain(stream,state,[")",")"],RXstyle,RXmodifiers);
664 return tokenChain(stream,state,[c,c],RXstyle,RXmodifiers)}}}}
665 if(ch=="`"){
666 return tokenChain(stream,state,[ch],"variable-2")}
667 if(ch=="/"){
668 if(!/~\s*$/.test(stream.prefix()))
669 return "operator";
670 else
671 return tokenChain(stream,state,[ch],RXstyle,RXmodifiers)}
672 if(ch=="$"){
673 var p=stream.pos;
674 if(stream.eatWhile(/\d/)||stream.eat("{")&&stream.eatWhile(/\d/)&&stream.eat("}"))
675 return "variable-2";
676 else
677 stream.pos=p}
678 if(/[$@%]/.test(ch)){
679 var p=stream.pos;
680 if(stream.eat("^")&&stream.eat(/[A-Z]/)||!/[@$%&]/.test(stream.look(-2))&&stream.eat(/[=|\\\-#?@;:&`~\^!\[\]*'"$+.,\/<>()]/)){
681 var c=stream.current();
682 if(PERL[c])
683 return "variable-2"}
684 stream.pos=p}
685 if(/[$@%&]/.test(ch)){
686 if(stream.eatWhile(/[\w$\[\]]/)||stream.eat("{")&&stream.eatWhile(/[\w$\[\]]/)&&stream.eat("}")){
687 var c=stream.current();
688 if(PERL[c])
689 return "variable-2";
690 else
691 return "variable"}}
692 if(ch=="#"){
693 if(stream.look(-2)!="$"){
694 stream.skipToEnd();
695 return "comment"}}
696 if(/[:+\-\^*$&%@=<>!?|\/~\.]/.test(ch)){
697 var p=stream.pos;
698 stream.eatWhile(/[:+\-\^*$&%@=<>!?|\/~\.]/);
699 if(PERL[stream.current()])
700 return "operator";
701 else
702 stream.pos=p}
703 if(ch=="_"){
704 if(stream.pos==1){
705 if(stream.suffix(6)=="_END__"){
706 return tokenChain(stream,state,['\0'],"comment")}
707 else if(stream.suffix(7)=="_DATA__"){
708 return tokenChain(stream,state,['\0'],"variable-2")}
709 else if(stream.suffix(7)=="_C__"){
710 return tokenChain(stream,state,['\0'],"string")}}}
711 if(/\w/.test(ch)){
712 var p=stream.pos;
713 if(stream.look(-2)=="{"&&(stream.look(0)=="}"||stream.eatWhile(/\w/)&&stream.look(0)=="}"))
714 return "string";
715 else
716 stream.pos=p}
717 if(/[A-Z]/.test(ch)){
718 var l=stream.look(-2);
719 var p=stream.pos;
720 stream.eatWhile(/[A-Z_]/);
721 if(/[\da-z]/.test(stream.look(0))){
722 stream.pos=p}
723 else{
724 var c=PERL[stream.current()];
725 if(!c)
726 return "meta";
727 if(c[1])
728 c=c[0];
729 if(l!=":"){
730 if(c==1)
731 return "keyword";
732 else if(c==2)
733 return "def";
734 else if(c==3)
735 return "atom";
736 else if(c==4)
737 return "operator";
738 else if(c==5)
739 return "variable-2";
740 else
741 return "meta"}
742 else
743 return "meta"}}
744 if(/[a-zA-Z_]/.test(ch)){
745 var l=stream.look(-2);
746 stream.eatWhile(/\w/);
747 var c=PERL[stream.current()];
748 if(!c)
749 return "meta";
750 if(c[1])
751 c=c[0];
752 if(l!=":"){
753 if(c==1)
754 return "keyword";
755 else if(c==2)
756 return "def";
757 else if(c==3)
758 return "atom";
759 else if(c==4)
760 return "operator";
761 else if(c==5)
762 return "variable-2";
763 else
764 return "meta"}
765 else
766 return "meta"}
767 return null}
768
769 return{
770 startState:function(){
771 return{
772 tokenize:tokenPerl,
773 chain:null,
774 style:null,
775 tail:null}},
776 token:function(stream,state){
777 return (state.tokenize||tokenPerl)(stream,state)},
778 electricChars:"{}"}});
779
780 CodeMirror.defineMIME("text/x-perl", "perl");
781
782 // it's like "peek", but need for look-ahead or look-behind if index < 0
783 CodeMirror.StringStream.prototype.look=function(c){
784 return this.string.charAt(this.pos+(c||0))};
785
786 // return a part of prefix of current stream from current position
787 CodeMirror.StringStream.prototype.prefix=function(c){
788 if(c){
789 var x=this.pos-c;
790 return this.string.substr((x>=0?x:0),c)}
791 else{
792 return this.string.substr(0,this.pos-1)}};
793
794 // return a part of suffix of current stream from current position
795 CodeMirror.StringStream.prototype.suffix=function(c){
796 var y=this.string.length;
797 var x=y-this.pos+1;
798 return this.string.substr(this.pos,(c&&c<y?c:x))};
799
800 // return a part of suffix of current stream from current position and change current position
801 CodeMirror.StringStream.prototype.nsuffix=function(c){
802 var p=this.pos;
803 var l=c||(this.string.length-this.pos+1);
804 this.pos+=l;
805 return this.string.substr(p,l)};
806
807 // eating and vomiting a part of stream from current position
808 CodeMirror.StringStream.prototype.eatSuffix=function(c){
809 var x=this.pos+c;
810 var y;
811 if(x<=0)
812 this.pos=0;
813 else if(x>=(y=this.string.length-1))
814 this.pos=y;
815 else
816 this.pos=x};
@@ -0,0 +1,48
1 <!doctype html>
2 <html>
3 <head>
4 <title>CodeMirror: PHP mode</title>
5 <link rel="stylesheet" href="../../lib/codemirror.css">
6 <script src="../../lib/codemirror.js"></script>
7 <script src="../xml/xml.js"></script>
8 <script src="../javascript/javascript.js"></script>
9 <script src="../css/css.js"></script>
10 <script src="../clike/clike.js"></script>
11 <script src="php.js"></script>
12 <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
13 <link rel="stylesheet" href="../../doc/docs.css">
14 </head>
15 <body>
16 <h1>CodeMirror: PHP mode</h1>
17
18 <form><textarea id="code" name="code">
19 <?php
20 function hello($who) {
21 return "Hello " . $who;
22 }
23 ?>
24 <p>The program says <?= hello("World") ?>.</p>
25 <script>
26 alert("And here is some JS code"); // also colored
27 </script>
28 </textarea></form>
29
30 <script>
31 var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
32 lineNumbers: true,
33 matchBrackets: true,
34 mode: "application/x-httpd-php",
35 indentUnit: 4,
36 indentWithTabs: true,
37 enterMode: "keep",
38 tabMode: "shift"
39 });
40 </script>
41
42 <p>Simple HTML/PHP mode based on
43 the <a href="../clike/">C-like</a> mode. Depends on XML,
44 JavaScript, CSS, and C-like modes.</p>
45
46 <p><strong>MIME types defined:</strong> <code>application/x-httpd-php</code> (HTML with PHP code), <code>text/x-php</code> (plain, non-wrapped PHP code).</p>
47 </body>
48 </html>
@@ -0,0 +1,150
1 (function() {
2 function keywords(str) {
3 var obj = {}, words = str.split(" ");
4 for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
5 return obj;
6 }
7 function heredoc(delim) {
8 return function(stream, state) {
9 if (stream.match(delim)) state.tokenize = null;
10 else stream.skipToEnd();
11 return "string";
12 }
13 }
14 var phpConfig = {
15 name: "clike",
16 keywords: keywords("abstract and array as break case catch class clone const continue declare default " +
17 "do else elseif enddeclare endfor endforeach endif endswitch endwhile extends final " +
18 "for foreach function global goto if implements interface instanceof namespace " +
19 "new or private protected public static switch throw trait try use var while xor " +
20 "die echo empty exit eval include include_once isset list require require_once return " +
21 "print unset __halt_compiler self static parent"),
22 blockKeywords: keywords("catch do else elseif for foreach if switch try while"),
23 atoms: keywords("true false null TRUE FALSE NULL"),
24 multiLineStrings: true,
25 hooks: {
26 "$": function(stream, state) {
27 stream.eatWhile(/[\w\$_]/);
28 return "variable-2";
29 },
30 "<": function(stream, state) {
31 if (stream.match(/<</)) {
32 stream.eatWhile(/[\w\.]/);
33 state.tokenize = heredoc(stream.current().slice(3));
34 return state.tokenize(stream, state);
35 }
36 return false;
37 },
38 "#": function(stream, state) {
39 while (!stream.eol() && !stream.match("?>", false)) stream.next();
40 return "comment";
41 },
42 "/": function(stream, state) {
43 if (stream.eat("/")) {
44 while (!stream.eol() && !stream.match("?>", false)) stream.next();
45 return "comment";
46 }
47 return false;
48 }
49 }
50 };
51
52 CodeMirror.defineMode("php", function(config, parserConfig) {
53 var htmlMode = CodeMirror.getMode(config, {name: "xml", htmlMode: true});
54 var jsMode = CodeMirror.getMode(config, "javascript");
55 var cssMode = CodeMirror.getMode(config, "css");
56 var phpMode = CodeMirror.getMode(config, phpConfig);
57
58 function dispatch(stream, state) { // TODO open PHP inside text/css
59 var isPHP = state.mode == "php";
60 if (stream.sol() && state.pending != '"') state.pending = null;
61 if (state.curMode == htmlMode) {
62 if (stream.match(/^<\?\w*/)) {
63 state.curMode = phpMode;
64 state.curState = state.php;
65 state.curClose = "?>";
66 state.mode = "php";
67 return "meta";
68 }
69 if (state.pending == '"') {
70 while (!stream.eol() && stream.next() != '"') {}
71 var style = "string";
72 } else if (state.pending && stream.pos < state.pending.end) {
73 stream.pos = state.pending.end;
74 var style = state.pending.style;
75 } else {
76 var style = htmlMode.token(stream, state.curState);
77 }
78 state.pending = null;
79 var cur = stream.current(), openPHP = cur.search(/<\?/);
80 if (openPHP != -1) {
81 if (style == "string" && /\"$/.test(cur) && !/\?>/.test(cur)) state.pending = '"';
82 else state.pending = {end: stream.pos, style: style};
83 stream.backUp(cur.length - openPHP);
84 } else if (style == "tag" && stream.current() == ">" && state.curState.context) {
85 if (/^script$/i.test(state.curState.context.tagName)) {
86 state.curMode = jsMode;
87 state.curState = jsMode.startState(htmlMode.indent(state.curState, ""));
88 state.curClose = /^<\/\s*script\s*>/i;
89 state.mode = "javascript";
90 }
91 else if (/^style$/i.test(state.curState.context.tagName)) {
92 state.curMode = cssMode;
93 state.curState = cssMode.startState(htmlMode.indent(state.curState, ""));
94 state.curClose = /^<\/\s*style\s*>/i;
95 state.mode = "css";
96 }
97 }
98 return style;
99 } else if ((!isPHP || state.php.tokenize == null) &&
100 stream.match(state.curClose, isPHP)) {
101 state.curMode = htmlMode;
102 state.curState = state.html;
103 state.curClose = null;
104 state.mode = "html";
105 if (isPHP) return "meta";
106 else return dispatch(stream, state);
107 } else {
108 return state.curMode.token(stream, state.curState);
109 }
110 }
111
112 return {
113 startState: function() {
114 var html = htmlMode.startState();
115 return {html: html,
116 php: phpMode.startState(),
117 curMode: parserConfig.startOpen ? phpMode : htmlMode,
118 curState: parserConfig.startOpen ? phpMode.startState() : html,
119 curClose: parserConfig.startOpen ? /^\?>/ : null,
120 mode: parserConfig.startOpen ? "php" : "html",
121 pending: null}
122 },
123
124 copyState: function(state) {
125 var html = state.html, htmlNew = CodeMirror.copyState(htmlMode, html),
126 php = state.php, phpNew = CodeMirror.copyState(phpMode, php), cur;
127 if (state.curState == html) cur = htmlNew;
128 else if (state.curState == php) cur = phpNew;
129 else cur = CodeMirror.copyState(state.curMode, state.curState);
130 return {html: htmlNew, php: phpNew, curMode: state.curMode, curState: cur,
131 curClose: state.curClose, mode: state.mode,
132 pending: state.pending};
133 },
134
135 token: dispatch,
136
137 indent: function(state, textAfter) {
138 if ((state.curMode != phpMode && /^\s*<\//.test(textAfter)) ||
139 (state.curMode == phpMode && /^\?>/.test(textAfter)))
140 return htmlMode.indent(state.html, textAfter);
141 return state.curMode.indent(state.curState, textAfter);
142 },
143
144 electricChars: "/{}:"
145 }
146 }, "xml", "clike", "javascript", "css");
147 CodeMirror.defineMIME("application/x-httpd-php", "php");
148 CodeMirror.defineMIME("application/x-httpd-php-open", {name: "php", startOpen: true});
149 CodeMirror.defineMIME("text/x-php", phpConfig);
150 })();
@@ -0,0 +1,42
1 <!doctype html>
2 <html>
3 <head>
4 <title>CodeMirror: Pig Latin mode</title>
5 <link rel="stylesheet" href="../../lib/codemirror.css">
6 <script src="../../lib/codemirror.js"></script>
7 <script src="pig.js"></script>
8 <link rel="stylesheet" href="../../doc/docs.css">
9 <style>.CodeMirror {border: 2px inset #dee;}</style>
10 </head>
11 <body>
12 <h1>CodeMirror: Pig Latin mode</h1>
13
14 <form><textarea id="code" name="code">
15 -- Apache Pig (Pig Latin Language) Demo
16 /*
17 This is a multiline comment.
18 */
19 a = LOAD "\path\to\input" USING PigStorage('\t') AS (x:long, y:chararray, z:bytearray);
20 b = GROUP a BY (x,y,3+4);
21 c = FOREACH b GENERATE flatten(group) as (x,y), SUM(group.$2) as z;
22 STORE c INTO "\path\to\output";
23
24 --
25 </textarea></form>
26
27 <script>
28 var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
29 lineNumbers: true,
30 matchBrackets: true,
31 indentUnit: 4,
32 mode: "text/x-pig"
33 });
34 </script>
35
36 <p>
37 Simple mode that handles Pig Latin language.
38 </p>
39
40 <p><strong>MIME type defined:</strong> <code>text/x-pig</code>
41 (PIG code)
42 </html>
@@ -0,0 +1,172
1 /*
2 * Pig Latin Mode for CodeMirror 2
3 * @author Prasanth Jayachandran
4 * @link https://github.com/prasanthj/pig-codemirror-2
5 * This implementation is adapted from PL/SQL mode in CodeMirror 2.
6 */
7 CodeMirror.defineMode("pig", function(config, parserConfig) {
8 var indentUnit = config.indentUnit,
9 keywords = parserConfig.keywords,
10 builtins = parserConfig.builtins,
11 types = parserConfig.types,
12 multiLineStrings = parserConfig.multiLineStrings;
13
14 var isOperatorChar = /[*+\-%<>=&?:\/!|]/;
15
16 function chain(stream, state, f) {
17 state.tokenize = f;
18 return f(stream, state);
19 }
20
21 var type;
22 function ret(tp, style) {
23 type = tp;
24 return style;
25 }
26
27 function tokenComment(stream, state) {
28 var isEnd = false;
29 var ch;
30 while(ch = stream.next()) {
31 if(ch == "/" && isEnd) {
32 state.tokenize = tokenBase;
33 break;
34 }
35 isEnd = (ch == "*");
36 }
37 return ret("comment", "comment");
38 }
39
40 function tokenString(quote) {
41 return function(stream, state) {
42 var escaped = false, next, end = false;
43 while((next = stream.next()) != null) {
44 if (next == quote && !escaped) {
45 end = true; break;
46 }
47 escaped = !escaped && next == "\\";
48 }
49 if (end || !(escaped || multiLineStrings))
50 state.tokenize = tokenBase;
51 return ret("string", "error");
52 };
53 }
54
55 function tokenBase(stream, state) {
56 var ch = stream.next();
57
58 // is a start of string?
59 if (ch == '"' || ch == "'")
60 return chain(stream, state, tokenString(ch));
61 // is it one of the special chars
62 else if(/[\[\]{}\(\),;\.]/.test(ch))
63 return ret(ch);
64 // is it a number?
65 else if(/\d/.test(ch)) {
66 stream.eatWhile(/[\w\.]/);
67 return ret("number", "number");
68 }
69 // multi line comment or operator
70 else if (ch == "/") {
71 if (stream.eat("*")) {
72 return chain(stream, state, tokenComment);
73 }
74 else {
75 stream.eatWhile(isOperatorChar);
76 return ret("operator", "operator");
77 }
78 }
79 // single line comment or operator
80 else if (ch=="-") {
81 if(stream.eat("-")){
82 stream.skipToEnd();
83 return ret("comment", "comment");
84 }
85 else {
86 stream.eatWhile(isOperatorChar);
87 return ret("operator", "operator");
88 }
89 }
90 // is it an operator
91 else if (isOperatorChar.test(ch)) {
92 stream.eatWhile(isOperatorChar);
93 return ret("operator", "operator");
94 }
95 else {
96 // get the while word
97 stream.eatWhile(/[\w\$_]/);
98 // is it one of the listed keywords?
99 if (keywords && keywords.propertyIsEnumerable(stream.current().toUpperCase())) {
100 if (stream.eat(")") || stream.eat(".")) {
101 //keywords can be used as variables like flatten(group), group.$0 etc..
102 }
103 else {
104 return ("keyword", "keyword");
105 }
106 }
107 // is it one of the builtin functions?
108 if (builtins && builtins.propertyIsEnumerable(stream.current().toUpperCase()))
109 {
110 return ("keyword", "variable-2")
111 }
112 // is it one of the listed types?
113 if (types && types.propertyIsEnumerable(stream.current().toUpperCase()))
114 return ("keyword", "variable-3")
115 // default is a 'variable'
116 return ret("variable", "pig-word");
117 }
118 }
119
120 // Interface
121 return {
122 startState: function(basecolumn) {
123 return {
124 tokenize: tokenBase,
125 startOfLine: true
126 };
127 },
128
129 token: function(stream, state) {
130 if(stream.eatSpace()) return null;
131 var style = state.tokenize(stream, state);
132 return style;
133 }
134 };
135 });
136
137 (function() {
138 function keywords(str) {
139 var obj = {}, words = str.split(" ");
140 for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
141 return obj;
142 }
143
144 // builtin funcs taken from trunk revision 1303237
145 var pBuiltins = "ABS ACOS ARITY ASIN ATAN AVG BAGSIZE BINSTORAGE BLOOM BUILDBLOOM CBRT CEIL "
146 + "CONCAT COR COS COSH COUNT COUNT_STAR COV CONSTANTSIZE CUBEDIMENSIONS DIFF DISTINCT DOUBLEABS "
147 + "DOUBLEAVG DOUBLEBASE DOUBLEMAX DOUBLEMIN DOUBLEROUND DOUBLESUM EXP FLOOR FLOATABS FLOATAVG "
148 + "FLOATMAX FLOATMIN FLOATROUND FLOATSUM GENERICINVOKER INDEXOF INTABS INTAVG INTMAX INTMIN "
149 + "INTSUM INVOKEFORDOUBLE INVOKEFORFLOAT INVOKEFORINT INVOKEFORLONG INVOKEFORSTRING INVOKER "
150 + "ISEMPTY JSONLOADER JSONMETADATA JSONSTORAGE LAST_INDEX_OF LCFIRST LOG LOG10 LOWER LONGABS "
151 + "LONGAVG LONGMAX LONGMIN LONGSUM MAX MIN MAPSIZE MONITOREDUDF NONDETERMINISTIC OUTPUTSCHEMA "
152 + "PIGSTORAGE PIGSTREAMING RANDOM REGEX_EXTRACT REGEX_EXTRACT_ALL REPLACE ROUND SIN SINH SIZE "
153 + "SQRT STRSPLIT SUBSTRING SUM STRINGCONCAT STRINGMAX STRINGMIN STRINGSIZE TAN TANH TOBAG "
154 + "TOKENIZE TOMAP TOP TOTUPLE TRIM TEXTLOADER TUPLESIZE UCFIRST UPPER UTF8STORAGECONVERTER ";
155
156 // taken from QueryLexer.g
157 var pKeywords = "VOID IMPORT RETURNS DEFINE LOAD FILTER FOREACH ORDER CUBE DISTINCT COGROUP "
158 + "JOIN CROSS UNION SPLIT INTO IF OTHERWISE ALL AS BY USING INNER OUTER ONSCHEMA PARALLEL "
159 + "PARTITION GROUP AND OR NOT GENERATE FLATTEN ASC DESC IS STREAM THROUGH STORE MAPREDUCE "
160 + "SHIP CACHE INPUT OUTPUT STDERROR STDIN STDOUT LIMIT SAMPLE LEFT RIGHT FULL EQ GT LT GTE LTE "
161 + "NEQ MATCHES TRUE FALSE ";
162
163 // data types
164 var pTypes = "BOOLEAN INT LONG FLOAT DOUBLE CHARARRAY BYTEARRAY BAG TUPLE MAP "
165
166 CodeMirror.defineMIME("text/x-pig", {
167 name: "pig",
168 builtins: keywords(pBuiltins),
169 keywords: keywords(pKeywords),
170 types: keywords(pTypes)
171 });
172 }());
@@ -0,0 +1,62
1 <!doctype html>
2 <html>
3 <head>
4 <title>CodeMirror: Oracle PL/SQL mode</title>
5 <link rel="stylesheet" href="../../lib/codemirror.css">
6 <script src="../../lib/codemirror.js"></script>
7 <script src="plsql.js"></script>
8 <link rel="stylesheet" href="../../doc/docs.css">
9 <style>.CodeMirror {border: 2px inset #dee;}</style>
10 </head>
11 <body>
12 <h1>CodeMirror: Oracle PL/SQL mode</h1>
13
14 <form><textarea id="code" name="code">
15 -- Oracle PL/SQL Code Demo
16 /*
17 based on c-like mode, adapted to PL/SQL by Peter Raganitsch ( http://www.oracle-and-apex.com/ )
18 April 2011
19 */
20 DECLARE
21 vIdx NUMBER;
22 vString VARCHAR2(100);
23 cText CONSTANT VARCHAR2(100) := 'That''s it! Have fun with CodeMirror 2';
24 BEGIN
25 vIdx := 0;
26 --
27 FOR rDATA IN
28 ( SELECT *
29 FROM EMP
30 ORDER BY EMPNO
31 )
32 LOOP
33 vIdx := vIdx + 1;
34 vString := rDATA.EMPNO || ' - ' || rDATA.ENAME;
35 --
36 UPDATE EMP
37 SET SAL = SAL * 101/100
38 WHERE EMPNO = rDATA.EMPNO
39 ;
40 END LOOP;
41 --
42 SYS.DBMS_OUTPUT.Put_Line (cText);
43 END;
44 --
45 </textarea></form>
46
47 <script>
48 var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
49 lineNumbers: true,
50 matchBrackets: true,
51 indentUnit: 4,
52 mode: "text/x-plsql"
53 });
54 </script>
55
56 <p>
57 Simple mode that handles Oracle PL/SQL language (and Oracle SQL, of course).
58 </p>
59
60 <p><strong>MIME type defined:</strong> <code>text/x-plsql</code>
61 (PLSQL code)
62 </html>
@@ -0,0 +1,217
1 CodeMirror.defineMode("plsql", function(config, parserConfig) {
2 var indentUnit = config.indentUnit,
3 keywords = parserConfig.keywords,
4 functions = parserConfig.functions,
5 types = parserConfig.types,
6 sqlplus = parserConfig.sqlplus,
7 multiLineStrings = parserConfig.multiLineStrings;
8 var isOperatorChar = /[+\-*&%=<>!?:\/|]/;
9 function chain(stream, state, f) {
10 state.tokenize = f;
11 return f(stream, state);
12 }
13
14 var type;
15 function ret(tp, style) {
16 type = tp;
17 return style;
18 }
19
20 function tokenBase(stream, state) {
21 var ch = stream.next();
22 // start of string?
23 if (ch == '"' || ch == "'")
24 return chain(stream, state, tokenString(ch));
25 // is it one of the special signs []{}().,;? Seperator?
26 else if (/[\[\]{}\(\),;\.]/.test(ch))
27 return ret(ch);
28 // start of a number value?
29 else if (/\d/.test(ch)) {
30 stream.eatWhile(/[\w\.]/);
31 return ret("number", "number");
32 }
33 // multi line comment or simple operator?
34 else if (ch == "/") {
35 if (stream.eat("*")) {
36 return chain(stream, state, tokenComment);
37 }
38 else {
39 stream.eatWhile(isOperatorChar);
40 return ret("operator", "operator");
41 }
42 }
43 // single line comment or simple operator?
44 else if (ch == "-") {
45 if (stream.eat("-")) {
46 stream.skipToEnd();
47 return ret("comment", "comment");
48 }
49 else {
50 stream.eatWhile(isOperatorChar);
51 return ret("operator", "operator");
52 }
53 }
54 // pl/sql variable?
55 else if (ch == "@" || ch == "$") {
56 stream.eatWhile(/[\w\d\$_]/);
57 return ret("word", "variable");
58 }
59 // is it a operator?
60 else if (isOperatorChar.test(ch)) {
61 stream.eatWhile(isOperatorChar);
62 return ret("operator", "operator");
63 }
64 else {
65 // get the whole word
66 stream.eatWhile(/[\w\$_]/);
67 // is it one of the listed keywords?
68 if (keywords && keywords.propertyIsEnumerable(stream.current().toLowerCase())) return ret("keyword", "keyword");
69 // is it one of the listed functions?
70 if (functions && functions.propertyIsEnumerable(stream.current().toLowerCase())) return ret("keyword", "builtin");
71 // is it one of the listed types?
72 if (types && types.propertyIsEnumerable(stream.current().toLowerCase())) return ret("keyword", "variable-2");
73 // is it one of the listed sqlplus keywords?
74 if (sqlplus && sqlplus.propertyIsEnumerable(stream.current().toLowerCase())) return ret("keyword", "variable-3");
75 // default: just a "variable"
76 return ret("word", "variable");
77 }
78 }
79
80 function tokenString(quote) {
81 return function(stream, state) {
82 var escaped = false, next, end = false;
83 while ((next = stream.next()) != null) {
84 if (next == quote && !escaped) {end = true; break;}
85 escaped = !escaped && next == "\\";
86 }
87 if (end || !(escaped || multiLineStrings))
88 state.tokenize = tokenBase;
89 return ret("string", "plsql-string");
90 };
91 }
92
93 function tokenComment(stream, state) {
94 var maybeEnd = false, ch;
95 while (ch = stream.next()) {
96 if (ch == "/" && maybeEnd) {
97 state.tokenize = tokenBase;
98 break;
99 }
100 maybeEnd = (ch == "*");
101 }
102 return ret("comment", "plsql-comment");
103 }
104
105 // Interface
106
107 return {
108 startState: function(basecolumn) {
109 return {
110 tokenize: tokenBase,
111 startOfLine: true
112 };
113 },
114
115 token: function(stream, state) {
116 if (stream.eatSpace()) return null;
117 var style = state.tokenize(stream, state);
118 return style;
119 }
120 };
121 });
122
123 (function() {
124 function keywords(str) {
125 var obj = {}, words = str.split(" ");
126 for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
127 return obj;
128 }
129 var cKeywords = "abort accept access add all alter and any array arraylen as asc assert assign at attributes audit " +
130 "authorization avg " +
131 "base_table begin between binary_integer body boolean by " +
132 "case cast char char_base check close cluster clusters colauth column comment commit compress connect " +
133 "connected constant constraint crash create current currval cursor " +
134 "data_base database date dba deallocate debugoff debugon decimal declare default definition delay delete " +
135 "desc digits dispose distinct do drop " +
136 "else elsif enable end entry escape exception exception_init exchange exclusive exists exit external " +
137 "fast fetch file for force form from function " +
138 "generic goto grant group " +
139 "having " +
140 "identified if immediate in increment index indexes indicator initial initrans insert interface intersect " +
141 "into is " +
142 "key " +
143 "level library like limited local lock log logging long loop " +
144 "master maxextents maxtrans member minextents minus mislabel mode modify multiset " +
145 "new next no noaudit nocompress nologging noparallel not nowait number_base " +
146 "object of off offline on online only open option or order out " +
147 "package parallel partition pctfree pctincrease pctused pls_integer positive positiven pragma primary prior " +
148 "private privileges procedure public " +
149 "raise range raw read rebuild record ref references refresh release rename replace resource restrict return " +
150 "returning reverse revoke rollback row rowid rowlabel rownum rows run " +
151 "savepoint schema segment select separate session set share snapshot some space split sql start statement " +
152 "storage subtype successful synonym " +
153 "tabauth table tables tablespace task terminate then to trigger truncate type " +
154 "union unique unlimited unrecoverable unusable update use using " +
155 "validate value values variable view views " +
156 "when whenever where while with work";
157
158 var cFunctions = "abs acos add_months ascii asin atan atan2 average " +
159 "bfilename " +
160 "ceil chartorowid chr concat convert cos cosh count " +
161 "decode deref dual dump dup_val_on_index " +
162 "empty error exp " +
163 "false floor found " +
164 "glb greatest " +
165 "hextoraw " +
166 "initcap instr instrb isopen " +
167 "last_day least lenght lenghtb ln lower lpad ltrim lub " +
168 "make_ref max min mod months_between " +
169 "new_time next_day nextval nls_charset_decl_len nls_charset_id nls_charset_name nls_initcap nls_lower " +
170 "nls_sort nls_upper nlssort no_data_found notfound null nvl " +
171 "others " +
172 "power " +
173 "rawtohex reftohex round rowcount rowidtochar rpad rtrim " +
174 "sign sin sinh soundex sqlcode sqlerrm sqrt stddev substr substrb sum sysdate " +
175 "tan tanh to_char to_date to_label to_multi_byte to_number to_single_byte translate true trunc " +
176 "uid upper user userenv " +
177 "variance vsize";
178
179 var cTypes = "bfile blob " +
180 "character clob " +
181 "dec " +
182 "float " +
183 "int integer " +
184 "mlslabel " +
185 "natural naturaln nchar nclob number numeric nvarchar2 " +
186 "real rowtype " +
187 "signtype smallint string " +
188 "varchar varchar2";
189
190 var cSqlplus = "appinfo arraysize autocommit autoprint autorecovery autotrace " +
191 "blockterminator break btitle " +
192 "cmdsep colsep compatibility compute concat copycommit copytypecheck " +
193 "define describe " +
194 "echo editfile embedded escape exec execute " +
195 "feedback flagger flush " +
196 "heading headsep " +
197 "instance " +
198 "linesize lno loboffset logsource long longchunksize " +
199 "markup " +
200 "native newpage numformat numwidth " +
201 "pagesize pause pno " +
202 "recsep recsepchar release repfooter repheader " +
203 "serveroutput shiftinout show showmode size spool sqlblanklines sqlcase sqlcode sqlcontinue sqlnumber " +
204 "sqlpluscompatibility sqlprefix sqlprompt sqlterminator suffix " +
205 "tab term termout time timing trimout trimspool ttitle " +
206 "underline " +
207 "verify version " +
208 "wrap";
209
210 CodeMirror.defineMIME("text/x-plsql", {
211 name: "plsql",
212 keywords: keywords(cKeywords),
213 functions: keywords(cFunctions),
214 types: keywords(cTypes),
215 sqlplus: keywords(cSqlplus)
216 });
217 }());
@@ -0,0 +1,40
1 <!doctype html>
2 <html>
3 <head>
4 <title>CodeMirror: Properties files mode</title>
5 <link rel="stylesheet" href="../../lib/codemirror.css">
6 <script src="../../lib/codemirror.js"></script>
7 <script src="properties.js"></script>
8 <style>.CodeMirror {border-top: 1px solid #ddd; border-bottom: 1px solid #ddd;}</style>
9 <link rel="stylesheet" href="../../doc/docs.css">
10 </head>
11 <body>
12 <h1>CodeMirror: Properties files mode</h1>
13 <form><textarea id="code" name="code">
14 # This is a properties file
15 a.key = A value
16 another.key = http://example.com
17 ! Exclamation mark as comment
18 but.not=Within ! A value # indeed
19 # Spaces at the beginning of a line
20 spaces.before.key=value
21 backslash=Used for multi\
22 line entries,\
23 that's convenient.
24 # Unicode sequences
25 unicode.key=This is \u0020 Unicode
26 no.multiline=here
27 # Colons
28 colons : can be used too
29 # Spaces
30 spaces\ in\ keys=Not very common...
31 </textarea></form>
32 <script>
33 var editor = CodeMirror.fromTextArea(document.getElementById("code"), {});
34 </script>
35
36 <p><strong>MIME types defined:</strong> <code>text/x-properties</code>,
37 <code>text/x-ini</code>.</p>
38
39 </body>
40 </html>
@@ -0,0 +1,63
1 CodeMirror.defineMode("properties", function() {
2 return {
3 token: function(stream, state) {
4 var sol = stream.sol() || state.afterSection;
5 var eol = stream.eol();
6
7 state.afterSection = false;
8
9 if (sol) {
10 if (state.nextMultiline) {
11 state.inMultiline = true;
12 state.nextMultiline = false;
13 } else {
14 state.position = "def";
15 }
16 }
17
18 if (eol && ! state.nextMultiline) {
19 state.inMultiline = false;
20 state.position = "def";
21 }
22
23 if (sol) {
24 while(stream.eatSpace());
25 }
26
27 var ch = stream.next();
28
29 if (sol && (ch === "#" || ch === "!" || ch === ";")) {
30 state.position = "comment";
31 stream.skipToEnd();
32 return "comment";
33 } else if (sol && ch === "[") {
34 state.afterSection = true;
35 stream.skipTo("]"); stream.eat("]");
36 return "header";
37 } else if (ch === "=" || ch === ":") {
38 state.position = "quote";
39 return null;
40 } else if (ch === "\\" && state.position === "quote") {
41 if (stream.next() !== "u") { // u = Unicode sequence \u1234
42 // Multiline value
43 state.nextMultiline = true;
44 }
45 }
46
47 return state.position;
48 },
49
50 startState: function() {
51 return {
52 position : "def", // Current position, "def", "quote" or "comment"
53 nextMultiline : false, // Is the next line multiline value
54 inMultiline : false, // Is the current line a multiline value
55 afterSection : false // Did we just open a section
56 };
57 }
58
59 };
60 });
61
62 CodeMirror.defineMIME("text/x-properties", "properties");
63 CodeMirror.defineMIME("text/x-ini", "properties");
@@ -0,0 +1,24
1 Copyright (c) 2011, Ubalo, Inc.
2 All rights reserved.
3
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions are met:
6 * Redistributions of source code must retain the above copyright
7 notice, this list of conditions and the following disclaimer.
8 * Redistributions in binary form must reproduce the above copyright
9 notice, this list of conditions and the following disclaimer in the
10 documentation and/or other materials provided with the distribution.
11 * Neither the name of the Ubalo, Inc nor the names of its
12 contributors may be used to endorse or promote products derived
13 from this software without specific prior written permission.
14
15 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 DISCLAIMED. IN NO EVENT SHALL UBALO, INC BE LIABLE FOR ANY
19 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,73
1 <!doctype html>
2 <html>
3 <head>
4 <title>CodeMirror: R mode</title>
5 <link rel="stylesheet" href="../../lib/codemirror.css">
6 <script src="../../lib/codemirror.js"></script>
7 <script src="r.js"></script>
8 <style>
9 .CodeMirror { border-top: 1px solid silver; border-bottom: 1px solid silver; }
10 .cm-s-default span.cm-semi { color: blue; font-weight: bold; }
11 .cm-s-default span.cm-dollar { color: orange; font-weight: bold; }
12 .cm-s-default span.cm-arrow { color: brown; }
13 .cm-s-default span.cm-arg-is { color: brown; }
14 </style>
15 <link rel="stylesheet" href="../../doc/docs.css">
16 </head>
17 <body>
18 <h1>CodeMirror: R mode</h1>
19 <form><textarea id="code" name="code">
20 # Code from http://www.mayin.org/ajayshah/KB/R/
21
22 # FIRST LEARN ABOUT LISTS --
23 X = list(height=5.4, weight=54)
24 print("Use default printing --")
25 print(X)
26 print("Accessing individual elements --")
27 cat("Your height is ", X$height, " and your weight is ", X$weight, "\n")
28
29 # FUNCTIONS --
30 square <- function(x) {
31 return(x*x)
32 }
33 cat("The square of 3 is ", square(3), "\n")
34
35 # default value of the arg is set to 5.
36 cube <- function(x=5) {
37 return(x*x*x);
38 }
39 cat("Calling cube with 2 : ", cube(2), "\n") # will give 2^3
40 cat("Calling cube : ", cube(), "\n") # will default to 5^3.
41
42 # LEARN ABOUT FUNCTIONS THAT RETURN MULTIPLE OBJECTS --
43 powers <- function(x) {
44 parcel = list(x2=x*x, x3=x*x*x, x4=x*x*x*x);
45 return(parcel);
46 }
47
48 X = powers(3);
49 print("Showing powers of 3 --"); print(X);
50
51 # WRITING THIS COMPACTLY (4 lines instead of 7)
52
53 powerful <- function(x) {
54 return(list(x2=x*x, x3=x*x*x, x4=x*x*x*x));
55 }
56 print("Showing powers of 3 --"); print(powerful(3));
57
58 # In R, the last expression in a function is, by default, what is
59 # returned. So you could equally just say:
60 powerful <- function(x) {list(x2=x*x, x3=x*x*x, x4=x*x*x*x)}
61 </textarea></form>
62 <script>
63 var editor = CodeMirror.fromTextArea(document.getElementById("code"), {});
64 </script>
65
66 <p><strong>MIME types defined:</strong> <code>text/x-rsrc</code>.</p>
67
68 <p>Development of the CodeMirror R mode was kindly sponsored
69 by <a href="http://ubalo.com/">Ubalo</a>, who hold
70 the <a href="LICENSE">license</a>.</p>
71
72 </body>
73 </html>
@@ -0,0 +1,141
1 CodeMirror.defineMode("r", function(config) {
2 function wordObj(str) {
3 var words = str.split(" "), res = {};
4 for (var i = 0; i < words.length; ++i) res[words[i]] = true;
5 return res;
6 }
7 var atoms = wordObj("NULL NA Inf NaN NA_integer_ NA_real_ NA_complex_ NA_character_");
8 var builtins = wordObj("list quote bquote eval return call parse deparse");
9 var keywords = wordObj("if else repeat while function for in next break");
10 var blockkeywords = wordObj("if else repeat while function for");
11 var opChars = /[+\-*\/^<>=!&|~$:]/;
12 var curPunc;
13
14 function tokenBase(stream, state) {
15 curPunc = null;
16 var ch = stream.next();
17 if (ch == "#") {
18 stream.skipToEnd();
19 return "comment";
20 } else if (ch == "0" && stream.eat("x")) {
21 stream.eatWhile(/[\da-f]/i);
22 return "number";
23 } else if (ch == "." && stream.eat(/\d/)) {
24 stream.match(/\d*(?:e[+\-]?\d+)?/);
25 return "number";
26 } else if (/\d/.test(ch)) {
27 stream.match(/\d*(?:\.\d+)?(?:e[+\-]\d+)?L?/);
28 return "number";
29 } else if (ch == "'" || ch == '"') {
30 state.tokenize = tokenString(ch);
31 return "string";
32 } else if (ch == "." && stream.match(/.[.\d]+/)) {
33 return "keyword";
34 } else if (/[\w\.]/.test(ch) && ch != "_") {
35 stream.eatWhile(/[\w\.]/);
36 var word = stream.current();
37 if (atoms.propertyIsEnumerable(word)) return "atom";
38 if (keywords.propertyIsEnumerable(word)) {
39 if (blockkeywords.propertyIsEnumerable(word)) curPunc = "block";
40 return "keyword";
41 }
42 if (builtins.propertyIsEnumerable(word)) return "builtin";
43 return "variable";
44 } else if (ch == "%") {
45 if (stream.skipTo("%")) stream.next();
46 return "variable-2";
47 } else if (ch == "<" && stream.eat("-")) {
48 return "arrow";
49 } else if (ch == "=" && state.ctx.argList) {
50 return "arg-is";
51 } else if (opChars.test(ch)) {
52 if (ch == "$") return "dollar";
53 stream.eatWhile(opChars);
54 return "operator";
55 } else if (/[\(\){}\[\];]/.test(ch)) {
56 curPunc = ch;
57 if (ch == ";") return "semi";
58 return null;
59 } else {
60 return null;
61 }
62 }
63
64 function tokenString(quote) {
65 return function(stream, state) {
66 if (stream.eat("\\")) {
67 var ch = stream.next();
68 if (ch == "x") stream.match(/^[a-f0-9]{2}/i);
69 else if ((ch == "u" || ch == "U") && stream.eat("{") && stream.skipTo("}")) stream.next();
70 else if (ch == "u") stream.match(/^[a-f0-9]{4}/i);
71 else if (ch == "U") stream.match(/^[a-f0-9]{8}/i);
72 else if (/[0-7]/.test(ch)) stream.match(/^[0-7]{1,2}/);
73 return "string-2";
74 } else {
75 var next;
76 while ((next = stream.next()) != null) {
77 if (next == quote) { state.tokenize = tokenBase; break; }
78 if (next == "\\") { stream.backUp(1); break; }
79 }
80 return "string";
81 }
82 };
83 }
84
85 function push(state, type, stream) {
86 state.ctx = {type: type,
87 indent: state.indent,
88 align: null,
89 column: stream.column(),
90 prev: state.ctx};
91 }
92 function pop(state) {
93 state.indent = state.ctx.indent;
94 state.ctx = state.ctx.prev;
95 }
96
97 return {
98 startState: function(base) {
99 return {tokenize: tokenBase,
100 ctx: {type: "top",
101 indent: -config.indentUnit,
102 align: false},
103 indent: 0,
104 afterIdent: false};
105 },
106
107 token: function(stream, state) {
108 if (stream.sol()) {
109 if (state.ctx.align == null) state.ctx.align = false;
110 state.indent = stream.indentation();
111 }
112 if (stream.eatSpace()) return null;
113 var style = state.tokenize(stream, state);
114 if (style != "comment" && state.ctx.align == null) state.ctx.align = true;
115
116 var ctype = state.ctx.type;
117 if ((curPunc == ";" || curPunc == "{" || curPunc == "}") && ctype == "block") pop(state);
118 if (curPunc == "{") push(state, "}", stream);
119 else if (curPunc == "(") {
120 push(state, ")", stream);
121 if (state.afterIdent) state.ctx.argList = true;
122 }
123 else if (curPunc == "[") push(state, "]", stream);
124 else if (curPunc == "block") push(state, "block", stream);
125 else if (curPunc == ctype) pop(state);
126 state.afterIdent = style == "variable" || style == "keyword";
127 return style;
128 },
129
130 indent: function(state, textAfter) {
131 if (state.tokenize != tokenBase) return 0;
132 var firstChar = textAfter && textAfter.charAt(0), ctx = state.ctx,
133 closing = firstChar == ctx.type;
134 if (ctx.type == "block") return ctx.indent + (firstChar == "{" ? 0 : config.indentUnit);
135 else if (ctx.align) return ctx.column + (closing ? 0 : 1);
136 else return ctx.indent + (closing ? 0 : config.indentUnit);
137 }
138 };
139 });
140
141 CodeMirror.defineMIME("text/x-rsrc", "r");
@@ -0,0 +1,19
1 CodeMirror.defineMode("changes", function(config, modeConfig) {
2 var headerSeperator = /^-+$/;
3 var headerLine = /^(Mon|Tue|Wed|Thu|Fri|Sat|Sun) (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) ?\d{1,2} \d{2}:\d{2}(:\d{2})? [A-Z]{3,4} \d{4} - /;
4 var simpleEmail = /^[\w+.-]+@[\w.-]+/;
5
6 return {
7 token: function(stream) {
8 if (stream.sol()) {
9 if (stream.match(headerSeperator)) { return 'tag'; }
10 if (stream.match(headerLine)) { return 'tag'; }
11 }
12 if (stream.match(simpleEmail)) { return 'string'; }
13 stream.next();
14 return null;
15 }
16 };
17 });
18
19 CodeMirror.defineMIME("text/x-rpm-changes", "changes");
@@ -0,0 +1,53
1 <!doctype html>
2 <html>
3 <head>
4 <title>CodeMirror: RPM changes mode</title>
5 <link rel="stylesheet" href="../../../lib/codemirror.css">
6 <script src="../../../lib/codemirror.js"></script>
7 <script src="changes.js"></script>
8 <link rel="stylesheet" href="../../../doc/docs.css">
9 <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
10 </head>
11 <body>
12 <h1>CodeMirror: RPM changes mode</h1>
13
14 <div><textarea id="code" name="code">
15 -------------------------------------------------------------------
16 Tue Oct 18 13:58:40 UTC 2011 - misterx@example.com
17
18 - Update to r60.3
19 - Fixes bug in the reflect package
20 * disallow Interface method on Value obtained via unexported name
21
22 -------------------------------------------------------------------
23 Thu Oct 6 08:14:24 UTC 2011 - misterx@example.com
24
25 - Update to r60.2
26 - Fixes memory leak in certain map types
27
28 -------------------------------------------------------------------
29 Wed Oct 5 14:34:10 UTC 2011 - misterx@example.com
30
31 - Tweaks for gdb debugging
32 - go.spec changes:
33 - move %go_arch definition to %prep section
34 - pass correct location of go specific gdb pretty printer and
35 functions to cpp as HOST_EXTRA_CFLAGS macro
36 - install go gdb functions & printer
37 - gdb-printer.patch
38 - patch linker (src/cmd/ld/dwarf.c) to emit correct location of go
39 gdb functions and pretty printer
40 </textarea></div>
41 <script>
42 var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
43 mode: {name: "changes"},
44 lineNumbers: true,
45 indentUnit: 4,
46 tabMode: "shift",
47 matchBrackets: true
48 });
49 </script>
50
51 <p><strong>MIME types defined:</strong> <code>text/x-rpm-changes</code>.</p>
52 </body>
53 </html>
@@ -0,0 +1,99
1 <!doctype html>
2 <html>
3 <head>
4 <title>CodeMirror: RPM spec mode</title>
5 <link rel="stylesheet" href="../../../lib/codemirror.css">
6 <script src="../../../lib/codemirror.js"></script>
7 <script src="spec.js"></script>
8 <link rel="stylesheet" href="spec.css">
9 <link rel="stylesheet" href="../../../doc/docs.css">
10 <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
11 </head>
12 <body>
13 <h1>CodeMirror: RPM spec mode</h1>
14
15 <div><textarea id="code" name="code">
16 #
17 # spec file for package minidlna
18 #
19 # Copyright (c) 2011, Sascha Peilicke <saschpe@gmx.de>
20 #
21 # All modifications and additions to the file contributed by third parties
22 # remain the property of their copyright owners, unless otherwise agreed
23 # upon. The license for this file, and modifications and additions to the
24 # file, is the same license as for the pristine package itself (unless the
25 # license for the pristine package is not an Open Source License, in which
26 # case the license is the MIT License). An "Open Source License" is a
27 # license that conforms to the Open Source Definition (Version 1.9)
28 # published by the Open Source Initiative.
29
30
31 Name: libupnp6
32 Version: 1.6.13
33 Release: 0
34 Summary: Portable Universal Plug and Play (UPnP) SDK
35 Group: System/Libraries
36 License: BSD-3-Clause
37 Url: http://sourceforge.net/projects/pupnp/
38 Source0: http://downloads.sourceforge.net/pupnp/libupnp-%{version}.tar.bz2
39 BuildRoot: %{_tmppath}/%{name}-%{version}-build
40
41 %description
42 The portable Universal Plug and Play (UPnP) SDK provides support for building
43 UPnP-compliant control points, devices, and bridges on several operating
44 systems.
45
46 %package -n libupnp-devel
47 Summary: Portable Universal Plug and Play (UPnP) SDK
48 Group: Development/Libraries/C and C++
49 Provides: pkgconfig(libupnp)
50 Requires: %{name} = %{version}
51
52 %description -n libupnp-devel
53 The portable Universal Plug and Play (UPnP) SDK provides support for building
54 UPnP-compliant control points, devices, and bridges on several operating
55 systems.
56
57 %prep
58 %setup -n libupnp-%{version}
59
60 %build
61 %configure --disable-static
62 make %{?_smp_mflags}
63
64 %install
65 %makeinstall
66 find %{buildroot} -type f -name '*.la' -exec rm -f {} ';'
67
68 %post -p /sbin/ldconfig
69
70 %postun -p /sbin/ldconfig
71
72 %files
73 %defattr(-,root,root,-)
74 %doc ChangeLog NEWS README TODO
75 %{_libdir}/libixml.so.*
76 %{_libdir}/libthreadutil.so.*
77 %{_libdir}/libupnp.so.*
78
79 %files -n libupnp-devel
80 %defattr(-,root,root,-)
81 %{_libdir}/pkgconfig/libupnp.pc
82 %{_libdir}/libixml.so
83 %{_libdir}/libthreadutil.so
84 %{_libdir}/libupnp.so
85 %{_includedir}/upnp/
86
87 %changelog</textarea></div>
88 <script>
89 var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
90 mode: {name: "spec"},
91 lineNumbers: true,
92 indentUnit: 4,
93 matchBrackets: true
94 });
95 </script>
96
97 <p><strong>MIME types defined:</strong> <code>text/x-rpm-spec</code>.</p>
98 </body>
99 </html>
@@ -0,0 +1,5
1 .cm-s-default span.cm-preamble {color: #b26818; font-weight: bold;}
2 .cm-s-default span.cm-macro {color: #b218b2;}
3 .cm-s-default span.cm-section {color: green; font-weight: bold;}
4 .cm-s-default span.cm-script {color: red;}
5 .cm-s-default span.cm-issue {color: yellow;}
@@ -0,0 +1,66
1 // Quick and dirty spec file highlighting
2
3 CodeMirror.defineMode("spec", function(config, modeConfig) {
4 var arch = /^(i386|i586|i686|x86_64|ppc64|ppc|ia64|s390x|s390|sparc64|sparcv9|sparc|noarch|alphaev6|alpha|hppa|mipsel)/;
5
6 var preamble = /^(Name|Version|Release|License|Summary|Url|Group|Source|BuildArch|BuildRequires|BuildRoot|AutoReqProv|Provides|Requires(\(\w+\))?|Obsoletes|Conflicts|Recommends|Source\d*|Patch\d*|ExclusiveArch|NoSource|Supplements):/;
7 var section = /^%(debug_package|package|description|prep|build|install|files|clean|changelog|preun|postun|pre|post|triggerin|triggerun|pretrans|posttrans|verifyscript|check|triggerpostun|triggerprein|trigger)/;
8 var control_flow_complex = /^%(ifnarch|ifarch|if)/; // rpm control flow macros
9 var control_flow_simple = /^%(else|endif)/; // rpm control flow macros
10 var operators = /^(\!|\?|\<\=|\<|\>\=|\>|\=\=|\&\&|\|\|)/; // operators in control flow macros
11
12 return {
13 startState: function () {
14 return {
15 controlFlow: false,
16 macroParameters: false,
17 section: false
18 };
19 },
20 token: function (stream, state) {
21 var ch = stream.peek();
22 if (ch == "#") { stream.skipToEnd(); return "comment"; }
23
24 if (stream.sol()) {
25 if (stream.match(preamble)) { return "preamble"; }
26 if (stream.match(section)) { return "section"; }
27 }
28
29 if (stream.match(/^\$\w+/)) { return "def"; } // Variables like '$RPM_BUILD_ROOT'
30 if (stream.match(/^\$\{\w+\}/)) { return "def"; } // Variables like '${RPM_BUILD_ROOT}'
31
32 if (stream.match(control_flow_simple)) { return "keyword"; }
33 if (stream.match(control_flow_complex)) {
34 state.controlFlow = true;
35 return "keyword";
36 }
37 if (state.controlFlow) {
38 if (stream.match(operators)) { return "operator"; }
39 if (stream.match(/^(\d+)/)) { return "number"; }
40 if (stream.eol()) { state.controlFlow = false; }
41 }
42
43 if (stream.match(arch)) { return "number"; }
44
45 // Macros like '%make_install' or '%attr(0775,root,root)'
46 if (stream.match(/^%[\w]+/)) {
47 if (stream.match(/^\(/)) { state.macroParameters = true; }
48 return "macro";
49 }
50 if (state.macroParameters) {
51 if (stream.match(/^\d+/)) { return "number";}
52 if (stream.match(/^\)/)) {
53 state.macroParameters = false;
54 return "macro";
55 }
56 }
57 if (stream.match(/^%\{\??[\w \-]+\}/)) { return "macro"; } // Macros like '%{defined fedora}'
58
59 //TODO: Include bash script sub-parser (CodeMirror supports that)
60 stream.next();
61 return null;
62 }
63 };
64 });
65
66 CodeMirror.defineMIME("text/x-rpm-spec", "spec");
@@ -0,0 +1,24
1 Copyright (c) 2011, Ubalo, Inc.
2 All rights reserved.
3
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions are met:
6 * Redistributions of source code must retain the above copyright
7 notice, this list of conditions and the following disclaimer.
8 * Redistributions in binary form must reproduce the above copyright
9 notice, this list of conditions and the following disclaimer in the
10 documentation and/or other materials provided with the distribution.
11 * Neither the name of the Ubalo, Inc. nor the names of its
12 contributors may be used to endorse or promote products derived
13 from this software without specific prior written permission.
14
15 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 DISCLAIMED. IN NO EVENT SHALL UBALO, INC BE LIABLE FOR ANY
19 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,171
1 <!doctype html>
2 <html>
3 <head>
4 <title>CodeMirror: Ruby mode</title>
5 <link rel="stylesheet" href="../../lib/codemirror.css">
6 <script src="../../lib/codemirror.js"></script>
7 <script src="ruby.js"></script>
8 <style>
9 .CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}
10 .cm-s-default span.cm-arrow { color: red; }
11 </style>
12 <link rel="stylesheet" href="../../doc/docs.css">
13 </head>
14 <body>
15 <h1>CodeMirror: Ruby mode</h1>
16 <form><textarea id="code" name="code">
17 # Code from http://sandbox.mc.edu/~bennet/ruby/code/poly_rb.html
18 #
19 # This program evaluates polynomials. It first asks for the coefficients
20 # of a polynomial, which must be entered on one line, highest-order first.
21 # It then requests values of x and will compute the value of the poly for
22 # each x. It will repeatly ask for x values, unless you the user enters
23 # a blank line. It that case, it will ask for another polynomial. If the
24 # user types quit for either input, the program immediately exits.
25 #
26
27 #
28 # Function to evaluate a polynomial at x. The polynomial is given
29 # as a list of coefficients, from the greatest to the least.
30 def polyval(x, coef)
31 sum = 0
32 coef = coef.clone # Don't want to destroy the original
33 while true
34 sum += coef.shift # Add and remove the next coef
35 break if coef.empty? # If no more, done entirely.
36 sum *= x # This happens the right number of times.
37 end
38 return sum
39 end
40
41 #
42 # Function to read a line containing a list of integers and return
43 # them as an array of integers. If the string conversion fails, it
44 # throws TypeError. If the input line is the word 'quit', then it
45 # converts it to an end-of-file exception
46 def readints(prompt)
47 # Read a line
48 print prompt
49 line = readline.chomp
50 raise EOFError.new if line == 'quit' # You can also use a real EOF.
51
52 # Go through each item on the line, converting each one and adding it
53 # to retval.
54 retval = [ ]
55 for str in line.split(/\s+/)
56 if str =~ /^\-?\d+$/
57 retval.push(str.to_i)
58 else
59 raise TypeError.new
60 end
61 end
62
63 return retval
64 end
65
66 #
67 # Take a coeff and an exponent and return the string representation, ignoring
68 # the sign of the coefficient.
69 def term_to_str(coef, exp)
70 ret = ""
71
72 # Show coeff, unless it's 1 or at the right
73 coef = coef.abs
74 ret = coef.to_s unless coef == 1 && exp > 0
75 ret += "x" if exp > 0 # x if exponent not 0
76 ret += "^" + exp.to_s if exp > 1 # ^exponent, if > 1.
77
78 return ret
79 end
80
81 #
82 # Create a string of the polynomial in sort-of-readable form.
83 def polystr(p)
84 # Get the exponent of first coefficient, plus 1.
85 exp = p.length
86
87 # Assign exponents to each term, making pairs of coeff and exponent,
88 # Then get rid of the zero terms.
89 p = (p.map { |c| exp -= 1; [ c, exp ] }).select { |p| p[0] != 0 }
90
91 # If there's nothing left, it's a zero
92 return "0" if p.empty?
93
94 # *** Now p is a non-empty list of [ coef, exponent ] pairs. ***
95
96 # Convert the first term, preceded by a "-" if it's negative.
97 result = (if p[0][0] < 0 then "-" else "" end) + term_to_str(*p[0])
98
99 # Convert the rest of the terms, in each case adding the appropriate
100 # + or - separating them.
101 for term in p[1...p.length]
102 # Add the separator then the rep. of the term.
103 result += (if term[0] < 0 then " - " else " + " end) +
104 term_to_str(*term)
105 end
106
107 return result
108 end
109
110 #
111 # Run until some kind of endfile.
112 begin
113 # Repeat until an exception or quit gets us out.
114 while true
115 # Read a poly until it works. An EOF will except out of the
116 # program.
117 print "\n"
118 begin
119 poly = readints("Enter a polynomial coefficients: ")
120 rescue TypeError
121 print "Try again.\n"
122 retry
123 end
124 break if poly.empty?
125
126 # Read and evaluate x values until the user types a blank line.
127 # Again, an EOF will except out of the pgm.
128 while true
129 # Request an integer.
130 print "Enter x value or blank line: "
131 x = readline.chomp
132 break if x == ''
133 raise EOFError.new if x == 'quit'
134
135 # If it looks bad, let's try again.
136 if x !~ /^\-?\d+$/
137 print "That doesn't look like an integer. Please try again.\n"
138 next
139 end
140
141 # Convert to an integer and print the result.
142 x = x.to_i
143 print "p(x) = ", polystr(poly), "\n"
144 print "p(", x, ") = ", polyval(x, poly), "\n"
145 end
146 end
147 rescue EOFError
148 print "\n=== EOF ===\n"
149 rescue Interrupt, SignalException
150 print "\n=== Interrupted ===\n"
151 else
152 print "--- Bye ---\n"
153 end
154 </textarea></form>
155 <script>
156 var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
157 mode: "text/x-ruby",
158 tabMode: "indent",
159 matchBrackets: true,
160 indentUnit: 4
161 });
162 </script>
163
164 <p><strong>MIME types defined:</strong> <code>text/x-ruby</code>.</p>
165
166 <p>Development of the CodeMirror Ruby mode was kindly sponsored
167 by <a href="http://ubalo.com/">Ubalo</a>, who hold
168 the <a href="LICENSE">license</a>.</p>
169
170 </body>
171 </html>
@@ -0,0 +1,195
1 CodeMirror.defineMode("ruby", function(config, parserConfig) {
2 function wordObj(words) {
3 var o = {};
4 for (var i = 0, e = words.length; i < e; ++i) o[words[i]] = true;
5 return o;
6 }
7 var keywords = wordObj([
8 "alias", "and", "BEGIN", "begin", "break", "case", "class", "def", "defined?", "do", "else",
9 "elsif", "END", "end", "ensure", "false", "for", "if", "in", "module", "next", "not", "or",
10 "redo", "rescue", "retry", "return", "self", "super", "then", "true", "undef", "unless",
11 "until", "when", "while", "yield", "nil", "raise", "throw", "catch", "fail", "loop", "callcc",
12 "caller", "lambda", "proc", "public", "protected", "private", "require", "load",
13 "require_relative", "extend", "autoload"
14 ]);
15 var indentWords = wordObj(["def", "class", "case", "for", "while", "do", "module", "then",
16 "catch", "loop", "proc", "begin"]);
17 var dedentWords = wordObj(["end", "until"]);
18 var matching = {"[": "]", "{": "}", "(": ")"};
19 var curPunc;
20
21 function chain(newtok, stream, state) {
22 state.tokenize.push(newtok);
23 return newtok(stream, state);
24 }
25
26 function tokenBase(stream, state) {
27 curPunc = null;
28 if (stream.sol() && stream.match("=begin") && stream.eol()) {
29 state.tokenize.push(readBlockComment);
30 return "comment";
31 }
32 if (stream.eatSpace()) return null;
33 var ch = stream.next(), m;
34 if (ch == "`" || ch == "'" || ch == '"' ||
35 (ch == "/" && !stream.eol() && stream.peek() != " ")) {
36 return chain(readQuoted(ch, "string", ch == '"' || ch == "`"), stream, state);
37 } else if (ch == "%") {
38 var style, embed = false;
39 if (stream.eat("s")) style = "atom";
40 else if (stream.eat(/[WQ]/)) { style = "string"; embed = true; }
41 else if (stream.eat(/[wxqr]/)) style = "string";
42 var delim = stream.eat(/[^\w\s]/);
43 if (!delim) return "operator";
44 if (matching.propertyIsEnumerable(delim)) delim = matching[delim];
45 return chain(readQuoted(delim, style, embed, true), stream, state);
46 } else if (ch == "#") {
47 stream.skipToEnd();
48 return "comment";
49 } else if (ch == "<" && (m = stream.match(/^<-?[\`\"\']?([a-zA-Z_?]\w*)[\`\"\']?(?:;|$)/))) {
50 return chain(readHereDoc(m[1]), stream, state);
51 } else if (ch == "0") {
52 if (stream.eat("x")) stream.eatWhile(/[\da-fA-F]/);
53 else if (stream.eat("b")) stream.eatWhile(/[01]/);
54 else stream.eatWhile(/[0-7]/);
55 return "number";
56 } else if (/\d/.test(ch)) {
57 stream.match(/^[\d_]*(?:\.[\d_]+)?(?:[eE][+\-]?[\d_]+)?/);
58 return "number";
59 } else if (ch == "?") {
60 while (stream.match(/^\\[CM]-/)) {}
61 if (stream.eat("\\")) stream.eatWhile(/\w/);
62 else stream.next();
63 return "string";
64 } else if (ch == ":") {
65 if (stream.eat("'")) return chain(readQuoted("'", "atom", false), stream, state);
66 if (stream.eat('"')) return chain(readQuoted('"', "atom", true), stream, state);
67 stream.eatWhile(/[\w\?]/);
68 return "atom";
69 } else if (ch == "@") {
70 stream.eat("@");
71 stream.eatWhile(/[\w\?]/);
72 return "variable-2";
73 } else if (ch == "$") {
74 stream.next();
75 stream.eatWhile(/[\w\?]/);
76 return "variable-3";
77 } else if (/\w/.test(ch)) {
78 stream.eatWhile(/[\w\?]/);
79 if (stream.eat(":")) return "atom";
80 return "ident";
81 } else if (ch == "|" && (state.varList || state.lastTok == "{" || state.lastTok == "do")) {
82 curPunc = "|";
83 return null;
84 } else if (/[\(\)\[\]{}\\;]/.test(ch)) {
85 curPunc = ch;
86 return null;
87 } else if (ch == "-" && stream.eat(">")) {
88 return "arrow";
89 } else if (/[=+\-\/*:\.^%<>~|]/.test(ch)) {
90 stream.eatWhile(/[=+\-\/*:\.^%<>~|]/);
91 return "operator";
92 } else {
93 return null;
94 }
95 }
96
97 function tokenBaseUntilBrace() {
98 var depth = 1;
99 return function(stream, state) {
100 if (stream.peek() == "}") {
101 depth--;
102 if (depth == 0) {
103 state.tokenize.pop();
104 return state.tokenize[state.tokenize.length-1](stream, state);
105 }
106 } else if (stream.peek() == "{") {
107 depth++;
108 }
109 return tokenBase(stream, state);
110 };
111 }
112 function readQuoted(quote, style, embed, unescaped) {
113 return function(stream, state) {
114 var escaped = false, ch;
115 while ((ch = stream.next()) != null) {
116 if (ch == quote && (unescaped || !escaped)) {
117 state.tokenize.pop();
118 break;
119 }
120 if (embed && ch == "#" && !escaped && stream.eat("{")) {
121 state.tokenize.push(tokenBaseUntilBrace(arguments.callee));
122 break;
123 }
124 escaped = !escaped && ch == "\\";
125 }
126 return style;
127 };
128 }
129 function readHereDoc(phrase) {
130 return function(stream, state) {
131 if (stream.match(phrase)) state.tokenize.pop();
132 else stream.skipToEnd();
133 return "string";
134 };
135 }
136 function readBlockComment(stream, state) {
137 if (stream.sol() && stream.match("=end") && stream.eol())
138 state.tokenize.pop();
139 stream.skipToEnd();
140 return "comment";
141 }
142
143 return {
144 startState: function() {
145 return {tokenize: [tokenBase],
146 indented: 0,
147 context: {type: "top", indented: -config.indentUnit},
148 continuedLine: false,
149 lastTok: null,
150 varList: false};
151 },
152
153 token: function(stream, state) {
154 if (stream.sol()) state.indented = stream.indentation();
155 var style = state.tokenize[state.tokenize.length-1](stream, state), kwtype;
156 if (style == "ident") {
157 var word = stream.current();
158 style = keywords.propertyIsEnumerable(stream.current()) ? "keyword"
159 : /^[A-Z]/.test(word) ? "tag"
160 : (state.lastTok == "def" || state.lastTok == "class" || state.varList) ? "def"
161 : "variable";
162 if (indentWords.propertyIsEnumerable(word)) kwtype = "indent";
163 else if (dedentWords.propertyIsEnumerable(word)) kwtype = "dedent";
164 else if ((word == "if" || word == "unless") && stream.column() == stream.indentation())
165 kwtype = "indent";
166 }
167 if (curPunc || (style && style != "comment")) state.lastTok = word || curPunc || style;
168 if (curPunc == "|") state.varList = !state.varList;
169
170 if (kwtype == "indent" || /[\(\[\{]/.test(curPunc))
171 state.context = {prev: state.context, type: curPunc || style, indented: state.indented};
172 else if ((kwtype == "dedent" || /[\)\]\}]/.test(curPunc)) && state.context.prev)
173 state.context = state.context.prev;
174
175 if (stream.eol())
176 state.continuedLine = (curPunc == "\\" || style == "operator");
177 return style;
178 },
179
180 indent: function(state, textAfter) {
181 if (state.tokenize[state.tokenize.length-1] != tokenBase) return 0;
182 var firstChar = textAfter && textAfter.charAt(0);
183 var ct = state.context;
184 var closing = ct.type == matching[firstChar] ||
185 ct.type == "keyword" && /^(?:end|until|else|elsif|when|rescue)\b/.test(textAfter);
186 return ct.indented + (closing ? 0 : config.indentUnit) +
187 (state.continuedLine ? config.indentUnit : 0);
188 },
189 electricChars: "}de" // enD and rescuE
190
191 };
192 });
193
194 CodeMirror.defineMIME("text/x-ruby", "ruby");
195
@@ -0,0 +1,48
1 <!doctype html>
2 <html>
3 <head>
4 <title>CodeMirror: Rust mode</title>
5 <link rel="stylesheet" href="../../lib/codemirror.css">
6 <script src="../../lib/codemirror.js"></script>
7 <script src="rust.js"></script>
8 <link rel="stylesheet" href="../../doc/docs.css">
9 <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
10 </head>
11 <body>
12 <h1>CodeMirror: Rust mode</h1>
13
14 <div><textarea id="code" name="code">
15 // Demo code.
16
17 type foo<T> = int;
18 enum bar {
19 some(int, foo<float>),
20 none
21 }
22
23 fn check_crate(x: int) {
24 let v = 10;
25 alt foo {
26 1 to 3 {
27 print_foo();
28 if x {
29 blah() + 10;
30 }
31 }
32 (x, y) { "bye" }
33 _ { "hi" }
34 }
35 }
36 </textarea></div>
37
38 <script>
39 var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
40 lineNumbers: true,
41 matchBrackets: true,
42 tabMode: "indent"
43 });
44 </script>
45
46 <p><strong>MIME types defined:</strong> <code>text/x-rustsrc</code>.</p>
47 </body>
48 </html>
@@ -0,0 +1,432
1 CodeMirror.defineMode("rust", function() {
2 var indentUnit = 4, altIndentUnit = 2;
3 var valKeywords = {
4 "if": "if-style", "while": "if-style", "else": "else-style",
5 "do": "else-style", "ret": "else-style", "fail": "else-style",
6 "break": "atom", "cont": "atom", "const": "let", "resource": "fn",
7 "let": "let", "fn": "fn", "for": "for", "alt": "alt", "iface": "iface",
8 "impl": "impl", "type": "type", "enum": "enum", "mod": "mod",
9 "as": "op", "true": "atom", "false": "atom", "assert": "op", "check": "op",
10 "claim": "op", "native": "ignore", "unsafe": "ignore", "import": "else-style",
11 "export": "else-style", "copy": "op", "log": "op", "log_err": "op",
12 "use": "op", "bind": "op", "self": "atom"
13 };
14 var typeKeywords = function() {
15 var keywords = {"fn": "fn", "block": "fn", "obj": "obj"};
16 var atoms = "bool uint int i8 i16 i32 i64 u8 u16 u32 u64 float f32 f64 str char".split(" ");
17 for (var i = 0, e = atoms.length; i < e; ++i) keywords[atoms[i]] = "atom";
18 return keywords;
19 }();
20 var operatorChar = /[+\-*&%=<>!?|\.@]/;
21
22 // Tokenizer
23
24 // Used as scratch variable to communicate multiple values without
25 // consing up tons of objects.
26 var tcat, content;
27 function r(tc, style) {
28 tcat = tc;
29 return style;
30 }
31
32 function tokenBase(stream, state) {
33 var ch = stream.next();
34 if (ch == '"') {
35 state.tokenize = tokenString;
36 return state.tokenize(stream, state);
37 }
38 if (ch == "'") {
39 tcat = "atom";
40 if (stream.eat("\\")) {
41 if (stream.skipTo("'")) { stream.next(); return "string"; }
42 else { return "error"; }
43 } else {
44 stream.next();
45 return stream.eat("'") ? "string" : "error";
46 }
47 }
48 if (ch == "/") {
49 if (stream.eat("/")) { stream.skipToEnd(); return "comment"; }
50 if (stream.eat("*")) {
51 state.tokenize = tokenComment(1);
52 return state.tokenize(stream, state);
53 }
54 }
55 if (ch == "#") {
56 if (stream.eat("[")) { tcat = "open-attr"; return null; }
57 stream.eatWhile(/\w/);
58 return r("macro", "meta");
59 }
60 if (ch == ":" && stream.match(":<")) {
61 return r("op", null);
62 }
63 if (ch.match(/\d/) || (ch == "." && stream.eat(/\d/))) {
64 var flp = false;
65 if (!stream.match(/^x[\da-f]+/i) && !stream.match(/^b[01]+/)) {
66 stream.eatWhile(/\d/);
67 if (stream.eat(".")) { flp = true; stream.eatWhile(/\d/); }
68 if (stream.match(/^e[+\-]?\d+/i)) { flp = true; }
69 }
70 if (flp) stream.match(/^f(?:32|64)/);
71 else stream.match(/^[ui](?:8|16|32|64)/);
72 return r("atom", "number");
73 }
74 if (ch.match(/[()\[\]{}:;,]/)) return r(ch, null);
75 if (ch == "-" && stream.eat(">")) return r("->", null);
76 if (ch.match(operatorChar)) {
77 stream.eatWhile(operatorChar);
78 return r("op", null);
79 }
80 stream.eatWhile(/\w/);
81 content = stream.current();
82 if (stream.match(/^::\w/)) {
83 stream.backUp(1);
84 return r("prefix", "variable-2");
85 }
86 if (state.keywords.propertyIsEnumerable(content))
87 return r(state.keywords[content], content.match(/true|false/) ? "atom" : "keyword");
88 return r("name", "variable");
89 }
90
91 function tokenString(stream, state) {
92 var ch, escaped = false;
93 while (ch = stream.next()) {
94 if (ch == '"' && !escaped) {
95 state.tokenize = tokenBase;
96 return r("atom", "string");
97 }
98 escaped = !escaped && ch == "\\";
99 }
100 // Hack to not confuse the parser when a string is split in
101 // pieces.
102 return r("op", "string");
103 }
104
105 function tokenComment(depth) {
106 return function(stream, state) {
107 var lastCh = null, ch;
108 while (ch = stream.next()) {
109 if (ch == "/" && lastCh == "*") {
110 if (depth == 1) {
111 state.tokenize = tokenBase;
112 break;
113 } else {
114 state.tokenize = tokenComment(depth - 1);
115 return state.tokenize(stream, state);
116 }
117 }
118 if (ch == "*" && lastCh == "/") {
119 state.tokenize = tokenComment(depth + 1);
120 return state.tokenize(stream, state);
121 }
122 lastCh = ch;
123 }
124 return "comment";
125 };
126 }
127
128 // Parser
129
130 var cx = {state: null, stream: null, marked: null, cc: null};
131 function pass() {
132 for (var i = arguments.length - 1; i >= 0; i--) cx.cc.push(arguments[i]);
133 }
134 function cont() {
135 pass.apply(null, arguments);
136 return true;
137 }
138
139 function pushlex(type, info) {
140 var result = function() {
141 var state = cx.state;
142 state.lexical = {indented: state.indented, column: cx.stream.column(),
143 type: type, prev: state.lexical, info: info};
144 };
145 result.lex = true;
146 return result;
147 }
148 function poplex() {
149 var state = cx.state;
150 if (state.lexical.prev) {
151 if (state.lexical.type == ")")
152 state.indented = state.lexical.indented;
153 state.lexical = state.lexical.prev;
154 }
155 }
156 function typecx() { cx.state.keywords = typeKeywords; }
157 function valcx() { cx.state.keywords = valKeywords; }
158 poplex.lex = typecx.lex = valcx.lex = true;
159
160 function commasep(comb, end) {
161 function more(type) {
162 if (type == ",") return cont(comb, more);
163 if (type == end) return cont();
164 return cont(more);
165 }
166 return function(type) {
167 if (type == end) return cont();
168 return pass(comb, more);
169 };
170 }
171
172 function stat_of(comb, tag) {
173 return cont(pushlex("stat", tag), comb, poplex, block);
174 }
175 function block(type) {
176 if (type == "}") return cont();
177 if (type == "let") return stat_of(letdef1, "let");
178 if (type == "fn") return stat_of(fndef);
179 if (type == "type") return cont(pushlex("stat"), tydef, endstatement, poplex, block);
180 if (type == "enum") return stat_of(enumdef);
181 if (type == "mod") return stat_of(mod);
182 if (type == "iface") return stat_of(iface);
183 if (type == "impl") return stat_of(impl);
184 if (type == "open-attr") return cont(pushlex("]"), commasep(expression, "]"), poplex);
185 if (type == "ignore" || type.match(/[\]\);,]/)) return cont(block);
186 return pass(pushlex("stat"), expression, poplex, endstatement, block);
187 }
188 function endstatement(type) {
189 if (type == ";") return cont();
190 return pass();
191 }
192 function expression(type) {
193 if (type == "atom" || type == "name") return cont(maybeop);
194 if (type == "{") return cont(pushlex("}"), exprbrace, poplex);
195 if (type.match(/[\[\(]/)) return matchBrackets(type, expression);
196 if (type.match(/[\]\)\};,]/)) return pass();
197 if (type == "if-style") return cont(expression, expression);
198 if (type == "else-style" || type == "op") return cont(expression);
199 if (type == "for") return cont(pattern, maybetype, inop, expression, expression);
200 if (type == "alt") return cont(expression, altbody);
201 if (type == "fn") return cont(fndef);
202 if (type == "macro") return cont(macro);
203 return cont();
204 }
205 function maybeop(type) {
206 if (content == ".") return cont(maybeprop);
207 if (content == "::<"){return cont(typarams, maybeop);}
208 if (type == "op" || content == ":") return cont(expression);
209 if (type == "(" || type == "[") return matchBrackets(type, expression);
210 return pass();
211 }
212 function maybeprop(type) {
213 if (content.match(/^\w+$/)) {cx.marked = "variable"; return cont(maybeop);}
214 return pass(expression);
215 }
216 function exprbrace(type) {
217 if (type == "op") {
218 if (content == "|") return cont(blockvars, poplex, pushlex("}", "block"), block);
219 if (content == "||") return cont(poplex, pushlex("}", "block"), block);
220 }
221 if (content == "mutable" || (content.match(/^\w+$/) && cx.stream.peek() == ":"
222 && !cx.stream.match("::", false)))
223 return pass(record_of(expression));
224 return pass(block);
225 }
226 function record_of(comb) {
227 function ro(type) {
228 if (content == "mutable" || content == "with") {cx.marked = "keyword"; return cont(ro);}
229 if (content.match(/^\w*$/)) {cx.marked = "variable"; return cont(ro);}
230 if (type == ":") return cont(comb, ro);
231 if (type == "}") return cont();
232 return cont(ro);
233 }
234 return ro;
235 }
236 function blockvars(type) {
237 if (type == "name") {cx.marked = "def"; return cont(blockvars);}
238 if (type == "op" && content == "|") return cont();
239 return cont(blockvars);
240 }
241
242 function letdef1(type) {
243 if (type.match(/[\]\)\};]/)) return cont();
244 if (content == "=") return cont(expression, letdef2);
245 if (type == ",") return cont(letdef1);
246 return pass(pattern, maybetype, letdef1);
247 }
248 function letdef2(type) {
249 if (type.match(/[\]\)\};,]/)) return pass(letdef1);
250 else return pass(expression, letdef2);
251 }
252 function maybetype(type) {
253 if (type == ":") return cont(typecx, rtype, valcx);
254 return pass();
255 }
256 function inop(type) {
257 if (type == "name" && content == "in") {cx.marked = "keyword"; return cont();}
258 return pass();
259 }
260 function fndef(type) {
261 if (content == "@" || content == "~") {cx.marked = "keyword"; return cont(fndef);}
262 if (type == "name") {cx.marked = "def"; return cont(fndef);}
263 if (content == "<") return cont(typarams, fndef);
264 if (type == "{") return pass(expression);
265 if (type == "(") return cont(pushlex(")"), commasep(argdef, ")"), poplex, fndef);
266 if (type == "->") return cont(typecx, rtype, valcx, fndef);
267 if (type == ";") return cont();
268 return cont(fndef);
269 }
270 function tydef(type) {
271 if (type == "name") {cx.marked = "def"; return cont(tydef);}
272 if (content == "<") return cont(typarams, tydef);
273 if (content == "=") return cont(typecx, rtype, valcx);
274 return cont(tydef);
275 }
276 function enumdef(type) {
277 if (type == "name") {cx.marked = "def"; return cont(enumdef);}
278 if (content == "<") return cont(typarams, enumdef);
279 if (content == "=") return cont(typecx, rtype, valcx, endstatement);
280 if (type == "{") return cont(pushlex("}"), typecx, enumblock, valcx, poplex);
281 return cont(enumdef);
282 }
283 function enumblock(type) {
284 if (type == "}") return cont();
285 if (type == "(") return cont(pushlex(")"), commasep(rtype, ")"), poplex, enumblock);
286 if (content.match(/^\w+$/)) cx.marked = "def";
287 return cont(enumblock);
288 }
289 function mod(type) {
290 if (type == "name") {cx.marked = "def"; return cont(mod);}
291 if (type == "{") return cont(pushlex("}"), block, poplex);
292 return pass();
293 }
294 function iface(type) {
295 if (type == "name") {cx.marked = "def"; return cont(iface);}
296 if (content == "<") return cont(typarams, iface);
297 if (type == "{") return cont(pushlex("}"), block, poplex);
298 return pass();
299 }
300 function impl(type) {
301 if (content == "<") return cont(typarams, impl);
302 if (content == "of" || content == "for") {cx.marked = "keyword"; return cont(rtype, impl);}
303 if (type == "name") {cx.marked = "def"; return cont(impl);}
304 if (type == "{") return cont(pushlex("}"), block, poplex);
305 return pass();
306 }
307 function typarams(type) {
308 if (content == ">") return cont();
309 if (content == ",") return cont(typarams);
310 if (content == ":") return cont(rtype, typarams);
311 return pass(rtype, typarams);
312 }
313 function argdef(type) {
314 if (type == "name") {cx.marked = "def"; return cont(argdef);}
315 if (type == ":") return cont(typecx, rtype, valcx);
316 return pass();
317 }
318 function rtype(type) {
319 if (type == "name") {cx.marked = "variable-3"; return cont(rtypemaybeparam); }
320 if (content == "mutable") {cx.marked = "keyword"; return cont(rtype);}
321 if (type == "atom") return cont(rtypemaybeparam);
322 if (type == "op" || type == "obj") return cont(rtype);
323 if (type == "fn") return cont(fntype);
324 if (type == "{") return cont(pushlex("{"), record_of(rtype), poplex);
325 return matchBrackets(type, rtype);
326 }
327 function rtypemaybeparam(type) {
328 if (content == "<") return cont(typarams);
329 return pass();
330 }
331 function fntype(type) {
332 if (type == "(") return cont(pushlex("("), commasep(rtype, ")"), poplex, fntype);
333 if (type == "->") return cont(rtype);
334 return pass();
335 }
336 function pattern(type) {
337 if (type == "name") {cx.marked = "def"; return cont(patternmaybeop);}
338 if (type == "atom") return cont(patternmaybeop);
339 if (type == "op") return cont(pattern);
340 if (type.match(/[\]\)\};,]/)) return pass();
341 return matchBrackets(type, pattern);
342 }
343 function patternmaybeop(type) {
344 if (type == "op" && content == ".") return cont();
345 if (content == "to") {cx.marked = "keyword"; return cont(pattern);}
346 else return pass();
347 }
348 function altbody(type) {
349 if (type == "{") return cont(pushlex("}", "alt"), altblock1, poplex);
350 return pass();
351 }
352 function altblock1(type) {
353 if (type == "}") return cont();
354 if (type == "|") return cont(altblock1);
355 if (content == "when") {cx.marked = "keyword"; return cont(expression, altblock2);}
356 if (type.match(/[\]\);,]/)) return cont(altblock1);
357 return pass(pattern, altblock2);
358 }
359 function altblock2(type) {
360 if (type == "{") return cont(pushlex("}", "alt"), block, poplex, altblock1);
361 else return pass(altblock1);
362 }
363
364 function macro(type) {
365 if (type.match(/[\[\(\{]/)) return matchBrackets(type, expression);
366 return pass();
367 }
368 function matchBrackets(type, comb) {
369 if (type == "[") return cont(pushlex("]"), commasep(comb, "]"), poplex);
370 if (type == "(") return cont(pushlex(")"), commasep(comb, ")"), poplex);
371 if (type == "{") return cont(pushlex("}"), commasep(comb, "}"), poplex);
372 return cont();
373 }
374
375 function parse(state, stream, style) {
376 var cc = state.cc;
377 // Communicate our context to the combinators.
378 // (Less wasteful than consing up a hundred closures on every call.)
379 cx.state = state; cx.stream = stream; cx.marked = null, cx.cc = cc;
380
381 while (true) {
382 var combinator = cc.length ? cc.pop() : block;
383 if (combinator(tcat)) {
384 while(cc.length && cc[cc.length - 1].lex)
385 cc.pop()();
386 return cx.marked || style;
387 }
388 }
389 }
390
391 return {
392 startState: function() {
393 return {
394 tokenize: tokenBase,
395 cc: [],
396 lexical: {indented: -indentUnit, column: 0, type: "top", align: false},
397 keywords: valKeywords,
398 indented: 0
399 };
400 },
401
402 token: function(stream, state) {
403 if (stream.sol()) {
404 if (!state.lexical.hasOwnProperty("align"))
405 state.lexical.align = false;
406 state.indented = stream.indentation();
407 }
408 if (stream.eatSpace()) return null;
409 tcat = content = null;
410 var style = state.tokenize(stream, state);
411 if (style == "comment") return style;
412 if (!state.lexical.hasOwnProperty("align"))
413 state.lexical.align = true;
414 if (tcat == "prefix") return style;
415 if (!content) content = stream.current();
416 return parse(state, stream, style);
417 },
418
419 indent: function(state, textAfter) {
420 if (state.tokenize != tokenBase) return 0;
421 var firstChar = textAfter && textAfter.charAt(0), lexical = state.lexical,
422 type = lexical.type, closing = firstChar == type;
423 if (type == "stat") return lexical.indented + indentUnit;
424 if (lexical.align) return lexical.column + (closing ? 0 : 1);
425 return lexical.indented + (closing ? 0 : (lexical.info == "alt" ? altIndentUnit : indentUnit));
426 },
427
428 electricChars: "{}"
429 };
430 });
431
432 CodeMirror.defineMIME("text/x-rustsrc", "rust");
@@ -0,0 +1,64
1 <!doctype html>
2 <html>
3 <head>
4 <title>CodeMirror: Scheme mode</title>
5 <link rel="stylesheet" href="../../lib/codemirror.css">
6 <script src="../../lib/codemirror.js"></script>
7 <script src="scheme.js"></script>
8 <style>.CodeMirror {background: #f8f8f8;}</style>
9 <link rel="stylesheet" href="../../doc/docs.css">
10 </head>
11 <body>
12 <h1>CodeMirror: Scheme mode</h1>
13 <form><textarea id="code" name="code">
14 ; See if the input starts with a given symbol.
15 (define (match-symbol input pattern)
16 (cond ((null? (remain input)) #f)
17 ((eqv? (car (remain input)) pattern) (r-cdr input))
18 (else #f)))
19
20 ; Allow the input to start with one of a list of patterns.
21 (define (match-or input pattern)
22 (cond ((null? pattern) #f)
23 ((match-pattern input (car pattern)))
24 (else (match-or input (cdr pattern)))))
25
26 ; Allow a sequence of patterns.
27 (define (match-seq input pattern)
28 (if (null? pattern)
29 input
30 (let ((match (match-pattern input (car pattern))))
31 (if match (match-seq match (cdr pattern)) #f))))
32
33 ; Match with the pattern but no problem if it does not match.
34 (define (match-opt input pattern)
35 (let ((match (match-pattern input (car pattern))))
36 (if match match input)))
37
38 ; Match anything (other than '()), until pattern is found. The rather
39 ; clumsy form of requiring an ending pattern is needed to decide where
40 ; the end of the match is. If none is given, this will match the rest
41 ; of the sentence.
42 (define (match-any input pattern)
43 (cond ((null? (remain input)) #f)
44 ((null? pattern) (f-cons (remain input) (clear-remain input)))
45 (else
46 (let ((accum-any (collector)))
47 (define (match-pattern-any input pattern)
48 (cond ((null? (remain input)) #f)
49 (else (accum-any (car (remain input)))
50 (cond ((match-pattern (r-cdr input) pattern))
51 (else (match-pattern-any (r-cdr input) pattern))))))
52 (let ((retval (match-pattern-any input (car pattern))))
53 (if retval
54 (f-cons (accum-any) retval)
55 #f))))))
56 </textarea></form>
57 <script>
58 var editor = CodeMirror.fromTextArea(document.getElementById("code"), {});
59 </script>
60
61 <p><strong>MIME types defined:</strong> <code>text/x-scheme</code>.</p>
62
63 </body>
64 </html>
@@ -0,0 +1,230
1 /**
2 * Author: Koh Zi Han, based on implementation by Koh Zi Chun
3 */
4 CodeMirror.defineMode("scheme", function (config, mode) {
5 var BUILTIN = "builtin", COMMENT = "comment", STRING = "string",
6 ATOM = "atom", NUMBER = "number", BRACKET = "bracket", KEYWORD="keyword";
7 var INDENT_WORD_SKIP = 2, KEYWORDS_SKIP = 1;
8
9 function makeKeywords(str) {
10 var obj = {}, words = str.split(" ");
11 for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
12 return obj;
13 }
14
15 var keywords = makeKeywords("λ case-lambda call/cc class define-class exit-handler field import inherit init-field interface let*-values let-values let/ec mixin opt-lambda override protect provide public rename require require-for-syntax syntax syntax-case syntax-error unit/sig unless when with-syntax and begin call-with-current-continuation call-with-input-file call-with-output-file case cond define define-syntax delay do dynamic-wind else for-each if lambda let let* let-syntax letrec letrec-syntax map or syntax-rules abs acos angle append apply asin assoc assq assv atan boolean? caar cadr call-with-input-file call-with-output-file call-with-values car cdddar cddddr cdr ceiling char->integer char-alphabetic? char-ci<=? char-ci<? char-ci=? char-ci>=? char-ci>? char-downcase char-lower-case? char-numeric? char-ready? char-upcase char-upper-case? char-whitespace? char<=? char<? char=? char>=? char>? char? close-input-port close-output-port complex? cons cos current-input-port current-output-port denominator display eof-object? eq? equal? eqv? eval even? exact->inexact exact? exp expt #f floor force gcd imag-part inexact->exact inexact? input-port? integer->char integer? interaction-environment lcm length list list->string list->vector list-ref list-tail list? load log magnitude make-polar make-rectangular make-string make-vector max member memq memv min modulo negative? newline not null-environment null? number->string number? numerator odd? open-input-file open-output-file output-port? pair? peek-char port? positive? procedure? quasiquote quote quotient rational? rationalize read read-char real-part real? remainder reverse round scheme-report-environment set! set-car! set-cdr! sin sqrt string string->list string->number string->symbol string-append string-ci<=? string-ci<? string-ci=? string-ci>=? string-ci>? string-copy string-fill! string-length string-ref string-set! string<=? string<? string=? string>=? string>? string? substring symbol->string symbol? #t tan transcript-off transcript-on truncate values vector vector->list vector-fill! vector-length vector-ref vector-set! with-input-from-file with-output-to-file write write-char zero?");
16 var indentKeys = makeKeywords("define let letrec let* lambda");
17
18 function stateStack(indent, type, prev) { // represents a state stack object
19 this.indent = indent;
20 this.type = type;
21 this.prev = prev;
22 }
23
24 function pushStack(state, indent, type) {
25 state.indentStack = new stateStack(indent, type, state.indentStack);
26 }
27
28 function popStack(state) {
29 state.indentStack = state.indentStack.prev;
30 }
31
32 var binaryMatcher = new RegExp(/^(?:[-+]i|[-+][01]+#*(?:\/[01]+#*)?i|[-+]?[01]+#*(?:\/[01]+#*)?@[-+]?[01]+#*(?:\/[01]+#*)?|[-+]?[01]+#*(?:\/[01]+#*)?[-+](?:[01]+#*(?:\/[01]+#*)?)?i|[-+]?[01]+#*(?:\/[01]+#*)?)(?=[()\s;"]|$)/i);
33 var octalMatcher = new RegExp(/^(?:[-+]i|[-+][0-7]+#*(?:\/[0-7]+#*)?i|[-+]?[0-7]+#*(?:\/[0-7]+#*)?@[-+]?[0-7]+#*(?:\/[0-7]+#*)?|[-+]?[0-7]+#*(?:\/[0-7]+#*)?[-+](?:[0-7]+#*(?:\/[0-7]+#*)?)?i|[-+]?[0-7]+#*(?:\/[0-7]+#*)?)(?=[()\s;"]|$)/i);
34 var hexMatcher = new RegExp(/^(?:[-+]i|[-+][\da-f]+#*(?:\/[\da-f]+#*)?i|[-+]?[\da-f]+#*(?:\/[\da-f]+#*)?@[-+]?[\da-f]+#*(?:\/[\da-f]+#*)?|[-+]?[\da-f]+#*(?:\/[\da-f]+#*)?[-+](?:[\da-f]+#*(?:\/[\da-f]+#*)?)?i|[-+]?[\da-f]+#*(?:\/[\da-f]+#*)?)(?=[()\s;"]|$)/i);
35 var decimalMatcher = new RegExp(/^(?:[-+]i|[-+](?:(?:(?:\d+#+\.?#*|\d+\.\d*#*|\.\d+#*|\d+)(?:[esfdl][-+]?\d+)?)|\d+#*\/\d+#*)i|[-+]?(?:(?:(?:\d+#+\.?#*|\d+\.\d*#*|\.\d+#*|\d+)(?:[esfdl][-+]?\d+)?)|\d+#*\/\d+#*)@[-+]?(?:(?:(?:\d+#+\.?#*|\d+\.\d*#*|\.\d+#*|\d+)(?:[esfdl][-+]?\d+)?)|\d+#*\/\d+#*)|[-+]?(?:(?:(?:\d+#+\.?#*|\d+\.\d*#*|\.\d+#*|\d+)(?:[esfdl][-+]?\d+)?)|\d+#*\/\d+#*)[-+](?:(?:(?:\d+#+\.?#*|\d+\.\d*#*|\.\d+#*|\d+)(?:[esfdl][-+]?\d+)?)|\d+#*\/\d+#*)?i|(?:(?:(?:\d+#+\.?#*|\d+\.\d*#*|\.\d+#*|\d+)(?:[esfdl][-+]?\d+)?)|\d+#*\/\d+#*))(?=[()\s;"]|$)/i);
36
37 function isBinaryNumber (stream) {
38 return stream.match(binaryMatcher);
39 }
40
41 function isOctalNumber (stream) {
42 return stream.match(octalMatcher);
43 }
44
45 function isDecimalNumber (stream, backup) {
46 if (backup === true) {
47 stream.backUp(1);
48 }
49 return stream.match(decimalMatcher);
50 }
51
52 function isHexNumber (stream) {
53 return stream.match(hexMatcher);
54 }
55
56 return {
57 startState: function () {
58 return {
59 indentStack: null,
60 indentation: 0,
61 mode: false,
62 sExprComment: false
63 };
64 },
65
66 token: function (stream, state) {
67 if (state.indentStack == null && stream.sol()) {
68 // update indentation, but only if indentStack is empty
69 state.indentation = stream.indentation();
70 }
71
72 // skip spaces
73 if (stream.eatSpace()) {
74 return null;
75 }
76 var returnType = null;
77
78 switch(state.mode){
79 case "string": // multi-line string parsing mode
80 var next, escaped = false;
81 while ((next = stream.next()) != null) {
82 if (next == "\"" && !escaped) {
83
84 state.mode = false;
85 break;
86 }
87 escaped = !escaped && next == "\\";
88 }
89 returnType = STRING; // continue on in scheme-string mode
90 break;
91 case "comment": // comment parsing mode
92 var next, maybeEnd = false;
93 while ((next = stream.next()) != null) {
94 if (next == "#" && maybeEnd) {
95
96 state.mode = false;
97 break;
98 }
99 maybeEnd = (next == "|");
100 }
101 returnType = COMMENT;
102 break;
103 case "s-expr-comment": // s-expr commenting mode
104 state.mode = false;
105 if(stream.peek() == "(" || stream.peek() == "["){
106 // actually start scheme s-expr commenting mode
107 state.sExprComment = 0;
108 }else{
109 // if not we just comment the entire of the next token
110 stream.eatWhile(/[^/s]/); // eat non spaces
111 returnType = COMMENT;
112 break;
113 }
114 default: // default parsing mode
115 var ch = stream.next();
116
117 if (ch == "\"") {
118 state.mode = "string";
119 returnType = STRING;
120
121 } else if (ch == "'") {
122 returnType = ATOM;
123 } else if (ch == '#') {
124 if (stream.eat("|")) { // Multi-line comment
125 state.mode = "comment"; // toggle to comment mode
126 returnType = COMMENT;
127 } else if (stream.eat(/[tf]/i)) { // #t/#f (atom)
128 returnType = ATOM;
129 } else if (stream.eat(';')) { // S-Expr comment
130 state.mode = "s-expr-comment";
131 returnType = COMMENT;
132 } else {
133 var numTest = null, hasExactness = false, hasRadix = true;
134 if (stream.eat(/[ei]/i)) {
135 hasExactness = true;
136 } else {
137 stream.backUp(1); // must be radix specifier
138 }
139 if (stream.match(/^#b/i)) {
140 numTest = isBinaryNumber;
141 } else if (stream.match(/^#o/i)) {
142 numTest = isOctalNumber;
143 } else if (stream.match(/^#x/i)) {
144 numTest = isHexNumber;
145 } else if (stream.match(/^#d/i)) {
146 numTest = isDecimalNumber;
147 } else if (stream.match(/^[-+0-9.]/, false)) {
148 hasRadix = false;
149 numTest = isDecimalNumber;
150 // re-consume the intial # if all matches failed
151 } else if (!hasExactness) {
152 stream.eat('#');
153 }
154 if (numTest != null) {
155 if (hasRadix && !hasExactness) {
156 // consume optional exactness after radix
157 stream.match(/^#[ei]/i);
158 }
159 if (numTest(stream))
160 returnType = NUMBER;
161 }
162 }
163 } else if (/^[-+0-9.]/.test(ch) && isDecimalNumber(stream, true)) { // match non-prefixed number, must be decimal
164 returnType = NUMBER;
165 } else if (ch == ";") { // comment
166 stream.skipToEnd(); // rest of the line is a comment
167 returnType = COMMENT;
168 } else if (ch == "(" || ch == "[") {
169 var keyWord = ''; var indentTemp = stream.column();
170 /**
171 Either
172 (indent-word ..
173 (non-indent-word ..
174 (;something else, bracket, etc.
175 */
176
177 while ((letter = stream.eat(/[^\s\(\[\;\)\]]/)) != null) {
178 keyWord += letter;
179 }
180
181 if (keyWord.length > 0 && indentKeys.propertyIsEnumerable(keyWord)) { // indent-word
182
183 pushStack(state, indentTemp + INDENT_WORD_SKIP, ch);
184 } else { // non-indent word
185 // we continue eating the spaces
186 stream.eatSpace();
187 if (stream.eol() || stream.peek() == ";") {
188 // nothing significant after
189 // we restart indentation 1 space after
190 pushStack(state, indentTemp + 1, ch);
191 } else {
192 pushStack(state, indentTemp + stream.current().length, ch); // else we match
193 }
194 }
195 stream.backUp(stream.current().length - 1); // undo all the eating
196
197 if(typeof state.sExprComment == "number") state.sExprComment++;
198
199 returnType = BRACKET;
200 } else if (ch == ")" || ch == "]") {
201 returnType = BRACKET;
202 if (state.indentStack != null && state.indentStack.type == (ch == ")" ? "(" : "[")) {
203 popStack(state);
204
205 if(typeof state.sExprComment == "number"){
206 if(--state.sExprComment == 0){
207 returnType = COMMENT; // final closing bracket
208 state.sExprComment = false; // turn off s-expr commenting mode
209 }
210 }
211 }
212 } else {
213 stream.eatWhile(/[\w\$_\-!$%&*+\.\/:<=>?@\^~]/);
214
215 if (keywords && keywords.propertyIsEnumerable(stream.current())) {
216 returnType = BUILTIN;
217 } else returnType = "variable";
218 }
219 }
220 return (typeof state.sExprComment == "number") ? COMMENT : returnType;
221 },
222
223 indent: function (state, textAfter) {
224 if (state.indentStack == null) return state.indentation;
225 return state.indentStack.indent;
226 }
227 };
228 });
229
230 CodeMirror.defineMIME("text/x-scheme", "scheme");
@@ -0,0 +1,50
1 <!doctype html>
2 <meta charset=utf-8>
3 <title>CodeMirror: Shell mode</title>
4
5 <link rel=stylesheet href=../../lib/codemirror.css>
6 <link rel=stylesheet href=../../doc/docs.css>
7
8 <style type=text/css>
9 .CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}
10 </style>
11
12 <script src=../../lib/codemirror.js></script>
13 <script src=shell.js></script>
14
15 <h1>CodeMirror: Shell mode</h1>
16
17 <textarea id=code>
18 #!/bin/bash
19
20 # clone the repository
21 git clone http://github.com/garden/tree
22
23 # generate HTTPS credentials
24 cd tree
25 openssl genrsa -aes256 -out https.key 1024
26 openssl req -new -nodes -key https.key -out https.csr
27 openssl x509 -req -days 365 -in https.csr -signkey https.key -out https.crt
28 cp https.key{,.orig}
29 openssl rsa -in https.key.orig -out https.key
30
31 # start the server in HTTPS mode
32 cd web
33 sudo node ../server.js 443 'yes' &gt;&gt; ../node.log &amp;
34
35 # here is how to stop the server
36 for pid in `ps aux | grep 'node ../server.js' | awk '{print $2}'` ; do
37 sudo kill -9 $pid 2&gt; /dev/null
38 done
39
40 exit 0</textarea>
41
42 <script>
43 var editor = CodeMirror.fromTextArea(document.getElementById('code'), {
44 mode: 'shell',
45 lineNumbers: true,
46 matchBrackets: true
47 });
48 </script>
49
50 <p><strong>MIME types defined:</strong> <code>text/x-sh</code>.</p>
@@ -0,0 +1,118
1 CodeMirror.defineMode('shell', function(config) {
2
3 var words = {};
4 function define(style, string) {
5 var split = string.split(' ');
6 for(var i = 0; i < split.length; i++) {
7 words[split[i]] = style;
8 }
9 };
10
11 // Atoms
12 define('atom', 'true false');
13
14 // Keywords
15 define('keyword', 'if then do else elif while until for in esac fi fin ' +
16 'fil done exit set unset export function');
17
18 // Commands
19 define('builtin', 'ab awk bash beep cat cc cd chown chmod chroot clear cp ' +
20 'curl cut diff echo find gawk gcc get git grep kill killall ln ls make ' +
21 'mkdir openssl mv nc node npm ping ps restart rm rmdir sed service sh ' +
22 'shopt shred source sort sleep ssh start stop su sudo tee telnet top ' +
23 'touch vi vim wall wc wget who write yes zsh');
24
25 function tokenBase(stream, state) {
26
27 var sol = stream.sol();
28 var ch = stream.next();
29
30 if (ch === '\'' || ch === '"' || ch === '`') {
31 state.tokens.unshift(tokenString(ch));
32 return tokenize(stream, state);
33 }
34 if (ch === '#') {
35 if (sol && stream.eat('!')) {
36 stream.skipToEnd();
37 return 'meta'; // 'comment'?
38 }
39 stream.skipToEnd();
40 return 'comment';
41 }
42 if (ch === '$') {
43 state.tokens.unshift(tokenDollar);
44 return tokenize(stream, state);
45 }
46 if (ch === '+' || ch === '=') {
47 return 'operator';
48 }
49 if (ch === '-') {
50 stream.eat('-');
51 stream.eatWhile(/\w/);
52 return 'attribute';
53 }
54 if (/\d/.test(ch)) {
55 stream.eatWhile(/\d/);
56 if(!/\w/.test(stream.peek())) {
57 return 'number';
58 }
59 }
60 stream.eatWhile(/\w/);
61 var cur = stream.current();
62 if (stream.peek() === '=' && /\w+/.test(cur)) return 'def';
63 return words[cur] || null;
64 }
65
66 function tokenString(quote) {
67 return function(stream, state) {
68 var next, end = false, escaped = false;
69 while ((next = stream.next()) != null) {
70 if (next === quote && !escaped) {
71 end = true;
72 break;
73 }
74 if (next === '$' && !escaped && quote !== '\'') {
75 escaped = true;
76 stream.backUp(1);
77 state.tokens.unshift(tokenDollar);
78 break;
79 }
80 escaped = !escaped && next === '\\';
81 }
82 if (end || !escaped) {
83 state.tokens.shift();
84 }
85 return (quote === '`' || quote === ')' ? 'quote' : 'string');
86 };
87 };
88
89 var tokenDollar = function(stream, state) {
90 if (state.tokens.length > 1) stream.eat('$');
91 var ch = stream.next(), hungry = /\w/;
92 if (ch === '{') hungry = /[^}]/;
93 if (ch === '(') {
94 state.tokens[0] = tokenString(')');
95 return tokenize(stream, state);
96 }
97 if (!/\d/.test(ch)) {
98 stream.eatWhile(hungry);
99 stream.eat('}');
100 }
101 state.tokens.shift();
102 return 'def';
103 };
104
105 function tokenize(stream, state) {
106 return (state.tokens[0] || tokenBase) (stream, state);
107 };
108
109 return {
110 startState: function() {return {tokens:[]}},
111 token: function(stream, state) {
112 if (stream.eatSpace()) return null;
113 return tokenize(stream, state);
114 }
115 };
116 });
117
118 CodeMirror.defineMIME('text/x-sh', 'shell');
@@ -0,0 +1,55
1 <!doctype html>
2 <html>
3 <head>
4 <title>CodeMirror: Smalltalk mode</title>
5 <link rel="stylesheet" href="../../lib/codemirror.css">
6 <script src="../../lib/codemirror.js"></script>
7 <script src="smalltalk.js"></script>
8 <link rel="stylesheet" href="../../doc/docs.css">
9 <style>
10 .CodeMirror {border: 2px solid #dee; border-right-width: 10px;}
11 .CodeMirror-gutter {border: none; background: #dee;}
12 .CodeMirror-gutter pre {color: white; font-weight: bold;}
13 </style>
14 </head>
15 <body>
16 <h1>CodeMirror: Smalltalk mode</h1>
17
18 <form><textarea id="code" name="code">
19 "
20 This is a test of the Smalltalk code
21 "
22 Seaside.WAComponent subclass: #MyCounter [
23 | count |
24 MyCounter class &gt;&gt; canBeRoot [ ^true ]
25
26 initialize [
27 super initialize.
28 count := 0.
29 ]
30 states [ ^{ self } ]
31 renderContentOn: html [
32 html heading: count.
33 html anchor callback: [ count := count + 1 ]; with: '++'.
34 html space.
35 html anchor callback: [ count := count - 1 ]; with: '--'.
36 ]
37 ]
38
39 MyCounter registerAsApplication: 'mycounter'
40 </textarea></form>
41
42 <script>
43 var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
44 lineNumbers: true,
45 matchBrackets: true,
46 mode: "text/x-stsrc",
47 indentUnit: 4
48 });
49 </script>
50
51 <p>Simple Smalltalk mode.</p>
52
53 <p><strong>MIME types defined:</strong> <code>text/x-stsrc</code>.</p>
54 </body>
55 </html>
@@ -0,0 +1,139
1 CodeMirror.defineMode('smalltalk', function(config, modeConfig) {
2
3 var specialChars = /[+\-/\\*~<>=@%|&?!.:;^]/;
4 var keywords = /true|false|nil|self|super|thisContext/;
5
6 var Context = function(tokenizer, parent) {
7 this.next = tokenizer;
8 this.parent = parent;
9 };
10
11 var Token = function(name, context, eos) {
12 this.name = name;
13 this.context = context;
14 this.eos = eos;
15 };
16
17 var State = function() {
18 this.context = new Context(next, null);
19 this.expectVariable = true;
20 this.indentation = 0;
21 this.userIndentationDelta = 0;
22 };
23
24 State.prototype.userIndent = function(indentation) {
25 this.userIndentationDelta = indentation > 0 ? (indentation / config.indentUnit - this.indentation) : 0;
26 };
27
28 var next = function(stream, context, state) {
29 var token = new Token(null, context, false);
30 var aChar = stream.next();
31
32 if (aChar === '"') {
33 token = nextComment(stream, new Context(nextComment, context));
34
35 } else if (aChar === '\'') {
36 token = nextString(stream, new Context(nextString, context));
37
38 } else if (aChar === '#') {
39 stream.eatWhile(/[^ .]/);
40 token.name = 'string-2';
41
42 } else if (aChar === '$') {
43 stream.eatWhile(/[^ ]/);
44 token.name = 'string-2';
45
46 } else if (aChar === '|' && state.expectVariable) {
47 token.context = new Context(nextTemporaries, context);
48
49 } else if (/[\[\]{}()]/.test(aChar)) {
50 token.name = 'bracket';
51 token.eos = /[\[{(]/.test(aChar);
52
53 if (aChar === '[') {
54 state.indentation++;
55 } else if (aChar === ']') {
56 state.indentation = Math.max(0, state.indentation - 1);
57 }
58
59 } else if (specialChars.test(aChar)) {
60 stream.eatWhile(specialChars);
61 token.name = 'operator';
62 token.eos = aChar !== ';'; // ; cascaded message expression
63
64 } else if (/\d/.test(aChar)) {
65 stream.eatWhile(/[\w\d]/);
66 token.name = 'number'
67
68 } else if (/[\w_]/.test(aChar)) {
69 stream.eatWhile(/[\w\d_]/);
70 token.name = state.expectVariable ? (keywords.test(stream.current()) ? 'keyword' : 'variable') : null;
71
72 } else {
73 token.eos = state.expectVariable;
74 }
75
76 return token;
77 };
78
79 var nextComment = function(stream, context) {
80 stream.eatWhile(/[^"]/);
81 return new Token('comment', stream.eat('"') ? context.parent : context, true);
82 };
83
84 var nextString = function(stream, context) {
85 stream.eatWhile(/[^']/);
86 return new Token('string', stream.eat('\'') ? context.parent : context, false);
87 };
88
89 var nextTemporaries = function(stream, context, state) {
90 var token = new Token(null, context, false);
91 var aChar = stream.next();
92
93 if (aChar === '|') {
94 token.context = context.parent;
95 token.eos = true;
96
97 } else {
98 stream.eatWhile(/[^|]/);
99 token.name = 'variable';
100 }
101
102 return token;
103 }
104
105 return {
106 startState: function() {
107 return new State;
108 },
109
110 token: function(stream, state) {
111 state.userIndent(stream.indentation());
112
113 if (stream.eatSpace()) {
114 return null;
115 }
116
117 var token = state.context.next(stream, state.context, state);
118 state.context = token.context;
119 state.expectVariable = token.eos;
120
121 state.lastToken = token;
122 return token.name;
123 },
124
125 blankLine: function(state) {
126 state.userIndent(0);
127 },
128
129 indent: function(state, textAfter) {
130 var i = state.context.next === next && textAfter && textAfter.charAt(0) === ']' ? -1 : state.userIndentationDelta;
131 return (state.indentation + i) * config.indentUnit;
132 },
133
134 electricChars: ']'
135 };
136
137 });
138
139 CodeMirror.defineMIME('text/x-stsrc', {name: 'smalltalk'}); No newline at end of file
@@ -0,0 +1,82
1 <!doctype html>
2 <html>
3 <head>
4 <title>CodeMirror: Smarty mode</title>
5 <link rel="stylesheet" href="../../lib/codemirror.css">
6 <script src="../../lib/codemirror.js"></script>
7 <script src="smarty.js"></script>
8 <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
9 <link rel="stylesheet" href="../../doc/docs.css">
10 </head>
11 <body>
12 <h1>CodeMirror: Smarty mode</h1>
13
14 <form><textarea id="code" name="code">
15 {extends file="parent.tpl"}
16 {include file="template.tpl"}
17
18 {* some example Smarty content *}
19 {if isset($name) && $name == 'Blog'}
20 This is a {$var}.
21 {$integer = 451}, {$array[] = "a"}, {$stringvar = "string"}
22 {assign var='bob' value=$var.prop}
23 {elseif $name == $foo}
24 {function name=menu level=0}
25 {foreach $data as $entry}
26 {if is_array($entry)}
27 - {$entry@key}
28 {menu data=$entry level=$level+1}
29 {else}
30 {$entry}
31 {/if}
32 {/foreach}
33 {/function}
34 {/if}</textarea></form>
35
36 <script>
37 var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
38 lineNumbers: true,
39 mode: "smarty"
40 });
41 </script>
42
43 <br />
44
45 <form><textarea id="code2" name="code2">
46 {--extends file="parent.tpl"--}
47 {--include file="template.tpl"--}
48
49 {--* some example Smarty content *--}
50 {--if isset($name) && $name == 'Blog'--}
51 This is a {--$var--}.
52 {--$integer = 451--}, {--$array[] = "a"--}, {--$stringvar = "string"--}
53 {--assign var='bob' value=$var.prop--}
54 {--elseif $name == $foo--}
55 {--function name=menu level=0--}
56 {--foreach $data as $entry--}
57 {--if is_array($entry)--}
58 - {--$entry@key--}
59 {--menu data=$entry level=$level+1--}
60 {--else--}
61 {--$entry--}
62 {--/if--}
63 {--/foreach--}
64 {--/function--}
65 {--/if--}</textarea></form>
66
67 <script>
68 var editor = CodeMirror.fromTextArea(document.getElementById("code2"), {
69 lineNumbers: true,
70 mode: {
71 name: "smarty",
72 leftDelimiter: "{--",
73 rightDelimiter: "--}"
74 }
75 });
76 </script>
77
78 <p>A plain text/Smarty mode which allows for custom delimiter tags (defaults to <b>{</b> and <b>}</b>).</p>
79
80 <p><strong>MIME types defined:</strong> <code>text/x-smarty</code></p>
81 </body>
82 </html>
@@ -0,0 +1,148
1 CodeMirror.defineMode("smarty", function(config, parserConfig) {
2 var keyFuncs = ["debug", "extends", "function", "include", "literal"];
3 var last;
4 var regs = {
5 operatorChars: /[+\-*&%=<>!?]/,
6 validIdentifier: /[a-zA-Z0-9\_]/,
7 stringChar: /[\'\"]/
8 }
9 var leftDelim = (typeof config.mode.leftDelimiter != 'undefined') ? config.mode.leftDelimiter : "{";
10 var rightDelim = (typeof config.mode.rightDelimiter != 'undefined') ? config.mode.rightDelimiter : "}";
11 function ret(style, lst) { last = lst; return style; }
12
13
14 function tokenizer(stream, state) {
15 function chain(parser) {
16 state.tokenize = parser;
17 return parser(stream, state);
18 }
19
20 if (stream.match(leftDelim, true)) {
21 if (stream.eat("*")) {
22 return chain(inBlock("comment", "*" + rightDelim));
23 }
24 else {
25 state.tokenize = inSmarty;
26 return "tag";
27 }
28 }
29 else {
30 // I'd like to do an eatWhile() here, but I can't get it to eat only up to the rightDelim string/char
31 stream.next();
32 return null;
33 }
34 }
35
36 function inSmarty(stream, state) {
37 if (stream.match(rightDelim, true)) {
38 state.tokenize = tokenizer;
39 return ret("tag", null);
40 }
41
42 var ch = stream.next();
43 if (ch == "$") {
44 stream.eatWhile(regs.validIdentifier);
45 return ret("variable-2", "variable");
46 }
47 else if (ch == ".") {
48 return ret("operator", "property");
49 }
50 else if (regs.stringChar.test(ch)) {
51 state.tokenize = inAttribute(ch);
52 return ret("string", "string");
53 }
54 else if (regs.operatorChars.test(ch)) {
55 stream.eatWhile(regs.operatorChars);
56 return ret("operator", "operator");
57 }
58 else if (ch == "[" || ch == "]") {
59 return ret("bracket", "bracket");
60 }
61 else if (/\d/.test(ch)) {
62 stream.eatWhile(/\d/);
63 return ret("number", "number");
64 }
65 else {
66 if (state.last == "variable") {
67 if (ch == "@") {
68 stream.eatWhile(regs.validIdentifier);
69 return ret("property", "property");
70 }
71 else if (ch == "|") {
72 stream.eatWhile(regs.validIdentifier);
73 return ret("qualifier", "modifier");
74 }
75 }
76 else if (state.last == "whitespace") {
77 stream.eatWhile(regs.validIdentifier);
78 return ret("attribute", "modifier");
79 }
80 else if (state.last == "property") {
81 stream.eatWhile(regs.validIdentifier);
82 return ret("property", null);
83 }
84 else if (/\s/.test(ch)) {
85 last = "whitespace";
86 return null;
87 }
88
89 var str = "";
90 if (ch != "/") {
91 str += ch;
92 }
93 var c = "";
94 while ((c = stream.eat(regs.validIdentifier))) {
95 str += c;
96 }
97 var i, j;
98 for (i=0, j=keyFuncs.length; i<j; i++) {
99 if (keyFuncs[i] == str) {
100 return ret("keyword", "keyword");
101 }
102 }
103 if (/\s/.test(ch)) {
104 return null;
105 }
106 return ret("tag", "tag");
107 }
108 }
109
110 function inAttribute(quote) {
111 return function(stream, state) {
112 while (!stream.eol()) {
113 if (stream.next() == quote) {
114 state.tokenize = inSmarty;
115 break;
116 }
117 }
118 return "string";
119 };
120 }
121
122 function inBlock(style, terminator) {
123 return function(stream, state) {
124 while (!stream.eol()) {
125 if (stream.match(terminator)) {
126 state.tokenize = tokenizer;
127 break;
128 }
129 stream.next();
130 }
131 return style;
132 };
133 }
134
135 return {
136 startState: function() {
137 return { tokenize: tokenizer, mode: "smarty", last: null };
138 },
139 token: function(stream, state) {
140 var style = state.tokenize(stream, state);
141 state.last = last;
142 return style;
143 },
144 electricChars: ""
145 }
146 });
147
148 CodeMirror.defineMIME("text/x-smarty", "smarty"); No newline at end of file
@@ -0,0 +1,40
1 <!doctype html>
2 <html>
3 <head>
4 <title>CodeMirror: SPARQL mode</title>
5 <link rel="stylesheet" href="../../lib/codemirror.css">
6 <script src="../../lib/codemirror.js"></script>
7 <script src="sparql.js"></script>
8 <style>.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
9 <link rel="stylesheet" href="../../doc/docs.css">
10 </head>
11 <body>
12 <h1>CodeMirror: SPARQL mode</h1>
13 <form><textarea id="code" name="code">
14 PREFIX a: &lt;http://www.w3.org/2000/10/annotation-ns#>
15 PREFIX dc: &lt;http://purl.org/dc/elements/1.1/>
16 PREFIX foaf: &lt;http://xmlns.com/foaf/0.1/>
17
18 # Comment!
19
20 SELECT ?given ?family
21 WHERE {
22 ?annot a:annotates &lt;http://www.w3.org/TR/rdf-sparql-query/> .
23 ?annot dc:creator ?c .
24 OPTIONAL {?c foaf:given ?given ;
25 foaf:family ?family } .
26 FILTER isBlank(?c)
27 }
28 </textarea></form>
29 <script>
30 var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
31 mode: "application/x-sparql-query",
32 tabMode: "indent",
33 matchBrackets: true
34 });
35 </script>
36
37 <p><strong>MIME types defined:</strong> <code>application/x-sparql-query</code>.</p>
38
39 </body>
40 </html>
@@ -0,0 +1,143
1 CodeMirror.defineMode("sparql", function(config) {
2 var indentUnit = config.indentUnit;
3 var curPunc;
4
5 function wordRegexp(words) {
6 return new RegExp("^(?:" + words.join("|") + ")$", "i");
7 }
8 var ops = wordRegexp(["str", "lang", "langmatches", "datatype", "bound", "sameterm", "isiri", "isuri",
9 "isblank", "isliteral", "union", "a"]);
10 var keywords = wordRegexp(["base", "prefix", "select", "distinct", "reduced", "construct", "describe",
11 "ask", "from", "named", "where", "order", "limit", "offset", "filter", "optional",
12 "graph", "by", "asc", "desc"]);
13 var operatorChars = /[*+\-<>=&|]/;
14
15 function tokenBase(stream, state) {
16 var ch = stream.next();
17 curPunc = null;
18 if (ch == "$" || ch == "?") {
19 stream.match(/^[\w\d]*/);
20 return "variable-2";
21 }
22 else if (ch == "<" && !stream.match(/^[\s\u00a0=]/, false)) {
23 stream.match(/^[^\s\u00a0>]*>?/);
24 return "atom";
25 }
26 else if (ch == "\"" || ch == "'") {
27 state.tokenize = tokenLiteral(ch);
28 return state.tokenize(stream, state);
29 }
30 else if (/[{}\(\),\.;\[\]]/.test(ch)) {
31 curPunc = ch;
32 return null;
33 }
34 else if (ch == "#") {
35 stream.skipToEnd();
36 return "comment";
37 }
38 else if (operatorChars.test(ch)) {
39 stream.eatWhile(operatorChars);
40 return null;
41 }
42 else if (ch == ":") {
43 stream.eatWhile(/[\w\d\._\-]/);
44 return "atom";
45 }
46 else {
47 stream.eatWhile(/[_\w\d]/);
48 if (stream.eat(":")) {
49 stream.eatWhile(/[\w\d_\-]/);
50 return "atom";
51 }
52 var word = stream.current(), type;
53 if (ops.test(word))
54 return null;
55 else if (keywords.test(word))
56 return "keyword";
57 else
58 return "variable";
59 }
60 }
61
62 function tokenLiteral(quote) {
63 return function(stream, state) {
64 var escaped = false, ch;
65 while ((ch = stream.next()) != null) {
66 if (ch == quote && !escaped) {
67 state.tokenize = tokenBase;
68 break;
69 }
70 escaped = !escaped && ch == "\\";
71 }
72 return "string";
73 };
74 }
75
76 function pushContext(state, type, col) {
77 state.context = {prev: state.context, indent: state.indent, col: col, type: type};
78 }
79 function popContext(state) {
80 state.indent = state.context.indent;
81 state.context = state.context.prev;
82 }
83
84 return {
85 startState: function(base) {
86 return {tokenize: tokenBase,
87 context: null,
88 indent: 0,
89 col: 0};
90 },
91
92 token: function(stream, state) {
93 if (stream.sol()) {
94 if (state.context && state.context.align == null) state.context.align = false;
95 state.indent = stream.indentation();
96 }
97 if (stream.eatSpace()) return null;
98 var style = state.tokenize(stream, state);
99
100 if (style != "comment" && state.context && state.context.align == null && state.context.type != "pattern") {
101 state.context.align = true;
102 }
103
104 if (curPunc == "(") pushContext(state, ")", stream.column());
105 else if (curPunc == "[") pushContext(state, "]", stream.column());
106 else if (curPunc == "{") pushContext(state, "}", stream.column());
107 else if (/[\]\}\)]/.test(curPunc)) {
108 while (state.context && state.context.type == "pattern") popContext(state);
109 if (state.context && curPunc == state.context.type) popContext(state);
110 }
111 else if (curPunc == "." && state.context && state.context.type == "pattern") popContext(state);
112 else if (/atom|string|variable/.test(style) && state.context) {
113 if (/[\}\]]/.test(state.context.type))
114 pushContext(state, "pattern", stream.column());
115 else if (state.context.type == "pattern" && !state.context.align) {
116 state.context.align = true;
117 state.context.col = stream.column();
118 }
119 }
120
121 return style;
122 },
123
124 indent: function(state, textAfter) {
125 var firstChar = textAfter && textAfter.charAt(0);
126 var context = state.context;
127 if (/[\]\}]/.test(firstChar))
128 while (context && context.type == "pattern") context = context.prev;
129
130 var closing = context && firstChar == context.type;
131 if (!context)
132 return 0;
133 else if (context.type == "pattern")
134 return context.col;
135 else if (context.align)
136 return context.col + (closing ? 0 : 1);
137 else
138 return context.indent + (closing ? 0 : indentUnit);
139 }
140 };
141 });
142
143 CodeMirror.defineMIME("application/x-sparql-query", "sparql");
@@ -0,0 +1,95
1 <!doctype html>
2 <html>
3 <head>
4 <title>CodeMirror: sTeX mode</title>
5 <link rel="stylesheet" href="../../lib/codemirror.css">
6 <script src="../../lib/codemirror.js"></script>
7 <script src="stex.js"></script>
8 <style>.CodeMirror {background: #f8f8f8;}</style>
9 <link rel="stylesheet" href="../../doc/docs.css">
10 </head>
11 <body>
12 <h1>CodeMirror: sTeX mode</h1>
13 <form><textarea id="code" name="code">
14 \begin{module}[id=bbt-size]
15 \importmodule[balanced-binary-trees]{balanced-binary-trees}
16 \importmodule[\KWARCslides{dmath/en/cardinality}]{cardinality}
17
18 \begin{frame}
19 \frametitle{Size Lemma for Balanced Trees}
20 \begin{itemize}
21 \item
22 \begin{assertion}[id=size-lemma,type=lemma]
23 Let $G=\tup{V,E}$ be a \termref[cd=binary-trees]{balanced binary tree}
24 of \termref[cd=graph-depth,name=vertex-depth]{depth}$n>i$, then the set
25 $\defeq{\livar{V}i}{\setst{\inset{v}{V}}{\gdepth{v} = i}}$ of
26 \termref[cd=graphs-intro,name=node]{nodes} at
27 \termref[cd=graph-depth,name=vertex-depth]{depth} $i$ has
28 \termref[cd=cardinality,name=cardinality]{cardinality} $\power2i$.
29 \end{assertion}
30 \item
31 \begin{sproof}[id=size-lemma-pf,proofend=,for=size-lemma]{via induction over the depth $i$.}
32 \begin{spfcases}{We have to consider two cases}
33 \begin{spfcase}{$i=0$}
34 \begin{spfstep}[display=flow]
35 then $\livar{V}i=\set{\livar{v}r}$, where $\livar{v}r$ is the root, so
36 $\eq{\card{\livar{V}0},\card{\set{\livar{v}r}},1,\power20}$.
37 \end{spfstep}
38 \end{spfcase}
39 \begin{spfcase}{$i>0$}
40 \begin{spfstep}[display=flow]
41 then $\livar{V}{i-1}$ contains $\power2{i-1}$ vertexes
42 \begin{justification}[method=byIH](IH)\end{justification}
43 \end{spfstep}
44 \begin{spfstep}
45 By the \begin{justification}[method=byDef]definition of a binary
46 tree\end{justification}, each $\inset{v}{\livar{V}{i-1}}$ is a leaf or has
47 two children that are at depth $i$.
48 \end{spfstep}
49 \begin{spfstep}
50 As $G$ is \termref[cd=balanced-binary-trees,name=balanced-binary-tree]{balanced} and $\gdepth{G}=n>i$, $\livar{V}{i-1}$ cannot contain
51 leaves.
52 \end{spfstep}
53 \begin{spfstep}[type=conclusion]
54 Thus $\eq{\card{\livar{V}i},{\atimes[cdot]{2,\card{\livar{V}{i-1}}}},{\atimes[cdot]{2,\power2{i-1}}},\power2i}$.
55 \end{spfstep}
56 \end{spfcase}
57 \end{spfcases}
58 \end{sproof}
59 \item
60 \begin{assertion}[id=fbbt,type=corollary]
61 A fully balanced tree of depth $d$ has $\power2{d+1}-1$ nodes.
62 \end{assertion}
63 \item
64 \begin{sproof}[for=fbbt,id=fbbt-pf]{}
65 \begin{spfstep}
66 Let $\defeq{G}{\tup{V,E}}$ be a fully balanced tree
67 \end{spfstep}
68 \begin{spfstep}
69 Then $\card{V}=\Sumfromto{i}1d{\power2i}= \power2{d+1}-1$.
70 \end{spfstep}
71 \end{sproof}
72 \end{itemize}
73 \end{frame}
74 \begin{note}
75 \begin{omtext}[type=conclusion,for=binary-tree]
76 This shows that balanced binary trees grow in breadth very quickly, a consequence of
77 this is that they are very shallow (and this compute very fast), which is the essence of
78 the next result.
79 \end{omtext}
80 \end{note}
81 \end{module}
82
83 %%% Local Variables:
84 %%% mode: LaTeX
85 %%% TeX-master: "all"
86 %%% End: \end{document}
87 </textarea></form>
88 <script>
89 var editor = CodeMirror.fromTextArea(document.getElementById("code"), {});
90 </script>
91
92 <p><strong>MIME types defined:</strong> <code>text/x-stex</code>.</p>
93
94 </body>
95 </html>
@@ -0,0 +1,182
1 /*
2 * Author: Constantin Jucovschi (c.jucovschi@jacobs-university.de)
3 * Licence: MIT
4 */
5
6 CodeMirror.defineMode("stex", function(cmCfg, modeCfg)
7 {
8 function pushCommand(state, command) {
9 state.cmdState.push(command);
10 }
11
12 function peekCommand(state) {
13 if (state.cmdState.length>0)
14 return state.cmdState[state.cmdState.length-1];
15 else
16 return null;
17 }
18
19 function popCommand(state) {
20 if (state.cmdState.length>0) {
21 var plug = state.cmdState.pop();
22 plug.closeBracket();
23 }
24 }
25
26 function applyMostPowerful(state) {
27 var context = state.cmdState;
28 for (var i = context.length - 1; i >= 0; i--) {
29 var plug = context[i];
30 if (plug.name=="DEFAULT")
31 continue;
32 return plug.styleIdentifier();
33 }
34 return null;
35 }
36
37 function addPluginPattern(pluginName, cmdStyle, brackets, styles) {
38 return function () {
39 this.name=pluginName;
40 this.bracketNo = 0;
41 this.style=cmdStyle;
42 this.styles = styles;
43 this.brackets = brackets;
44
45 this.styleIdentifier = function(content) {
46 if (this.bracketNo<=this.styles.length)
47 return this.styles[this.bracketNo-1];
48 else
49 return null;
50 };
51 this.openBracket = function(content) {
52 this.bracketNo++;
53 return "bracket";
54 };
55 this.closeBracket = function(content) {
56 };
57 }
58 }
59
60 var plugins = new Array();
61
62 plugins["importmodule"] = addPluginPattern("importmodule", "tag", "{[", ["string", "builtin"]);
63 plugins["documentclass"] = addPluginPattern("documentclass", "tag", "{[", ["", "atom"]);
64 plugins["usepackage"] = addPluginPattern("documentclass", "tag", "[", ["atom"]);
65 plugins["begin"] = addPluginPattern("documentclass", "tag", "[", ["atom"]);
66 plugins["end"] = addPluginPattern("documentclass", "tag", "[", ["atom"]);
67
68 plugins["DEFAULT"] = function () {
69 this.name="DEFAULT";
70 this.style="tag";
71
72 this.styleIdentifier = function(content) {
73 };
74 this.openBracket = function(content) {
75 };
76 this.closeBracket = function(content) {
77 };
78 };
79
80 function setState(state, f) {
81 state.f = f;
82 }
83
84 function normal(source, state) {
85 if (source.match(/^\\[a-zA-Z@]+/)) {
86 var cmdName = source.current();
87 cmdName = cmdName.substr(1, cmdName.length-1);
88 var plug;
89 if (plugins.hasOwnProperty(cmdName)) {
90 plug = plugins[cmdName];
91 } else {
92 plug = plugins["DEFAULT"];
93 }
94 plug = new plug();
95 pushCommand(state, plug);
96 setState(state, beginParams);
97 return plug.style;
98 }
99
100 // escape characters
101 if (source.match(/^\\[$&%#{}_]/)) {
102 return "tag";
103 }
104
105 // white space control characters
106 if (source.match(/^\\[,;!\/]/)) {
107 return "tag";
108 }
109
110 var ch = source.next();
111 if (ch == "%") {
112 // special case: % at end of its own line; stay in same state
113 if (!source.eol()) {
114 setState(state, inCComment);
115 }
116 return "comment";
117 }
118 else if (ch=='}' || ch==']') {
119 plug = peekCommand(state);
120 if (plug) {
121 plug.closeBracket(ch);
122 setState(state, beginParams);
123 } else
124 return "error";
125 return "bracket";
126 } else if (ch=='{' || ch=='[') {
127 plug = plugins["DEFAULT"];
128 plug = new plug();
129 pushCommand(state, plug);
130 return "bracket";
131 }
132 else if (/\d/.test(ch)) {
133 source.eatWhile(/[\w.%]/);
134 return "atom";
135 }
136 else {
137 source.eatWhile(/[\w-_]/);
138 return applyMostPowerful(state);
139 }
140 }
141
142 function inCComment(source, state) {
143 source.skipToEnd();
144 setState(state, normal);
145 return "comment";
146 }
147
148 function beginParams(source, state) {
149 var ch = source.peek();
150 if (ch == '{' || ch == '[') {
151 var lastPlug = peekCommand(state);
152 var style = lastPlug.openBracket(ch);
153 source.eat(ch);
154 setState(state, normal);
155 return "bracket";
156 }
157 if (/[ \t\r]/.test(ch)) {
158 source.eat(ch);
159 return null;
160 }
161 setState(state, normal);
162 lastPlug = peekCommand(state);
163 if (lastPlug) {
164 popCommand(state);
165 }
166 return normal(source, state);
167 }
168
169 return {
170 startState: function() { return { f:normal, cmdState:[] }; },
171 copyState: function(s) { return { f: s.f, cmdState: s.cmdState.slice(0, s.cmdState.length) }; },
172
173 token: function(stream, state) {
174 var t = state.f(stream, state);
175 var w = stream.current();
176 return t;
177 }
178 };
179 });
180
181 CodeMirror.defineMIME("text/x-stex", "stex");
182 CodeMirror.defineMIME("text/x-latex", "stex");
@@ -0,0 +1,263
1 <!doctype html>
2 <html>
3 <head>
4 <title>CodeMirror: sTeX mode</title>
5 <link rel="stylesheet" href="../../lib/codemirror.css">
6 <script src="../../lib/codemirror.js"></script>
7 <script src="stex.js"></script>
8 <link rel="stylesheet" href="../../test/mode_test.css">
9 <script src="../../test/mode_test.js"></script>
10 <link rel="stylesheet" href="../../doc/docs.css">
11 </head>
12 <body>
13 <h1>Tests for the sTeX Mode</h1>
14 <h2>Basics</h2>
15 <script language="javascript">
16 MT = ModeTest;
17
18 MT.test('foo',
19 null, 'foo');
20
21 MT.test('foo bar',
22 null, 'foo',
23 null, ' bar');
24 </script>
25
26 <h2>Tags</h2>
27 <script language="javascript">
28 MT.test('\\begin{document}\n\\end{document}',
29 'tag', '\\begin',
30 'bracket', '{',
31 'atom', 'document',
32 'bracket', '}',
33 'tag', '\\end',
34 'bracket', '{',
35 'atom', 'document',
36 'bracket', '}');
37
38 MT.test('\\begin{equation}\n E=mc^2\n\\end{equation}',
39 'tag', '\\begin',
40 'bracket', '{',
41 'atom', 'equation',
42 'bracket', '}',
43 null, ' ',
44 null, ' ',
45 null, 'E',
46 null, '=mc',
47 null, '^2',
48 'tag', '\\end',
49 'bracket', '{',
50 'atom', 'equation',
51 'bracket', '}');
52
53 MT.test('\\begin{module}[]',
54 'tag', '\\begin',
55 'bracket', '{',
56 'atom', 'module',
57 'bracket', '}',
58 'bracket', '[',
59 'bracket', ']');
60
61 MT.test('\\begin{module}[id=bbt-size]',
62 'tag', '\\begin',
63 'bracket', '{',
64 'atom', 'module',
65 'bracket', '}',
66 'bracket', '[',
67 null, 'id',
68 null, '=bbt-size',
69 'bracket', ']');
70
71 MT.test('\\importmodule[b-b-t]{b-b-t}',
72 'tag', '\\importmodule',
73 'bracket', '[',
74 'string', 'b-b-t',
75 'bracket', ']',
76 'bracket', '{',
77 'builtin', 'b-b-t',
78 'bracket', '}');
79
80 MT.test('\\importmodule[\\KWARCslides{dmath/en/cardinality}]{card}',
81 'tag', '\\importmodule',
82 'bracket', '[',
83 'tag', '\\KWARCslides',
84 'bracket', '{',
85 'string', 'dmath',
86 'string', '/en',
87 'string', '/cardinality',
88 'bracket', '}',
89 'bracket', ']',
90 'bracket', '{',
91 'builtin', 'card',
92 'bracket', '}');
93
94 MT.test('\\PSforPDF[1]{#1}', // could treat #1 specially
95 'tag', '\\PSforPDF',
96 'bracket', '[',
97 'atom', '1',
98 'bracket', ']',
99 'bracket', '{',
100 null, '#1',
101 'bracket', '}');
102 </script>
103
104 <h2>Comments</h2>
105 <script language="javascript">
106 MT.test('% foo',
107 'comment', '%',
108 'comment', ' foo');
109
110 MT.test('\\item% bar',
111 'tag', '\\item',
112 'comment', '%',
113 'comment', ' bar');
114
115 MT.test(' % \\item',
116 null, ' ',
117 'comment', '%',
118 'comment', ' \\item');
119
120 MT.test('%\nfoo',
121 'comment', '%',
122 null, 'foo');
123 </script>
124
125 <h2>Errors</h2>
126 <script language="javascript">
127 MT.test('\\begin}{',
128 'tag', '\\begin',
129 'error', '}',
130 'bracket', '{');
131
132 MT.test('\\item]{',
133 'tag', '\\item',
134 'error', ']',
135 'bracket', '{');
136
137 MT.test('% }',
138 'comment', '%',
139 'comment', ' }');
140 </script>
141
142 <h2>Character Escapes</h2>
143 <script language="javascript">
144 MT.test('the \\# key',
145 null, 'the',
146 null, ' ',
147 'tag', '\\#',
148 null, ' key');
149
150 MT.test('a \\$5 stetson',
151 null, 'a',
152 null, ' ',
153 'tag', '\\$',
154 'atom', 5,
155 null, ' stetson');
156
157 MT.test('100\\% beef',
158 'atom', '100',
159 'tag', '\\%',
160 null, ' beef');
161
162 MT.test('L \\& N',
163 null, 'L',
164 null, ' ',
165 'tag', '\\&',
166 null, ' N');
167
168 MT.test('foo\\_bar',
169 null, 'foo',
170 'tag', '\\_',
171 null, 'bar');
172
173 MT.test('\\emph{\\{}',
174 'tag', '\\emph',
175 'bracket','{',
176 'tag', '\\{',
177 'bracket','}');
178
179 MT.test('\\emph{\\}}',
180 'tag', '\\emph',
181 'bracket','{',
182 'tag', '\\}',
183 'bracket','}');
184
185 MT.test('section \\S1',
186 null, 'section',
187 null, ' ',
188 'tag', '\\S',
189 'atom', '1');
190
191 MT.test('para \\P2',
192 null, 'para',
193 null, ' ',
194 'tag', '\\P',
195 'atom', '2');
196
197 </script>
198
199 <h2>Spacing control</h2>
200
201 <script language="javascript">
202 MT.test('x\\,y', // thinspace
203 null, 'x',
204 'tag', '\\,',
205 null, 'y');
206
207 MT.test('x\\;y', // thickspace
208 null, 'x',
209 'tag', '\\;',
210 null, 'y');
211
212 MT.test('x\\!y', // negative thinspace
213 null, 'x',
214 'tag', '\\!',
215 null, 'y');
216
217 MT.test('J.\\ L.\\ is', // period not ending a sentence
218 null, 'J',
219 null, '.',
220 null, '\\',
221 null, ' L',
222 null, '.',
223 null, '\\',
224 null, ' is'); // maybe could be better
225
226 MT.test('X\\@. The', // period ending a sentence
227 null, 'X',
228 'tag', '\\@',
229 null, '.',
230 null, ' The');
231
232 MT.test('{\\em If\\/} I', // italic correction
233 'bracket', '{',
234 'tag', '\\em',
235 null, ' ',
236 null, 'If',
237 'tag', '\\/',
238 'bracket', '}',
239 null, ' ',
240 null, 'I');
241
242 </script>
243
244 <h2>New Commands</h2>
245
246 Should be able to define a new command that happens to be a method on Array
247 (e.g. <tt>pop</tt>):
248 <script language="javascript">
249 MT.test('\\newcommand{\\pop}',
250 'tag', '\\newcommand',
251 'bracket', '{',
252 'tag', '\\pop',
253 'bracket', '}');
254 </script>
255
256 <h2>Summary</h2>
257 <script language="javascript">
258 MT.printSummary();
259 </script>
260
261 </body>
262 </html>
263
@@ -0,0 +1,140
1 <!doctype html>
2 <html>
3 <head>
4 <title>CodeMirror: TiddlyWiki mode</title>
5 <link rel="stylesheet" href="../../lib/codemirror.css">
6 <script src="../../lib/codemirror.js"></script>
7 <script src="tiddlywiki.js"></script>
8 <link rel="stylesheet" href="tiddlywiki.css">
9 <link rel="stylesheet" href="../../doc/docs.css">
10 <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
11 </head>
12 <body>
13 <h1>CodeMirror: TiddlyWiki mode</h1>
14
15 <div><textarea id="code" name="code">
16 !TiddlyWiki Formatting
17 * Rendered versions can be found at: http://www.tiddlywiki.com/#Reference
18
19 |!Option | !Syntax |
20 |bold font | ''bold'' |
21 |italic type | //italic// |
22 |underlined text | __underlined__ |
23 |strikethrough text | --strikethrough-- |
24 |superscript text | super^^script^^ |
25 |subscript text | sub~~script~~ |
26 |highlighted text | @@highlighted@@ |
27 |preformatted text | {{{preformatted}}} |
28
29 !Block Elements
30 <<<
31 !Heading 1
32
33 !!Heading 2
34
35 !!!Heading 3
36
37 !!!!Heading 4
38
39 !!!!!Heading 5
40 <<<
41
42 !!Lists
43 <<<
44 * unordered list, level 1
45 ** unordered list, level 2
46 *** unordered list, level 3
47
48 # ordered list, level 1
49 ## ordered list, level 2
50 ### unordered list, level 3
51
52 ; definition list, term
53 : definition list, description
54 <<<
55
56 !!Blockquotes
57 <<<
58 > blockquote, level 1
59 >> blockquote, level 2
60 >>> blockquote, level 3
61
62 > blockquote
63 <<<
64
65 !!Preformatted Text
66 <<<
67 {{{
68 preformatted (e.g. code)
69 }}}
70 <<<
71
72 !!Code Sections
73 <<<
74 {{{
75 Text style code
76 }}}
77
78 //{{{
79 JS styled code. TiddlyWiki mixed mode should support highlighter switching in the future.
80 //}}}
81
82 <!--{{{-->
83 XML styled code. TiddlyWiki mixed mode should support highlighter switching in the future.
84 <!--}}}-->
85 <<<
86
87 !!Tables
88 <<<
89 |CssClass|k
90 |!heading column 1|!heading column 2|
91 |row 1, column 1|row 1, column 2|
92 |row 2, column 1|row 2, column 2|
93 |>|COLSPAN|
94 |ROWSPAN| ... |
95 |~| ... |
96 |CssProperty:value;...| ... |
97 |caption|c
98
99 ''Annotation:''
100 * The {{{>}}} marker creates a "colspan", causing the current cell to merge with the one to the right.
101 * The {{{~}}} marker creates a "rowspan", causing the current cell to merge with the one above.
102 <<<
103 !!Images /% TODO %/
104 cf. [[TiddlyWiki.com|http://www.tiddlywiki.com/#EmbeddedImages]]
105
106 !Hyperlinks
107 * [[WikiWords|WikiWord]] are automatically transformed to hyperlinks to the respective tiddler
108 ** the automatic transformation can be suppressed by preceding the respective WikiWord with a tilde ({{{~}}}): {{{~WikiWord}}}
109 * [[PrettyLinks]] are enclosed in square brackets and contain the desired tiddler name: {{{[[tiddler name]]}}}
110 ** optionally, a custom title or description can be added, separated by a pipe character ({{{|}}}): {{{[[title|target]]}}}<br>'''N.B.:''' In this case, the target can also be any website (i.e. URL).
111
112 !Custom Styling
113 * {{{@@CssProperty:value;CssProperty:value;...@@}}}<br>''N.B.:'' CSS color definitions should use lowercase letters to prevent the inadvertent creation of WikiWords.
114 * <html><code>{{customCssClass{...}}}</code></html>
115 * raw HTML can be inserted by enclosing the respective code in HTML tags: {{{<html> ... </html>}}}
116
117 !Special Markers
118 * {{{<br>}}} forces a manual line break
119 * {{{----}}} creates a horizontal ruler
120 * [[HTML entities|http://www.tiddlywiki.com/#HtmlEntities]]
121 * [[HTML entities local|HtmlEntities]]
122 * {{{<<macroName>>}}} calls the respective [[macro|Macros]]
123 * To hide text within a tiddler so that it is not displayed, it can be wrapped in {{{/%}}} and {{{%/}}}.<br/>This can be a useful trick for hiding drafts or annotating complex markup.
124 * To prevent wiki markup from taking effect for a particular section, that section can be enclosed in three double quotes: e.g. {{{"""WikiWord"""}}}.
125 </textarea></div>
126
127 <script>
128 var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
129 mode: 'tiddlywiki',
130 lineNumbers: true,
131 enterMode: 'keep',
132 matchBrackets: true
133 });
134 </script>
135
136 <p>TiddlyWiki mode supports a single configuration.</p>
137
138 <p><strong>MIME types defined:</strong> <code>text/x-tiddlywiki</code>.</p>
139 </body>
140 </html>
@@ -0,0 +1,14
1 span.cm-underlined {
2 text-decoration: underline;
3 }
4 span.cm-strikethrough {
5 text-decoration: line-through;
6 }
7 span.cm-brace {
8 color: #170;
9 font-weight: bold;
10 }
11 span.cm-table {
12 color: blue;
13 font-weight: bold;
14 }
@@ -0,0 +1,384
1 /***
2 |''Name''|tiddlywiki.js|
3 |''Description''|Enables TiddlyWikiy syntax highlighting using CodeMirror|
4 |''Author''|PMario|
5 |''Version''|0.1.7|
6 |''Status''|''stable''|
7 |''Source''|[[GitHub|https://github.com/pmario/CodeMirror2/blob/tw-syntax/mode/tiddlywiki]]|
8 |''Documentation''|http://codemirror.tiddlyspace.com/|
9 |''License''|[[MIT License|http://www.opensource.org/licenses/mit-license.php]]|
10 |''CoreVersion''|2.5.0|
11 |''Requires''|codemirror.js|
12 |''Keywords''|syntax highlighting color code mirror codemirror|
13 ! Info
14 CoreVersion parameter is needed for TiddlyWiki only!
15 ***/
16 //{{{
17 CodeMirror.defineMode("tiddlywiki", function (config, parserConfig) {
18 var indentUnit = config.indentUnit;
19
20 // Tokenizer
21 var textwords = function () {
22 function kw(type) {
23 return {
24 type: type,
25 style: "text"
26 };
27 }
28 return {};
29 }();
30
31 var keywords = function () {
32 function kw(type) {
33 return { type: type, style: "macro"};
34 }
35 return {
36 "allTags": kw('allTags'), "closeAll": kw('closeAll'), "list": kw('list'),
37 "newJournal": kw('newJournal'), "newTiddler": kw('newTiddler'),
38 "permaview": kw('permaview'), "saveChanges": kw('saveChanges'),
39 "search": kw('search'), "slider": kw('slider'), "tabs": kw('tabs'),
40 "tag": kw('tag'), "tagging": kw('tagging'), "tags": kw('tags'),
41 "tiddler": kw('tiddler'), "timeline": kw('timeline'),
42 "today": kw('today'), "version": kw('version'), "option": kw('option'),
43
44 "with": kw('with'),
45 "filter": kw('filter')
46 };
47 }();
48
49 var isSpaceName = /[\w_\-]/i,
50 reHR = /^\-\-\-\-+$/, // <hr>
51 reWikiCommentStart = /^\/\*\*\*$/, // /***
52 reWikiCommentStop = /^\*\*\*\/$/, // ***/
53 reBlockQuote = /^<<<$/,
54
55 reJsCodeStart = /^\/\/\{\{\{$/, // //{{{ js block start
56 reJsCodeStop = /^\/\/\}\}\}$/, // //}}} js stop
57 reXmlCodeStart = /^<!--\{\{\{-->$/, // xml block start
58 reXmlCodeStop = /^<!--\}\}\}-->$/, // xml stop
59
60 reCodeBlockStart = /^\{\{\{$/, // {{{ TW text div block start
61 reCodeBlockStop = /^\}\}\}$/, // }}} TW text stop
62
63 reCodeStart = /\{\{\{/, // {{{ code span start
64 reUntilCodeStop = /.*?\}\}\}/;
65
66 function chain(stream, state, f) {
67 state.tokenize = f;
68 return f(stream, state);
69 }
70
71 // used for strings
72 function nextUntilUnescaped(stream, end) {
73 var escaped = false,
74 next;
75 while ((next = stream.next()) != null) {
76 if (next == end && !escaped) return false;
77 escaped = !escaped && next == "\\";
78 }
79 return escaped;
80 }
81
82 // Used as scratch variables to communicate multiple values without
83 // consing up tons of objects.
84 var type, content;
85
86 function ret(tp, style, cont) {
87 type = tp;
88 content = cont;
89 return style;
90 }
91
92 function jsTokenBase(stream, state) {
93 var sol = stream.sol(),
94 ch, tch;
95
96 state.block = false; // indicates the start of a code block.
97
98 ch = stream.peek(); // don't eat, to make matching simpler
99
100 // check start of blocks
101 if (sol && /[<\/\*{}\-]/.test(ch)) {
102 if (stream.match(reCodeBlockStart)) {
103 state.block = true;
104 return chain(stream, state, twTokenCode);
105 }
106 if (stream.match(reBlockQuote)) {
107 return ret('quote', 'quote');
108 }
109 if (stream.match(reWikiCommentStart) || stream.match(reWikiCommentStop)) {
110 return ret('code', 'comment');
111 }
112 if (stream.match(reJsCodeStart) || stream.match(reJsCodeStop) || stream.match(reXmlCodeStart) || stream.match(reXmlCodeStop)) {
113 return ret('code', 'comment');
114 }
115 if (stream.match(reHR)) {
116 return ret('hr', 'hr');
117 }
118 } // sol
119 ch = stream.next();
120
121 if (sol && /[\/\*!#;:>|]/.test(ch)) {
122 if (ch == "!") { // tw header
123 stream.skipToEnd();
124 return ret("header", "header");
125 }
126 if (ch == "*") { // tw list
127 stream.eatWhile('*');
128 return ret("list", "comment");
129 }
130 if (ch == "#") { // tw numbered list
131 stream.eatWhile('#');
132 return ret("list", "comment");
133 }
134 if (ch == ";") { // definition list, term
135 stream.eatWhile(';');
136 return ret("list", "comment");
137 }
138 if (ch == ":") { // definition list, description
139 stream.eatWhile(':');
140 return ret("list", "comment");
141 }
142 if (ch == ">") { // single line quote
143 stream.eatWhile(">");
144 return ret("quote", "quote");
145 }
146 if (ch == '|') {
147 return ret('table', 'header');
148 }
149 }
150
151 if (ch == '{' && stream.match(/\{\{/)) {
152 return chain(stream, state, twTokenCode);
153 }
154
155 // rudimentary html:// file:// link matching. TW knows much more ...
156 if (/[hf]/i.test(ch)) {
157 if (/[ti]/i.test(stream.peek()) && stream.match(/\b(ttps?|tp|ile):\/\/[\-A-Z0-9+&@#\/%?=~_|$!:,.;]*[A-Z0-9+&@#\/%=~_|$]/i)) {
158 return ret("link", "link");
159 }
160 }
161 // just a little string indicator, don't want to have the whole string covered
162 if (ch == '"') {
163 return ret('string', 'string');
164 }
165 if (ch == '~') { // _no_ CamelCase indicator should be bold
166 return ret('text', 'brace');
167 }
168 if (/[\[\]]/.test(ch)) { // check for [[..]]
169 if (stream.peek() == ch) {
170 stream.next();
171 return ret('brace', 'brace');
172 }
173 }
174 if (ch == "@") { // check for space link. TODO fix @@...@@ highlighting
175 stream.eatWhile(isSpaceName);
176 return ret("link", "link");
177 }
178 if (/\d/.test(ch)) { // numbers
179 stream.eatWhile(/\d/);
180 return ret("number", "number");
181 }
182 if (ch == "/") { // tw invisible comment
183 if (stream.eat("%")) {
184 return chain(stream, state, twTokenComment);
185 }
186 else if (stream.eat("/")) { //
187 return chain(stream, state, twTokenEm);
188 }
189 }
190 if (ch == "_") { // tw underline
191 if (stream.eat("_")) {
192 return chain(stream, state, twTokenUnderline);
193 }
194 }
195 // strikethrough and mdash handling
196 if (ch == "-") {
197 if (stream.eat("-")) {
198 // if strikethrough looks ugly, change CSS.
199 if (stream.peek() != ' ')
200 return chain(stream, state, twTokenStrike);
201 // mdash
202 if (stream.peek() == ' ')
203 return ret('text', 'brace');
204 }
205 }
206 if (ch == "'") { // tw bold
207 if (stream.eat("'")) {
208 return chain(stream, state, twTokenStrong);
209 }
210 }
211 if (ch == "<") { // tw macro
212 if (stream.eat("<")) {
213 return chain(stream, state, twTokenMacro);
214 }
215 }
216 else {
217 return ret(ch);
218 }
219
220 // core macro handling
221 stream.eatWhile(/[\w\$_]/);
222 var word = stream.current(),
223 known = textwords.propertyIsEnumerable(word) && textwords[word];
224
225 return known ? ret(known.type, known.style, word) : ret("text", null, word);
226
227 } // jsTokenBase()
228
229 function twTokenString(quote) {
230 return function (stream, state) {
231 if (!nextUntilUnescaped(stream, quote)) state.tokenize = jsTokenBase;
232 return ret("string", "string");
233 };
234 }
235
236 // tw invisible comment
237 function twTokenComment(stream, state) {
238 var maybeEnd = false,
239 ch;
240 while (ch = stream.next()) {
241 if (ch == "/" && maybeEnd) {
242 state.tokenize = jsTokenBase;
243 break;
244 }
245 maybeEnd = (ch == "%");
246 }
247 return ret("comment", "comment");
248 }
249
250 // tw strong / bold
251 function twTokenStrong(stream, state) {
252 var maybeEnd = false,
253 ch;
254 while (ch = stream.next()) {
255 if (ch == "'" && maybeEnd) {
256 state.tokenize = jsTokenBase;
257 break;
258 }
259 maybeEnd = (ch == "'");
260 }
261 return ret("text", "strong");
262 }
263
264 // tw code
265 function twTokenCode(stream, state) {
266 var ch, sb = state.block;
267
268 if (sb && stream.current()) {
269 return ret("code", "comment");
270 }
271
272 if (!sb && stream.match(reUntilCodeStop)) {
273 state.tokenize = jsTokenBase;
274 return ret("code", "comment");
275 }
276
277 if (sb && stream.sol() && stream.match(reCodeBlockStop)) {
278 state.tokenize = jsTokenBase;
279 return ret("code", "comment");
280 }
281
282 ch = stream.next();
283 return (sb) ? ret("code", "comment") : ret("code", "comment");
284 }
285
286 // tw em / italic
287 function twTokenEm(stream, state) {
288 var maybeEnd = false,
289 ch;
290 while (ch = stream.next()) {
291 if (ch == "/" && maybeEnd) {
292 state.tokenize = jsTokenBase;
293 break;
294 }
295 maybeEnd = (ch == "/");
296 }
297 return ret("text", "em");
298 }
299
300 // tw underlined text
301 function twTokenUnderline(stream, state) {
302 var maybeEnd = false,
303 ch;
304 while (ch = stream.next()) {
305 if (ch == "_" && maybeEnd) {
306 state.tokenize = jsTokenBase;
307 break;
308 }
309 maybeEnd = (ch == "_");
310 }
311 return ret("text", "underlined");
312 }
313
314 // tw strike through text looks ugly
315 // change CSS if needed
316 function twTokenStrike(stream, state) {
317 var maybeEnd = false,
318 ch, nr;
319
320 while (ch = stream.next()) {
321 if (ch == "-" && maybeEnd) {
322 state.tokenize = jsTokenBase;
323 break;
324 }
325 maybeEnd = (ch == "-");
326 }
327 return ret("text", "strikethrough");
328 }
329
330 // macro
331 function twTokenMacro(stream, state) {
332 var ch, tmp, word, known;
333
334 if (stream.current() == '<<') {
335 return ret('brace', 'macro');
336 }
337
338 ch = stream.next();
339 if (!ch) {
340 state.tokenize = jsTokenBase;
341 return ret(ch);
342 }
343 if (ch == ">") {
344 if (stream.peek() == '>') {
345 stream.next();
346 state.tokenize = jsTokenBase;
347 return ret("brace", "macro");
348 }
349 }
350
351 stream.eatWhile(/[\w\$_]/);
352 word = stream.current();
353 known = keywords.propertyIsEnumerable(word) && keywords[word];
354
355 if (known) {
356 return ret(known.type, known.style, word);
357 }
358 else {
359 return ret("macro", null, word);
360 }
361 }
362
363 // Interface
364 return {
365 startState: function (basecolumn) {
366 return {
367 tokenize: jsTokenBase,
368 indented: 0,
369 level: 0
370 };
371 },
372
373 token: function (stream, state) {
374 if (stream.eatSpace()) return null;
375 var style = state.tokenize(stream, state);
376 return style;
377 },
378
379 electricChars: ""
380 };
381 });
382
383 CodeMirror.defineMIME("text/x-tiddlywiki", "tiddlywiki");
384 //}}}
@@ -0,0 +1,82
1 <html xmlns="http://www.w3.org/1999/xhtml">
2 <head>
3 <title>CodeMirror: Tiki wiki mode</title>
4 <link rel="stylesheet" href="../../lib/codemirror.css">
5 <script src="../../lib/codemirror.js"></script>
6 <script src="tiki.js"></script>
7 <link rel="stylesheet" href="tiki.css">
8 <link rel="stylesheet" href="../../doc/docs.css">
9 <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
10 </head>
11 <body style="padding: 20px;">
12 <h1>CodeMirror: Tiki wiki mode</h1>
13
14 <div><textarea id="code" name="code">
15 Headings
16 !Header 1
17 !!Header 2
18 !!!Header 3
19 !!!!Header 4
20 !!!!!Header 5
21 !!!!!!Header 6
22
23 Styling
24 -=titlebar=-
25 ^^ Box on multi
26 lines
27 of content^^
28 __bold__
29 ''italic''
30 ===underline===
31 ::center::
32 --Line Through--
33
34 Operators
35 ~np~No parse~/np~
36
37 Link
38 [link|desc|nocache]
39
40 Wiki
41 ((Wiki))
42 ((Wiki|desc))
43 ((Wiki|desc|timeout))
44
45 Table
46 ||row1 col1|row1 col2|row1 col3
47 row2 col1|row2 col2|row2 col3
48 row3 col1|row3 col2|row3 col3||
49
50 Lists:
51 *bla
52 **bla-1
53 ++continue-bla-1
54 ***bla-2
55 ++continue-bla-1
56 *bla
57 +continue-bla
58 #bla
59 ** tra-la-la
60 +continue-bla
61 #bla
62
63 Plugin (standard):
64 {PLUGIN(attr="my attr")}
65 Plugin Body
66 {PLUGIN}
67
68 Plugin (inline):
69 {plugin attr="my attr"}
70 </textarea></div>
71
72 <script type="text/javascript">
73 var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
74 mode: 'tiki',
75 lineNumbers: true,
76 enterMode: 'keep',
77 matchBrackets: true
78 });
79 </script>
80
81 </body>
82 </html>
@@ -0,0 +1,26
1 .cm-tw-syntaxerror {
2 color: #FFFFFF;
3 background-color: #990000;
4 }
5
6 .cm-tw-deleted {
7 text-decoration: line-through;
8 }
9
10 .cm-tw-header5 {
11 font-weight: bold;
12 }
13 .cm-tw-listitem:first-child { /*Added first child to fix duplicate padding when highlighting*/
14 padding-left: 10px;
15 }
16
17 .cm-tw-box {
18 border-top-width: 0px ! important;
19 border-style: solid;
20 border-width: 1px;
21 border-color: inherit;
22 }
23
24 .cm-tw-underline {
25 text-decoration: underline;
26 } No newline at end of file
@@ -0,0 +1,316
1 CodeMirror.defineMode('tiki', function(config, parserConfig) {
2 function inBlock(style, terminator, returnTokenizer) {
3 return function(stream, state) {
4 while (!stream.eol()) {
5 if (stream.match(terminator)) {
6 state.tokenize = inText;
7 break;
8 }
9 stream.next();
10 }
11
12 if (returnTokenizer) state.tokenize = returnTokenizer;
13
14 return style;
15 };
16 }
17
18 function inLine(style, terminator) {
19 return function(stream, state) {
20 while(!stream.eol()) {
21 stream.next()
22 }
23 state.tokenize = inText;
24 return style;
25 };
26 }
27
28 function inText(stream, state) {
29 function chain(parser) {
30 state.tokenize = parser;
31 return parser(stream, state);
32 }
33
34 var sol = stream.sol();
35 var ch = stream.next();
36
37 //non start of line
38 switch (ch) { //switch is generally much faster than if, so it is used here
39 case "{": //plugin
40 type = stream.eat("/") ? "closeTag" : "openTag";
41 stream.eatSpace();
42 tagName = "";
43 var c;
44 while ((c = stream.eat(/[^\s\u00a0=\"\'\/?(}]/))) tagName += c;
45 state.tokenize = inPlugin;
46 return "tag";
47 break;
48 case "_": //bold
49 if (stream.eat("_")) {
50 return chain(inBlock("strong", "__", inText));
51 }
52 break;
53 case "'": //italics
54 if (stream.eat("'")) {
55 // Italic text
56 return chain(inBlock("em", "''", inText));
57 }
58 break;
59 case "(":// Wiki Link
60 if (stream.eat("(")) {
61 return chain(inBlock("variable-2", "))", inText));
62 }
63 break;
64 case "[":// Weblink
65 return chain(inBlock("variable-3", "]", inText));
66 break;
67 case "|": //table
68 if (stream.eat("|")) {
69 return chain(inBlock("comment", "||"));
70 }
71 break;
72 case "-":
73 if (stream.eat("=")) {//titleBar
74 return chain(inBlock("header string", "=-", inText));
75 } else if (stream.eat("-")) {//deleted
76 return chain(inBlock("error tw-deleted", "--", inText));
77 }
78 break;
79 case "=": //underline
80 if (stream.match("==")) {
81 return chain(inBlock("tw-underline", "===", inText));
82 }
83 break;
84 case ":":
85 if (stream.eat(":")) {
86 return chain(inBlock("comment", "::"));
87 }
88 break;
89 case "^": //box
90 return chain(inBlock("tw-box", "^"));
91 break;
92 case "~": //np
93 if (stream.match("np~")) {
94 return chain(inBlock("meta", "~/np~"));
95 }
96 break;
97 }
98
99 //start of line types
100 if (sol) {
101 switch (ch) {
102 case "!": //header at start of line
103 if (stream.match('!!!!!')) {
104 return chain(inLine("header string"));
105 } else if (stream.match('!!!!')) {
106 return chain(inLine("header string"));
107 } else if (stream.match('!!!')) {
108 return chain(inLine("header string"));
109 } else if (stream.match('!!')) {
110 return chain(inLine("header string"));
111 } else {
112 return chain(inLine("header string"));
113 }
114 break;
115 case "*": //unordered list line item, or <li /> at start of line
116 case "#": //ordered list line item, or <li /> at start of line
117 case "+": //ordered list line item, or <li /> at start of line
118 return chain(inLine("tw-listitem bracket"));
119 break;
120 }
121 }
122
123 //stream.eatWhile(/[&{]/); was eating up plugins, turned off to act less like html and more like tiki
124 return null;
125 }
126
127 var indentUnit = config.indentUnit;
128
129 // Return variables for tokenizers
130 var pluginName, type;
131 function inPlugin(stream, state) {
132 var ch = stream.next();
133 var peek = stream.peek();
134
135 if (ch == "}") {
136 state.tokenize = inText;
137 //type = ch == ")" ? "endPlugin" : "selfclosePlugin"; inPlugin
138 return "tag";
139 } else if (ch == "(" || ch == ")") {
140 return "bracket";
141 } else if (ch == "=") {
142 type = "equals";
143
144 if (peek == ">") {
145 ch = stream.next();
146 peek = stream.peek();
147 }
148
149 //here we detect values directly after equal character with no quotes
150 if (!/[\'\"]/.test(peek)) {
151 state.tokenize = inAttributeNoQuote();
152 }
153 //end detect values
154
155 return "operator";
156 } else if (/[\'\"]/.test(ch)) {
157 state.tokenize = inAttribute(ch);
158 return state.tokenize(stream, state);
159 } else {
160 stream.eatWhile(/[^\s\u00a0=\"\'\/?]/);
161 return "keyword";
162 }
163 }
164
165 function inAttribute(quote) {
166 return function(stream, state) {
167 while (!stream.eol()) {
168 if (stream.next() == quote) {
169 state.tokenize = inPlugin;
170 break;
171 }
172 }
173 return "string";
174 };
175 }
176
177 function inAttributeNoQuote() {
178 return function(stream, state) {
179 while (!stream.eol()) {
180 var ch = stream.next();
181 var peek = stream.peek();
182 if (ch == " " || ch == "," || /[ )}]/.test(peek)) {
183 state.tokenize = inPlugin;
184 break;
185 }
186 }
187 return "string";
188 };
189 }
190
191 var curState, setStyle;
192 function pass() {
193 for (var i = arguments.length - 1; i >= 0; i--) curState.cc.push(arguments[i]);
194 }
195
196 function cont() {
197 pass.apply(null, arguments);
198 return true;
199 }
200
201 function pushContext(pluginName, startOfLine) {
202 var noIndent = curState.context && curState.context.noIndent;
203 curState.context = {
204 prev: curState.context,
205 pluginName: pluginName,
206 indent: curState.indented,
207 startOfLine: startOfLine,
208 noIndent: noIndent
209 };
210 }
211
212 function popContext() {
213 if (curState.context) curState.context = curState.context.prev;
214 }
215
216 function element(type) {
217 if (type == "openPlugin") {curState.pluginName = pluginName; return cont(attributes, endplugin(curState.startOfLine));}
218 else if (type == "closePlugin") {
219 var err = false;
220 if (curState.context) {
221 err = curState.context.pluginName != pluginName;
222 popContext();
223 } else {
224 err = true;
225 }
226 if (err) setStyle = "error";
227 return cont(endcloseplugin(err));
228 }
229 else if (type == "string") {
230 if (!curState.context || curState.context.name != "!cdata") pushContext("!cdata");
231 if (curState.tokenize == inText) popContext();
232 return cont();
233 }
234 else return cont();
235 }
236
237 function endplugin(startOfLine) {
238 return function(type) {
239 if (
240 type == "selfclosePlugin" ||
241 type == "endPlugin"
242 )
243 return cont();
244 if (type == "endPlugin") {pushContext(curState.pluginName, startOfLine); return cont();}
245 return cont();
246 };
247 }
248
249 function endcloseplugin(err) {
250 return function(type) {
251 if (err) setStyle = "error";
252 if (type == "endPlugin") return cont();
253 return pass();
254 }
255 }
256
257 function attributes(type) {
258 if (type == "keyword") {setStyle = "attribute"; return cont(attributes);}
259 if (type == "equals") return cont(attvalue, attributes);
260 return pass();
261 }
262 function attvalue(type) {
263 if (type == "keyword") {setStyle = "string"; return cont();}
264 if (type == "string") return cont(attvaluemaybe);
265 return pass();
266 }
267 function attvaluemaybe(type) {
268 if (type == "string") return cont(attvaluemaybe);
269 else return pass();
270 }
271 return {
272 startState: function() {
273 return {tokenize: inText, cc: [], indented: 0, startOfLine: true, pluginName: null, context: null};
274 },
275 token: function(stream, state) {
276 if (stream.sol()) {
277 state.startOfLine = true;
278 state.indented = stream.indentation();
279 }
280 if (stream.eatSpace()) return null;
281
282 setStyle = type = pluginName = null;
283 var style = state.tokenize(stream, state);
284 if ((style || type) && style != "comment") {
285 curState = state;
286 while (true) {
287 var comb = state.cc.pop() || element;
288 if (comb(type || style)) break;
289 }
290 }
291 state.startOfLine = false;
292 return setStyle || style;
293 },
294 indent: function(state, textAfter) {
295 var context = state.context;
296 if (context && context.noIndent) return 0;
297 if (context && /^{\//.test(textAfter))
298 context = context.prev;
299 while (context && !context.startOfLine)
300 context = context.prev;
301 if (context) return context.indent + indentUnit;
302 else return 0;
303 },
304 compareStates: function(a, b) {
305 if (a.indented != b.indented || a.pluginName != b.pluginName) return false;
306 for (var ca = a.context, cb = b.context; ; ca = ca.prev, cb = cb.prev) {
307 if (!ca || !cb) return ca == cb;
308 if (ca.pluginName != cb.pluginName) return false;
309 }
310 },
311 electricChars: "/"
312 };
313 });
314
315 //I figure, why not
316 CodeMirror.defineMIME("text/tiki", "tiki");
@@ -0,0 +1,21
1 The MIT License
2
3 Copyright (c) 2012 Codility Limited, 107 Cheapside, London EC2V 6DN, UK
4
5 Permission is hereby granted, free of charge, to any person obtaining a copy
6 of this software and associated documentation files (the "Software"), to deal
7 in the Software without restriction, including without limitation the rights
8 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 copies of the Software, and to permit persons to whom the Software is
10 furnished to do so, subject to the following conditions:
11
12 The above copyright notice and this permission notice shall be included in
13 all copies or substantial portions of the Software.
14
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 THE SOFTWARE.
@@ -0,0 +1,88
1 <html>
2 <head>
3 <title>CodeMirror: VB.NET mode</title>
4 <link rel="stylesheet" href="../../lib/codemirror.css">
5 <script src="../../lib/codemirror.js"></script>
6 <script src="vb.js"></script>
7 <link rel="stylesheet" href="../../doc/docs.css">
8 <link href="http://fonts.googleapis.com/css?family=Inconsolata" rel="stylesheet" type="text/css">
9 <style>
10 .CodeMirror {border: 1px solid #aaa; height:210px;}
11 .CodeMirror-scroll { overflow-x: auto; height: 100%;}
12 .CodeMirror pre { font-family: Inconsolata; font-size: 14px}
13 </style>
14 <script type="text/javascript" src="../../lib/util/runmode.js"></script>
15 </head>
16 <body onload="init()">
17 <h1>CodeMirror: VB.NET mode</h1>
18 <script type="text/javascript">
19 function test(golden, text) {
20 var ok = true;
21 var i = 0;
22 function callback(token, style, lineNo, pos){
23 //console.log(String(token) + " " + String(style) + " " + String(lineNo) + " " + String(pos));
24 var result = [String(token), String(style)];
25 if (golden[i][0] != result[0] || golden[i][1] != result[1]){
26 return "Error, expected: " + String(golden[i]) + ", got: " + String(result);
27 ok = false;
28 }
29 i++;
30 }
31 CodeMirror.runMode(text, "text/x-vb",callback);
32
33 if (ok) return "Tests OK";
34 }
35 function testTypes() {
36 var golden = [['Integer','keyword'],[' ','null'],['Float','keyword']]
37 var text = "Integer Float";
38 return test(golden,text);
39 }
40 function testIf(){
41 var golden = [['If','keyword'],[' ','null'],['True','keyword'],[' ','null'],['End','keyword'],[' ','null'],['If','keyword']];
42 var text = 'If True End If';
43 return test(golden, text);
44 }
45 function testDecl(){
46 var golden = [['Dim','keyword'],[' ','null'],['x','variable'],[' ','null'],['as','keyword'],[' ','null'],['Integer','keyword']];
47 var text = 'Dim x as Integer';
48 return test(golden, text);
49 }
50 function testAll(){
51 var result = "";
52
53 result += testTypes() + "\n";
54 result += testIf() + "\n";
55 result += testDecl() + "\n";
56 return result;
57
58 }
59 function initText(editor) {
60 var content = 'Class rocket\nPrivate quality as Double\nPublic Sub launch() as String\nif quality > 0.8\nlaunch = "Successful"\nElse\nlaunch = "Failed"\nEnd If\nEnd sub\nEnd class\n';
61 editor.setValue(content);
62 for (var i =0; i< editor.lineCount(); i++) editor.indentLine(i);
63 }
64 function init() {
65 editor = CodeMirror.fromTextArea(document.getElementById("solution"), {
66 lineNumbers: true,
67 matchBrackets: true,
68 mode: "text/x-vb",
69 readOnly: false,
70 tabMode: "shift"
71 });
72 runTest();
73 }
74 function runTest() {
75 document.getElementById('testresult').innerHTML = testAll();
76 initText(editor);
77
78 }
79 </script>
80
81
82 <div id="edit">
83 <textarea style="width:95%;height:200px;padding:5px;" name="solution" id="solution" ></textarea>
84 </div>
85 <pre id="testresult"></pre>
86 <p>MIME type defined: <code>text/x-vb</code>.</p>
87
88 </body></html>
@@ -0,0 +1,260
1 CodeMirror.defineMode("vb", function(conf, parserConf) {
2 var ERRORCLASS = 'error';
3
4 function wordRegexp(words) {
5 return new RegExp("^((" + words.join(")|(") + "))\\b", "i");
6 }
7
8 var singleOperators = new RegExp("^[\\+\\-\\*/%&\\\\|\\^~<>!]");
9 var singleDelimiters = new RegExp('^[\\(\\)\\[\\]\\{\\}@,:`=;\\.]');
10 var doubleOperators = new RegExp("^((==)|(<>)|(<=)|(>=)|(<>)|(<<)|(>>)|(//)|(\\*\\*))");
11 var doubleDelimiters = new RegExp("^((\\+=)|(\\-=)|(\\*=)|(%=)|(/=)|(&=)|(\\|=)|(\\^=))");
12 var tripleDelimiters = new RegExp("^((//=)|(>>=)|(<<=)|(\\*\\*=))");
13 var identifiers = new RegExp("^[_A-Za-z][_A-Za-z0-9]*");
14
15 var openingKeywords = ['class','module', 'sub','enum','select','while','if','function', 'get','set','property'];
16 var middleKeywords = ['else','elseif','case'];
17 var endKeywords = ['next','loop'];
18
19 var wordOperators = wordRegexp(['and', 'or', 'not', 'xor', 'in']);
20 var commonkeywords = ['as', 'dim', 'break', 'continue','optional', 'then', 'until',
21 'goto', 'byval','byref','new','handles','property', 'return',
22 'const','private', 'protected', 'friend', 'public', 'shared', 'static', 'true','false'];
23 var commontypes = ['integer','string','double','decimal','boolean','short','char', 'float','single'];
24
25 var keywords = wordRegexp(commonkeywords);
26 var types = wordRegexp(commontypes);
27 var stringPrefixes = '"';
28
29 var opening = wordRegexp(openingKeywords);
30 var middle = wordRegexp(middleKeywords);
31 var closing = wordRegexp(endKeywords);
32 var doubleClosing = wordRegexp(['end']);
33 var doOpening = wordRegexp(['do']);
34
35 var indentInfo = null;
36
37
38
39
40 function indent(stream, state) {
41 state.currentIndent++;
42 }
43
44 function dedent(stream, state) {
45 state.currentIndent--;
46 }
47 // tokenizers
48 function tokenBase(stream, state) {
49 if (stream.eatSpace()) {
50 return null;
51 }
52
53 var ch = stream.peek();
54
55 // Handle Comments
56 if (ch === "'") {
57 stream.skipToEnd();
58 return 'comment';
59 }
60
61
62 // Handle Number Literals
63 if (stream.match(/^((&H)|(&O))?[0-9\.a-f]/i, false)) {
64 var floatLiteral = false;
65 // Floats
66 if (stream.match(/^\d*\.\d+F?/i)) { floatLiteral = true; }
67 else if (stream.match(/^\d+\.\d*F?/)) { floatLiteral = true; }
68 else if (stream.match(/^\.\d+F?/)) { floatLiteral = true; }
69
70 if (floatLiteral) {
71 // Float literals may be "imaginary"
72 stream.eat(/J/i);
73 return 'number';
74 }
75 // Integers
76 var intLiteral = false;
77 // Hex
78 if (stream.match(/^&H[0-9a-f]+/i)) { intLiteral = true; }
79 // Octal
80 else if (stream.match(/^&O[0-7]+/i)) { intLiteral = true; }
81 // Decimal
82 else if (stream.match(/^[1-9]\d*F?/)) {
83 // Decimal literals may be "imaginary"
84 stream.eat(/J/i);
85 // TODO - Can you have imaginary longs?
86 intLiteral = true;
87 }
88 // Zero by itself with no other piece of number.
89 else if (stream.match(/^0(?![\dx])/i)) { intLiteral = true; }
90 if (intLiteral) {
91 // Integer literals may be "long"
92 stream.eat(/L/i);
93 return 'number';
94 }
95 }
96
97 // Handle Strings
98 if (stream.match(stringPrefixes)) {
99 state.tokenize = tokenStringFactory(stream.current());
100 return state.tokenize(stream, state);
101 }
102
103 // Handle operators and Delimiters
104 if (stream.match(tripleDelimiters) || stream.match(doubleDelimiters)) {
105 return null;
106 }
107 if (stream.match(doubleOperators)
108 || stream.match(singleOperators)
109 || stream.match(wordOperators)) {
110 return 'operator';
111 }
112 if (stream.match(singleDelimiters)) {
113 return null;
114 }
115 if (stream.match(doOpening)) {
116 indent(stream,state);
117 state.doInCurrentLine = true;
118 return 'keyword';
119 }
120 if (stream.match(opening)) {
121 if (! state.doInCurrentLine)
122 indent(stream,state);
123 else
124 state.doInCurrentLine = false;
125 return 'keyword';
126 }
127 if (stream.match(middle)) {
128 return 'keyword';
129 }
130
131 if (stream.match(doubleClosing)) {
132 dedent(stream,state);
133 dedent(stream,state);
134 return 'keyword';
135 }
136 if (stream.match(closing)) {
137 dedent(stream,state);
138 return 'keyword';
139 }
140
141 if (stream.match(types)) {
142 return 'keyword';
143 }
144
145 if (stream.match(keywords)) {
146 return 'keyword';
147 }
148
149 if (stream.match(identifiers)) {
150 return 'variable';
151 }
152
153 // Handle non-detected items
154 stream.next();
155 return ERRORCLASS;
156 }
157
158 function tokenStringFactory(delimiter) {
159 var singleline = delimiter.length == 1;
160 var OUTCLASS = 'string';
161
162 return function tokenString(stream, state) {
163 while (!stream.eol()) {
164 stream.eatWhile(/[^'"]/);
165 if (stream.match(delimiter)) {
166 state.tokenize = tokenBase;
167 return OUTCLASS;
168 } else {
169 stream.eat(/['"]/);
170 }
171 }
172 if (singleline) {
173 if (parserConf.singleLineStringErrors) {
174 return ERRORCLASS;
175 } else {
176 state.tokenize = tokenBase;
177 }
178 }
179 return OUTCLASS;
180 };
181 }
182
183
184 function tokenLexer(stream, state) {
185 var style = state.tokenize(stream, state);
186 var current = stream.current();
187
188 // Handle '.' connected identifiers
189 if (current === '.') {
190 style = state.tokenize(stream, state);
191 current = stream.current();
192 if (style === 'variable') {
193 return 'variable';
194 } else {
195 return ERRORCLASS;
196 }
197 }
198
199
200 var delimiter_index = '[({'.indexOf(current);
201 if (delimiter_index !== -1) {
202 indent(stream, state );
203 }
204 if (indentInfo === 'dedent') {
205 if (dedent(stream, state)) {
206 return ERRORCLASS;
207 }
208 }
209 delimiter_index = '])}'.indexOf(current);
210 if (delimiter_index !== -1) {
211 if (dedent(stream, state)) {
212 return ERRORCLASS;
213 }
214 }
215
216 return style;
217 }
218
219 var external = {
220 electricChars:"dDpPtTfFeE ",
221 startState: function(basecolumn) {
222 return {
223 tokenize: tokenBase,
224 lastToken: null,
225 currentIndent: 0,
226 nextLineIndent: 0,
227 doInCurrentLine: false
228
229
230 };
231 },
232
233 token: function(stream, state) {
234 if (stream.sol()) {
235 state.currentIndent += state.nextLineIndent;
236 state.nextLineIndent = 0;
237 state.doInCurrentLine = 0;
238 }
239 var style = tokenLexer(stream, state);
240
241 state.lastToken = {style:style, content: stream.current()};
242
243
244
245 return style;
246 },
247
248 indent: function(state, textAfter) {
249 var trueText = textAfter.replace(/^\s+|\s+$/g, '') ;
250 if (trueText.match(closing) || trueText.match(doubleClosing) || trueText.match(middle)) return conf.indentUnit*(state.currentIndent-1);
251 if(state.currentIndent < 0) return 0;
252 return state.currentIndent * conf.indentUnit;
253 }
254
255 };
256 return external;
257 });
258
259 CodeMirror.defineMIME("text/x-vb", "vb");
260
@@ -0,0 +1,42
1 <!doctype html>
2 <html>
3 <head>
4 <title>CodeMirror: VBScript mode</title>
5 <link rel="stylesheet" href="../../lib/codemirror.css">
6 <script src="../../lib/codemirror.js"></script>
7 <script src="vbscript.js"></script>
8 <link rel="stylesheet" href="../../doc/docs.css">
9 <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
10 </head>
11 <body>
12 <h1>CodeMirror: VBScript mode</h1>
13
14 <div><textarea id="code" name="code">
15 ' Pete Guhl
16 ' 03-04-2012
17 '
18 ' Basic VBScript support for codemirror2
19
20 Const ForReading = 1, ForWriting = 2, ForAppending = 8
21
22 Call Sub020_PostBroadcastToUrbanAirship(strUserName, strPassword, intTransmitID, strResponse)
23
24 If Not IsNull(strResponse) AND Len(strResponse) = 0 Then
25 boolTransmitOkYN = False
26 Else
27 ' WScript.Echo "Oh Happy Day! Oh Happy DAY!"
28 boolTransmitOkYN = True
29 End If
30 </textarea></div>
31
32 <script>
33 var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
34 lineNumbers: true,
35 matchBrackets: true
36 });
37 </script>
38
39 <p><strong>MIME types defined:</strong> <code>text/vbscript</code>.</p>
40 </body>
41 </html>
42
@@ -0,0 +1,26
1 CodeMirror.defineMode("vbscript", function() {
2 var regexVBScriptKeyword = /^(?:Call|Case|CDate|Clear|CInt|CLng|Const|CStr|Description|Dim|Do|Each|Else|ElseIf|End|Err|Error|Exit|False|For|Function|If|LCase|Loop|LTrim|Next|Nothing|Now|Number|On|Preserve|Quit|ReDim|Resume|RTrim|Select|Set|Sub|Then|To|Trim|True|UBound|UCase|Until|VbCr|VbCrLf|VbLf|VbTab)$/im;
3
4 return {
5 token: function(stream) {
6 if (stream.eatSpace()) return null;
7 var ch = stream.next();
8 if (ch == "'") {
9 stream.skipToEnd();
10 return "comment";
11 }
12 if (ch == '"') {
13 stream.skipTo('"');
14 return "string";
15 }
16
17 if (/\w/.test(ch)) {
18 stream.eatWhile(/\w/);
19 if (regexVBScriptKeyword.test(stream.current())) return "keyword";
20 }
21 return null;
22 }
23 };
24 });
25
26 CodeMirror.defineMIME("text/vbscript", "vbscript");
@@ -0,0 +1,103
1 <!doctype html>
2 <html>
3 <head>
4 <title>CodeMirror: Velocity mode</title>
5 <link rel="stylesheet" href="../../lib/codemirror.css">
6 <script src="../../lib/codemirror.js"></script>
7 <script src="velocity.js"></script>
8 <link rel="stylesheet" href="../../theme/night.css">
9 <style>.CodeMirror {border: 1px solid black;}</style>
10 <link rel="stylesheet" href="../../doc/docs.css">
11 </head>
12 <body>
13 <h1>CodeMirror: Velocity mode</h1>
14 <form><textarea id="code" name="code">
15 ## Velocity Code Demo
16 #*
17 based on PL/SQL mode by Peter Raganitsch, adapted to Velocity by Steve O'Hara ( http://www.pivotal-solutions.co.uk )
18 August 2011
19 *#
20
21 #*
22 This is a multiline comment.
23 This is the second line
24 *#
25
26 #[[ hello steve
27 This has invalid syntax that would normally need "poor man's escaping" like:
28
29 #define()
30
31 ${blah
32 ]]#
33
34 #include( "disclaimer.txt" "opinion.txt" )
35 #include( $foo $bar )
36
37 #parse( "lecorbusier.vm" )
38 #parse( $foo )
39
40 #evaluate( 'string with VTL #if(true)will be displayed#end' )
41
42 #define( $hello ) Hello $who #end #set( $who = "World!") $hello ## displays Hello World!
43
44 #foreach( $customer in $customerList )
45
46 $foreach.count $customer.Name
47
48 #if( $foo == ${bar})
49 it's true!
50 #break
51 #{else}
52 it's not!
53 #stop
54 #end
55
56 #if ($foreach.parent.hasNext)
57 $velocityCount
58 #end
59 #end
60
61 $someObject.getValues("this is a string split
62 across lines")
63
64 #macro( tablerows $color $somelist )
65 #foreach( $something in $somelist )
66 <tr><td bgcolor=$color>$something</td></tr>
67 #end
68 #end
69
70 #tablerows("red" ["dadsdf","dsa"])
71
72 Variable reference: #set( $monkey = $bill )
73 String literal: #set( $monkey.Friend = 'monica' )
74 Property reference: #set( $monkey.Blame = $whitehouse.Leak )
75 Method reference: #set( $monkey.Plan = $spindoctor.weave($web) )
76 Number literal: #set( $monkey.Number = 123 )
77 Range operator: #set( $monkey.Numbers = [1..3] )
78 Object list: #set( $monkey.Say = ["Not", $my, "fault"] )
79 Object map: #set( $monkey.Map = {"banana" : "good", "roast beef" : "bad"})
80
81 The RHS can also be a simple arithmetic expression, such as:
82 Addition: #set( $value = $foo + 1 )
83 Subtraction: #set( $value = $bar - 1 )
84 Multiplication: #set( $value = $foo * $bar )
85 Division: #set( $value = $foo / $bar )
86 Remainder: #set( $value = $foo % $bar )
87
88 </textarea></form>
89 <script>
90 var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
91 tabMode: "indent",
92 matchBrackets: true,
93 theme: "night",
94 lineNumbers: true,
95 indentUnit: 4,
96 mode: "text/velocity"
97 });
98 </script>
99
100 <p><strong>MIME types defined:</strong> <code>text/velocity</code>.</p>
101
102 </body>
103 </html>
@@ -0,0 +1,146
1 CodeMirror.defineMode("velocity", function(config) {
2 function parseWords(str) {
3 var obj = {}, words = str.split(" ");
4 for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
5 return obj;
6 }
7
8 var indentUnit = config.indentUnit
9 var keywords = parseWords("#end #else #break #stop #[[ #]] " +
10 "#{end} #{else} #{break} #{stop}");
11 var functions = parseWords("#if #elseif #foreach #set #include #parse #macro #define #evaluate " +
12 "#{if} #{elseif} #{foreach} #{set} #{include} #{parse} #{macro} #{define} #{evaluate}");
13 var specials = parseWords("$foreach.count $foreach.hasNext $foreach.first $foreach.last $foreach.topmost $foreach.parent $velocityCount");
14 var isOperatorChar = /[+\-*&%=<>!?:\/|]/;
15 var multiLineStrings =true;
16
17 function chain(stream, state, f) {
18 state.tokenize = f;
19 return f(stream, state);
20 }
21 function tokenBase(stream, state) {
22 var beforeParams = state.beforeParams;
23 state.beforeParams = false;
24 var ch = stream.next();
25 // start of string?
26 if ((ch == '"' || ch == "'") && state.inParams)
27 return chain(stream, state, tokenString(ch));
28 // is it one of the special signs []{}().,;? Seperator?
29 else if (/[\[\]{}\(\),;\.]/.test(ch)) {
30 if (ch == "(" && beforeParams) state.inParams = true;
31 else if (ch == ")") state.inParams = false;
32 return null;
33 }
34 // start of a number value?
35 else if (/\d/.test(ch)) {
36 stream.eatWhile(/[\w\.]/);
37 return "number";
38 }
39 // multi line comment?
40 else if (ch == "#" && stream.eat("*")) {
41 return chain(stream, state, tokenComment);
42 }
43 // unparsed content?
44 else if (ch == "#" && stream.match(/ *\[ *\[/)) {
45 return chain(stream, state, tokenUnparsed);
46 }
47 // single line comment?
48 else if (ch == "#" && stream.eat("#")) {
49 stream.skipToEnd();
50 return "comment";
51 }
52 // variable?
53 else if (ch == "$") {
54 stream.eatWhile(/[\w\d\$_\.{}]/);
55 // is it one of the specials?
56 if (specials && specials.propertyIsEnumerable(stream.current().toLowerCase())) {
57 return "keyword";
58 }
59 else {
60 state.beforeParams = true;
61 return "builtin";
62 }
63 }
64 // is it a operator?
65 else if (isOperatorChar.test(ch)) {
66 stream.eatWhile(isOperatorChar);
67 return "operator";
68 }
69 else {
70 // get the whole word
71 stream.eatWhile(/[\w\$_{}]/);
72 var word = stream.current().toLowerCase();
73 // is it one of the listed keywords?
74 if (keywords && keywords.propertyIsEnumerable(word))
75 return "keyword";
76 // is it one of the listed functions?
77 if (functions && functions.propertyIsEnumerable(word) ||
78 stream.current().match(/^#[a-z0-9_]+ *$/i) && stream.peek()=="(") {
79 state.beforeParams = true;
80 return "keyword";
81 }
82 // default: just a "word"
83 return null;
84 }
85 }
86
87 function tokenString(quote) {
88 return function(stream, state) {
89 var escaped = false, next, end = false;
90 while ((next = stream.next()) != null) {
91 if (next == quote && !escaped) {
92 end = true;
93 break;
94 }
95 escaped = !escaped && next == "\\";
96 }
97 if (end) state.tokenize = tokenBase;
98 return "string";
99 };
100 }
101
102 function tokenComment(stream, state) {
103 var maybeEnd = false, ch;
104 while (ch = stream.next()) {
105 if (ch == "#" && maybeEnd) {
106 state.tokenize = tokenBase;
107 break;
108 }
109 maybeEnd = (ch == "*");
110 }
111 return "comment";
112 }
113
114 function tokenUnparsed(stream, state) {
115 var maybeEnd = 0, ch;
116 while (ch = stream.next()) {
117 if (ch == "#" && maybeEnd == 2) {
118 state.tokenize = tokenBase;
119 break;
120 }
121 if (ch == "]")
122 maybeEnd++;
123 else if (ch != " ")
124 maybeEnd = 0;
125 }
126 return "meta";
127 }
128 // Interface
129
130 return {
131 startState: function(basecolumn) {
132 return {
133 tokenize: tokenBase,
134 beforeParams: false,
135 inParams: false
136 };
137 },
138
139 token: function(stream, state) {
140 if (stream.eatSpace()) return null;
141 return state.tokenize(stream, state);
142 }
143 };
144 });
145
146 CodeMirror.defineMIME("text/velocity", "velocity");
@@ -0,0 +1,210
1 <!doctype html>
2 <html>
3 <head>
4 <title>CodeMirror: Verilog mode</title>
5 <link rel="stylesheet" href="../../lib/codemirror.css">
6 <script src="../../lib/codemirror.js"></script>
7 <script src="verilog.js"></script>
8 <link rel="stylesheet" href="../../doc/docs.css">
9 <style>.CodeMirror {border: 2px inset #dee;}</style>
10 </head>
11 <body>
12 <h1>CodeMirror: Verilog mode</h1>
13
14 <form><textarea id="code" name="code">
15 /* Verilog demo code */
16
17 //////////////////////////////////////////////////////////////////////
18 //// ////
19 //// wb_master_model.v ////
20 //// ////
21 //// This file is part of the SPI IP core project ////
22 //// http://www.opencores.org/projects/spi/ ////
23 //// ////
24 //// Author(s): ////
25 //// - Simon Srot (simons@opencores.org) ////
26 //// ////
27 //// Based on: ////
28 //// - i2c/bench/verilog/wb_master_model.v ////
29 //// Copyright (C) 2001 Richard Herveille ////
30 //// ////
31 //// All additional information is avaliable in the Readme.txt ////
32 //// file. ////
33 //// ////
34 //////////////////////////////////////////////////////////////////////
35 //// ////
36 //// Copyright (C) 2002 Authors ////
37 //// ////
38 //// This source file may be used and distributed without ////
39 //// restriction provided that this copyright statement is not ////
40 //// removed from the file and that any derivative work contains ////
41 //// the original copyright notice and the associated disclaimer. ////
42 //// ////
43 //// This source file is free software; you can redistribute it ////
44 //// and/or modify it under the terms of the GNU Lesser General ////
45 //// Public License as published by the Free Software Foundation; ////
46 //// either version 2.1 of the License, or (at your option) any ////
47 //// later version. ////
48 //// ////
49 //// This source is distributed in the hope that it will be ////
50 //// useful, but WITHOUT ANY WARRANTY; without even the implied ////
51 //// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
52 //// PURPOSE. See the GNU Lesser General Public License for more ////
53 //// details. ////
54 //// ////
55 //// You should have received a copy of the GNU Lesser General ////
56 //// Public License along with this source; if not, download it ////
57 //// from http://www.opencores.org/lgpl.shtml ////
58 //// ////
59 //////////////////////////////////////////////////////////////////////
60
61 `include "timescale.v"
62
63 module wb_master_model(clk, rst, adr, din, dout, cyc, stb, we, sel, ack, err, rty);
64
65 parameter dwidth = 32;
66 parameter awidth = 32;
67
68 input clk, rst;
69 output [awidth -1:0] adr;
70 input [dwidth -1:0] din;
71 output [dwidth -1:0] dout;
72 output cyc, stb;
73 output we;
74 output [dwidth/8 -1:0] sel;
75 input ack, err, rty;
76
77 // Internal signals
78 reg [awidth -1:0] adr;
79 reg [dwidth -1:0] dout;
80 reg cyc, stb;
81 reg we;
82 reg [dwidth/8 -1:0] sel;
83
84 reg [dwidth -1:0] q;
85
86 // Memory Logic
87 initial
88 begin
89 adr = {awidth{1'bx}};
90 dout = {dwidth{1'bx}};
91 cyc = 1'b0;
92 stb = 1'bx;
93 we = 1'hx;
94 sel = {dwidth/8{1'bx}};
95 #1;
96 end
97
98 // Wishbone write cycle
99 task wb_write;
100 input delay;
101 integer delay;
102
103 input [awidth -1:0] a;
104 input [dwidth -1:0] d;
105
106 begin
107
108 // wait initial delay
109 repeat(delay) @(posedge clk);
110
111 // assert wishbone signal
112 #1;
113 adr = a;
114 dout = d;
115 cyc = 1'b1;
116 stb = 1'b1;
117 we = 1'b1;
118 sel = {dwidth/8{1'b1}};
119 @(posedge clk);
120
121 // wait for acknowledge from slave
122 while(~ack) @(posedge clk);
123
124 // negate wishbone signals
125 #1;
126 cyc = 1'b0;
127 stb = 1'bx;
128 adr = {awidth{1'bx}};
129 dout = {dwidth{1'bx}};
130 we = 1'hx;
131 sel = {dwidth/8{1'bx}};
132
133 end
134 endtask
135
136 // Wishbone read cycle
137 task wb_read;
138 input delay;
139 integer delay;
140
141 input [awidth -1:0] a;
142 output [dwidth -1:0] d;
143
144 begin
145
146 // wait initial delay
147 repeat(delay) @(posedge clk);
148
149 // assert wishbone signals
150 #1;
151 adr = a;
152 dout = {dwidth{1'bx}};
153 cyc = 1'b1;
154 stb = 1'b1;
155 we = 1'b0;
156 sel = {dwidth/8{1'b1}};
157 @(posedge clk);
158
159 // wait for acknowledge from slave
160 while(~ack) @(posedge clk);
161
162 // negate wishbone signals
163 #1;
164 cyc = 1'b0;
165 stb = 1'bx;
166 adr = {awidth{1'bx}};
167 dout = {dwidth{1'bx}};
168 we = 1'hx;
169 sel = {dwidth/8{1'bx}};
170 d = din;
171
172 end
173 endtask
174
175 // Wishbone compare cycle (read data from location and compare with expected data)
176 task wb_cmp;
177 input delay;
178 integer delay;
179
180 input [awidth -1:0] a;
181 input [dwidth -1:0] d_exp;
182
183 begin
184 wb_read (delay, a, q);
185
186 if (d_exp !== q) begin
187 $display("\n--- ERROR: At address 0x%0x, got 0x%0x, expected 0x%0x at time %t", a, q, d_exp, $time);
188 $stop;
189 end
190 end
191 endtask
192
193 endmodule
194 </textarea></form>
195
196 <script>
197 var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
198 lineNumbers: true,
199 matchBrackets: true,
200 mode: "text/x-verilog"
201 });
202 </script>
203
204 <p>Simple mode that tries to handle Verilog-like languages as well as it
205 can. Takes one configuration parameters: <code>keywords</code>, an
206 object whose property names are the keywords in the language.</p>
207
208 <p><strong>MIME types defined:</strong> <code>text/x-verilog</code> (Verilog code).</p>
209 </body>
210 </html>
@@ -0,0 +1,194
1 CodeMirror.defineMode("verilog", function(config, parserConfig) {
2 var indentUnit = config.indentUnit,
3 keywords = parserConfig.keywords || {},
4 blockKeywords = parserConfig.blockKeywords || {},
5 atoms = parserConfig.atoms || {},
6 hooks = parserConfig.hooks || {},
7 multiLineStrings = parserConfig.multiLineStrings;
8 var isOperatorChar = /[&|~><!\)\(*#%@+\/=?\:;}{,\.\^\-\[\]]/;
9
10 var curPunc;
11
12 function tokenBase(stream, state) {
13 var ch = stream.next();
14 if (hooks[ch]) {
15 var result = hooks[ch](stream, state);
16 if (result !== false) return result;
17 }
18 if (ch == '"') {
19 state.tokenize = tokenString(ch);
20 return state.tokenize(stream, state);
21 }
22 if (/[\[\]{}\(\),;\:\.]/.test(ch)) {
23 curPunc = ch;
24 return null
25 }
26 if (/[\d']/.test(ch)) {
27 stream.eatWhile(/[\w\.']/);
28 return "number";
29 }
30 if (ch == "/") {
31 if (stream.eat("*")) {
32 state.tokenize = tokenComment;
33 return tokenComment(stream, state);
34 }
35 if (stream.eat("/")) {
36 stream.skipToEnd();
37 return "comment";
38 }
39 }
40 if (isOperatorChar.test(ch)) {
41 stream.eatWhile(isOperatorChar);
42 return "operator";
43 }
44 stream.eatWhile(/[\w\$_]/);
45 var cur = stream.current();
46 if (keywords.propertyIsEnumerable(cur)) {
47 if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement";
48 return "keyword";
49 }
50 if (atoms.propertyIsEnumerable(cur)) return "atom";
51 return "variable";
52 }
53
54 function tokenString(quote) {
55 return function(stream, state) {
56 var escaped = false, next, end = false;
57 while ((next = stream.next()) != null) {
58 if (next == quote && !escaped) {end = true; break;}
59 escaped = !escaped && next == "\\";
60 }
61 if (end || !(escaped || multiLineStrings))
62 state.tokenize = tokenBase;
63 return "string";
64 };
65 }
66
67 function tokenComment(stream, state) {
68 var maybeEnd = false, ch;
69 while (ch = stream.next()) {
70 if (ch == "/" && maybeEnd) {
71 state.tokenize = tokenBase;
72 break;
73 }
74 maybeEnd = (ch == "*");
75 }
76 return "comment";
77 }
78
79 function Context(indented, column, type, align, prev) {
80 this.indented = indented;
81 this.column = column;
82 this.type = type;
83 this.align = align;
84 this.prev = prev;
85 }
86 function pushContext(state, col, type) {
87 return state.context = new Context(state.indented, col, type, null, state.context);
88 }
89 function popContext(state) {
90 var t = state.context.type;
91 if (t == ")" || t == "]" || t == "}")
92 state.indented = state.context.indented;
93 return state.context = state.context.prev;
94 }
95
96 // Interface
97
98 return {
99 startState: function(basecolumn) {
100 return {
101 tokenize: null,
102 context: new Context((basecolumn || 0) - indentUnit, 0, "top", false),
103 indented: 0,
104 startOfLine: true
105 };
106 },
107
108 token: function(stream, state) {
109 var ctx = state.context;
110 if (stream.sol()) {
111 if (ctx.align == null) ctx.align = false;
112 state.indented = stream.indentation();
113 state.startOfLine = true;
114 }
115 if (stream.eatSpace()) return null;
116 curPunc = null;
117 var style = (state.tokenize || tokenBase)(stream, state);
118 if (style == "comment" || style == "meta") return style;
119 if (ctx.align == null) ctx.align = true;
120
121 if ((curPunc == ";" || curPunc == ":") && ctx.type == "statement") popContext(state);
122 else if (curPunc == "{") pushContext(state, stream.column(), "}");
123 else if (curPunc == "[") pushContext(state, stream.column(), "]");
124 else if (curPunc == "(") pushContext(state, stream.column(), ")");
125 else if (curPunc == "}") {
126 while (ctx.type == "statement") ctx = popContext(state);
127 if (ctx.type == "}") ctx = popContext(state);
128 while (ctx.type == "statement") ctx = popContext(state);
129 }
130 else if (curPunc == ctx.type) popContext(state);
131 else if (ctx.type == "}" || ctx.type == "top" || (ctx.type == "statement" && curPunc == "newstatement"))
132 pushContext(state, stream.column(), "statement");
133 state.startOfLine = false;
134 return style;
135 },
136
137 indent: function(state, textAfter) {
138 if (state.tokenize != tokenBase && state.tokenize != null) return 0;
139 var firstChar = textAfter && textAfter.charAt(0), ctx = state.context, closing = firstChar == ctx.type;
140 if (ctx.type == "statement") return ctx.indented + (firstChar == "{" ? 0 : indentUnit);
141 else if (ctx.align) return ctx.column + (closing ? 0 : 1);
142 else return ctx.indented + (closing ? 0 : indentUnit);
143 },
144
145 electricChars: "{}"
146 };
147 });
148
149 (function() {
150 function words(str) {
151 var obj = {}, words = str.split(" ");
152 for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
153 return obj;
154 }
155
156 var verilogKeywords = "always and assign automatic begin buf bufif0 bufif1 case casex casez cell cmos config " +
157 "deassign default defparam design disable edge else end endcase endconfig endfunction endgenerate endmodule " +
158 "endprimitive endspecify endtable endtask event for force forever fork function generate genvar highz0 " +
159 "highz1 if ifnone incdir include initial inout input instance integer join large liblist library localparam " +
160 "macromodule medium module nand negedge nmos nor noshowcancelled not notif0 notif1 or output parameter pmos " +
161 "posedge primitive pull0 pull1 pulldown pullup pulsestyle_onevent pulsestyle_ondetect rcmos real realtime " +
162 "reg release repeat rnmos rpmos rtran rtranif0 rtranif1 scalared showcancelled signed small specify specparam " +
163 "strong0 strong1 supply0 supply1 table task time tran tranif0 tranif1 tri tri0 tri1 triand trior trireg " +
164 "unsigned use vectored wait wand weak0 weak1 while wire wor xnor xor";
165
166 var verilogBlockKeywords = "begin bufif0 bufif1 case casex casez config else end endcase endconfig endfunction " +
167 "endgenerate endmodule endprimitive endspecify endtable endtask for forever function generate if ifnone " +
168 "macromodule module primitive repeat specify table task while";
169
170 function metaHook(stream, state) {
171 stream.eatWhile(/[\w\$_]/);
172 return "meta";
173 }
174
175 // C#-style strings where "" escapes a quote.
176 function tokenAtString(stream, state) {
177 var next;
178 while ((next = stream.next()) != null) {
179 if (next == '"' && !stream.eat('"')) {
180 state.tokenize = null;
181 break;
182 }
183 }
184 return "string";
185 }
186
187 CodeMirror.defineMIME("text/x-verilog", {
188 name: "verilog",
189 keywords: words(verilogKeywords),
190 blockKeywords: words(verilogBlockKeywords),
191 atoms: words("null"),
192 hooks: {"`": metaHook, "$": metaHook}
193 });
194 }());
@@ -0,0 +1,20
1 Copyright (C) 2011 by MarkLogic Corporation
2 Author: Mike Brevoort <mike@brevoort.com>
3
4 Permission is hereby granted, free of charge, to any person obtaining a copy
5 of this software and associated documentation files (the "Software"), to deal
6 in the Software without restriction, including without limitation the rights
7 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 copies of the Software, and to permit persons to whom the Software is
9 furnished to do so, subject to the following conditions:
10
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
13
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 THE SOFTWARE. No newline at end of file
@@ -0,0 +1,222
1 <!doctype html>
2 <html>
3 <!--
4 /*
5 Copyright (C) 2011 by MarkLogic Corporation
6 Author: Mike Brevoort <mike@brevoort.com>
7
8 Permission is hereby granted, free of charge, to any person obtaining a copy
9 of this software and associated documentation files (the "Software"), to deal
10 in the Software without restriction, including without limitation the rights
11 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 copies of the Software, and to permit persons to whom the Software is
13 furnished to do so, subject to the following conditions:
14
15 The above copyright notice and this permission notice shall be included in
16 all copies or substantial portions of the Software.
17
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 THE SOFTWARE.
25 */
26 -->
27 <head>
28 <title>CodeMirror 2: JavaScript mode</title>
29 <link rel="stylesheet" href="../../lib/codemirror.css">
30 <script src="http://codemirror.net/lib/codemirror.js"></script>
31 <script src="xquery.js"></script>
32 <link rel="stylesheet" href="../../doc/docs.css">
33 <link rel="stylesheet" href="../../theme/xq-dark.css">
34 <style type="text/css">
35 .CodeMirror {
36 border-top: 1px solid black; border-bottom: 1px solid black;
37 }
38 .CodeMirror-scroll {
39 height:400px;
40 }
41 </style>
42 </head>
43 <body>
44 <h1>CodeMirror 2: XQuery mode</h1>
45
46 <div class="cm-s-default">
47 <textarea id="code" name="code">
48 xquery version &quot;1.0-ml&quot;;
49 (: this is
50 : a
51 "comment" :)
52 let $let := &lt;x attr=&quot;value&quot;&gt;&quot;test&quot;&lt;func&gt;function() $var {function()} {$var}&lt;/func&gt;&lt;/x&gt;
53 let $joe:=1
54 return element element {
55 attribute attribute { 1 },
56 element test { &#39;a&#39; },
57 attribute foo { &quot;bar&quot; },
58 fn:doc()[ foo/@bar eq $let ],
59 //x }
60
61 (: a more 'evil' test :)
62 (: Modified Blakeley example (: with nested comment :) ... :)
63 declare private function local:declare() {()};
64 declare private function local:private() {()};
65 declare private function local:function() {()};
66 declare private function local:local() {()};
67 let $let := &lt;let&gt;let $let := &quot;let&quot;&lt;/let&gt;
68 return element element {
69 attribute attribute { try { xdmp:version() } catch($e) { xdmp:log($e) } },
70 attribute fn:doc { &quot;bar&quot; castable as xs:string },
71 element text { text { &quot;text&quot; } },
72 fn:doc()[ child::eq/(@bar | attribute::attribute) eq $let ],
73 //fn:doc
74 }
75
76
77
78 xquery version &quot;1.0-ml&quot;;
79
80 (: Copyright 2006-2010 Mark Logic Corporation. :)
81
82 (:
83 : Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);
84 : you may not use this file except in compliance with the License.
85 : You may obtain a copy of the License at
86 :
87 : http://www.apache.org/licenses/LICENSE-2.0
88 :
89 : Unless required by applicable law or agreed to in writing, software
90 : distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
91 : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
92 : See the License for the specific language governing permissions and
93 : limitations under the License.
94 :)
95
96 module namespace json = &quot;http://marklogic.com/json&quot;;
97 declare default function namespace &quot;http://www.w3.org/2005/xpath-functions&quot;;
98
99 (: Need to backslash escape any double quotes, backslashes, and newlines :)
100 declare function json:escape($s as xs:string) as xs:string {
101 let $s := replace($s, &quot;\\&quot;, &quot;\\\\&quot;)
102 let $s := replace($s, &quot;&quot;&quot;&quot;, &quot;\\&quot;&quot;&quot;)
103 let $s := replace($s, codepoints-to-string((13, 10)), &quot;\\n&quot;)
104 let $s := replace($s, codepoints-to-string(13), &quot;\\n&quot;)
105 let $s := replace($s, codepoints-to-string(10), &quot;\\n&quot;)
106 return $s
107 };
108
109 declare function json:atomize($x as element()) as xs:string {
110 if (count($x/node()) = 0) then 'null'
111 else if ($x/@type = &quot;number&quot;) then
112 let $castable := $x castable as xs:float or
113 $x castable as xs:double or
114 $x castable as xs:decimal
115 return
116 if ($castable) then xs:string($x)
117 else error(concat(&quot;Not a number: &quot;, xdmp:describe($x)))
118 else if ($x/@type = &quot;boolean&quot;) then
119 let $castable := $x castable as xs:boolean
120 return
121 if ($castable) then xs:string(xs:boolean($x))
122 else error(concat(&quot;Not a boolean: &quot;, xdmp:describe($x)))
123 else concat('&quot;', json:escape($x), '&quot;')
124 };
125
126 (: Print the thing that comes after the colon :)
127 declare function json:print-value($x as element()) as xs:string {
128 if (count($x/*) = 0) then
129 json:atomize($x)
130 else if ($x/@quote = &quot;true&quot;) then
131 concat('&quot;', json:escape(xdmp:quote($x/node())), '&quot;')
132 else
133 string-join(('{',
134 string-join(for $i in $x/* return json:print-name-value($i), &quot;,&quot;),
135 '}'), &quot;&quot;)
136 };
137
138 (: Print the name and value both :)
139 declare function json:print-name-value($x as element()) as xs:string? {
140 let $name := name($x)
141 let $first-in-array :=
142 count($x/preceding-sibling::*[name(.) = $name]) = 0 and
143 (count($x/following-sibling::*[name(.) = $name]) &gt; 0 or $x/@array = &quot;true&quot;)
144 let $later-in-array := count($x/preceding-sibling::*[name(.) = $name]) &gt; 0
145 return
146
147 if ($later-in-array) then
148 () (: I was handled previously :)
149 else if ($first-in-array) then
150 string-join(('&quot;', json:escape($name), '&quot;:[',
151 string-join((for $i in ($x, $x/following-sibling::*[name(.) = $name]) return json:print-value($i)), &quot;,&quot;),
152 ']'), &quot;&quot;)
153 else
154 string-join(('&quot;', json:escape($name), '&quot;:', json:print-value($x)), &quot;&quot;)
155 };
156
157 (:~
158 Transforms an XML element into a JSON string representation. See http://json.org.
159 &lt;p/&gt;
160 Sample usage:
161 &lt;pre&gt;
162 xquery version &quot;1.0-ml&quot;;
163 import module namespace json=&quot;http://marklogic.com/json&quot; at &quot;json.xqy&quot;;
164 json:serialize(&amp;lt;foo&amp;gt;&amp;lt;bar&amp;gt;kid&amp;lt;/bar&amp;gt;&amp;lt;/foo&amp;gt;)
165 &lt;/pre&gt;
166 Sample transformations:
167 &lt;pre&gt;
168 &amp;lt;e/&amp;gt; becomes {&quot;e&quot;:null}
169 &amp;lt;e&amp;gt;text&amp;lt;/e&amp;gt; becomes {&quot;e&quot;:&quot;text&quot;}
170 &amp;lt;e&amp;gt;quote &quot; escaping&amp;lt;/e&amp;gt; becomes {&quot;e&quot;:&quot;quote \&quot; escaping&quot;}
171 &amp;lt;e&amp;gt;backslash \ escaping&amp;lt;/e&amp;gt; becomes {&quot;e&quot;:&quot;backslash \\ escaping&quot;}
172 &amp;lt;e&amp;gt;&amp;lt;a&amp;gt;text1&amp;lt;/a&amp;gt;&amp;lt;b&amp;gt;text2&amp;lt;/b&amp;gt;&amp;lt;/e&amp;gt; becomes {&quot;e&quot;:{&quot;a&quot;:&quot;text1&quot;,&quot;b&quot;:&quot;text2&quot;}}
173 &amp;lt;e&amp;gt;&amp;lt;a&amp;gt;text1&amp;lt;/a&amp;gt;&amp;lt;a&amp;gt;text2&amp;lt;/a&amp;gt;&amp;lt;/e&amp;gt; becomes {&quot;e&quot;:{&quot;a&quot;:[&quot;text1&quot;,&quot;text2&quot;]}}
174 &amp;lt;e&amp;gt;&amp;lt;a array=&quot;true&quot;&amp;gt;text1&amp;lt;/a&amp;gt;&amp;lt;/e&amp;gt; becomes {&quot;e&quot;:{&quot;a&quot;:[&quot;text1&quot;]}}
175 &amp;lt;e&amp;gt;&amp;lt;a type=&quot;boolean&quot;&amp;gt;false&amp;lt;/a&amp;gt;&amp;lt;/e&amp;gt; becomes {&quot;e&quot;:{&quot;a&quot;:false}}
176 &amp;lt;e&amp;gt;&amp;lt;a type=&quot;number&quot;&amp;gt;123.5&amp;lt;/a&amp;gt;&amp;lt;/e&amp;gt; becomes {&quot;e&quot;:{&quot;a&quot;:123.5}}
177 &amp;lt;e quote=&quot;true&quot;&amp;gt;&amp;lt;div attrib=&quot;value&quot;/&amp;gt;&amp;lt;/e&amp;gt; becomes {&quot;e&quot;:&quot;&amp;lt;div attrib=\&quot;value\&quot;/&amp;gt;&quot;}
178 &lt;/pre&gt;
179 &lt;p/&gt;
180 Namespace URIs are ignored. Namespace prefixes are included in the JSON name.
181 &lt;p/&gt;
182 Attributes are ignored, except for the special attribute @array=&quot;true&quot; that
183 indicates the JSON serialization should write the node, even if single, as an
184 array, and the attribute @type that can be set to &quot;boolean&quot; or &quot;number&quot; to
185 dictate the value should be written as that type (unquoted). There's also
186 an @quote attribute that when set to true writes the inner content as text
187 rather than as structured JSON, useful for sending some XHTML over the
188 wire.
189 &lt;p/&gt;
190 Text nodes within mixed content are ignored.
191
192 @param $x Element node to convert
193 @return String holding JSON serialized representation of $x
194
195 @author Jason Hunter
196 @version 1.0.1
197
198 Ported to xquery 1.0-ml; double escaped backslashes in json:escape
199 :)
200 declare function json:serialize($x as element()) as xs:string {
201 string-join(('{', json:print-name-value($x), '}'), &quot;&quot;)
202 };
203 </textarea>
204 </div>
205
206 <script>
207 var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
208 lineNumbers: true,
209 matchBrackets: true,
210 theme: "xq-dark"
211 });
212 </script>
213
214 <p><strong>MIME types defined:</strong> <code>application/xquery</code>.</p>
215
216 <p>Development of the CodeMirror XQuery mode was sponsored by
217 <a href="http://marklogic.com">MarkLogic</a> and developed by
218 <a href="https://twitter.com/mbrevoort">Mike Brevoort</a>.
219 </p>
220
221 </body>
222 </html>
@@ -0,0 +1,27
1 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
2 "http://www.w3.org/TR/html4/loose.dtd">
3 <html>
4 <head>
5 <link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-git.css" type="text/css"/>
6 <script src="http://code.jquery.com/jquery-latest.js"> </script>
7 <script type="text/javascript" src="http://code.jquery.com/qunit/qunit-git.js"></script>
8
9 <script src="../../../lib/codemirror.js"></script>
10 <script src="../xquery.js"></script>
11
12 <script type="text/javascript" src="testBase.js"></script>
13 <script type="text/javascript" src="testMultiAttr.js"></script>
14 <script type="text/javascript" src="testQuotes.js"></script>
15 <script type="text/javascript" src="testEmptySequenceKeyword.js"></script>
16 <script type="text/javascript" src="testProcessingInstructions.js"></script>
17 <script type="text/javascript" src="testNamespaces.js"></script>
18 </head>
19 <body>
20 <h1 id="qunit-header">XQuery CodeMirror Mode</h1>
21 <h2 id="qunit-banner"></h2>
22 <h2 id="qunit-userAgent"></h2>
23 <ol id="qunit-tests">
24 </ol>
25 <div id="sandbox" style="right:5000px; position:absolute; "></div>
26 </body>
27 </html>
@@ -0,0 +1,42
1 $(document).ready(function(){
2 module("testBase");
3 test("eviltest", function() {
4 expect(1);
5
6 var input = 'xquery version &quot;1.0-ml&quot;;\
7 (: this is\
8 : a \
9 "comment" :)\
10 let $let := &lt;x attr=&quot;value&quot;&gt;&quot;test&quot;&lt;func&gt;function() $var {function()} {$var}&lt;/func&gt;&lt;/x&gt;\
11 let $joe:=1\
12 return element element {\
13 attribute attribute { 1 },\
14 element test { &#39;a&#39; }, \
15 attribute foo { &quot;bar&quot; },\
16 fn:doc()[ foo/@bar eq $let ],\
17 //x } \
18 \
19 (: a more \'evil\' test :)\
20 (: Modified Blakeley example (: with nested comment :) ... :)\
21 declare private function local:declare() {()};\
22 declare private function local:private() {()};\
23 declare private function local:function() {()};\
24 declare private function local:local() {()};\
25 let $let := &lt;let&gt;let $let := &quot;let&quot;&lt;/let&gt;\
26 return element element {\
27 attribute attribute { try { xdmp:version() } catch($e) { xdmp:log($e) } },\
28 attribute fn:doc { &quot;bar&quot; castable as xs:string },\
29 element text { text { &quot;text&quot; } },\
30 fn:doc()[ child::eq/(@bar | attribute::attribute) eq $let ],\
31 //fn:doc\
32 }';
33 var expected = '<span class="cm-keyword">xquery</span> <span class="cm-keyword">version</span> <span class="cm-string">"1.0-ml"</span><span class="cm-variable cm-def">;</span> <span class="cm-comment">(: this is : a "comment" :)</span> <span class="cm-keyword">let</span> <span class="cm-variable">$let</span> <span class="cm-keyword">:=</span> <span class="cm-tag">&lt;x </span><span class="cm-attribute">attr</span>=<span class="cm-string">"value"</span><span class="cm-tag">&gt;</span><span class="cm-word">"test"</span><span class="cm-tag">&lt;func&gt;</span><span class="cm-word">function()</span> <span class="cm-word">$var</span> {<span class="cm-keyword">function</span>()} {<span class="cm-variable">$var</span>}<span class="cm-tag">&lt;/func&gt;&lt;/x&gt;</span> <span class="cm-keyword">let</span> <span class="cm-variable">$joe</span><span class="cm-keyword">:=</span><span class="cm-atom">1</span> <span class="cm-keyword">return</span> <span class="cm-keyword">element</span> <span class="cm-word">element</span> { <span class="cm-keyword">attribute</span> <span class="cm-word">attribute</span> { <span class="cm-atom">1</span> }, <span class="cm-keyword">element</span> <span class="cm-word">test</span> { <span class="cm-string">\'a\'</span> }, <span class="cm-keyword">attribute</span> <span class="cm-word">foo</span> { <span class="cm-string">"bar"</span> }, <span class="cm-variable cm-def">fn:doc</span>()[ <span class="cm-word">foo</span><span class="cm-keyword">/</span><span class="cm-word">@bar</span> <span class="cm-keyword">eq</span> <span class="cm-variable">$let</span> ], <span class="cm-keyword">//</span><span class="cm-word">x</span> } <span class="cm-comment">(: a more \'evil\' test :)</span> <span class="cm-comment">(: Modified Blakeley example (: with nested comment :) ... :)</span> <span class="cm-keyword">declare</span> <span class="cm-keyword">private</span> <span class="cm-keyword">function</span> <span class="cm-variable cm-def">local:declare</span>() {()}<span class="cm-word">;</span> <span class="cm-keyword">declare</span> <span class="cm-keyword">private</span> <span class="cm-keyword">function</span> <span class="cm-variable cm-def">local:private</span>() {()}<span class="cm-word">;</span> <span class="cm-keyword">declare</span> <span class="cm-keyword">private</span> <span class="cm-keyword">function</span> <span class="cm-variable cm-def">local:function</span>() {()}<span class="cm-word">;</span> <span class="cm-keyword">declare</span> <span class="cm-keyword">private</span> <span class="cm-keyword">function</span> <span class="cm-variable cm-def">local:local</span>() {()}<span class="cm-word">;</span> <span class="cm-keyword">let</span> <span class="cm-variable">$let</span> <span class="cm-keyword">:=</span> <span class="cm-tag">&lt;let&gt;</span><span class="cm-word">let</span> <span class="cm-word">$let</span> <span class="cm-word">:=</span> <span class="cm-word">"let"</span><span class="cm-tag">&lt;/let&gt;</span> <span class="cm-keyword">return</span> <span class="cm-keyword">element</span> <span class="cm-word">element</span> { <span class="cm-keyword">attribute</span> <span class="cm-word">attribute</span> { <span class="cm-keyword">try</span> { <span class="cm-variable cm-def">xdmp:version</span>() } <span class="cm-keyword">catch</span>(<span class="cm-variable">$e</span>) { <span class="cm-variable cm-def">xdmp:log</span>(<span class="cm-variable">$e</span>) } }, <span class="cm-keyword">attribute</span> <span class="cm-word">fn:doc</span> { <span class="cm-string">"bar"</span> <span class="cm-word">castable</span> <span class="cm-keyword">as</span> <span class="cm-atom">xs:string</span> }, <span class="cm-keyword">element</span> <span class="cm-word">text</span> { <span class="cm-keyword">text</span> { <span class="cm-string">"text"</span> } }, <span class="cm-variable cm-def">fn:doc</span>()[ <span class="cm-qualifier">child::</span><span class="cm-word">eq</span><span class="cm-keyword">/</span>(<span class="cm-word">@bar</span> <span class="cm-keyword">|</span> <span class="cm-qualifier">attribute::</span><span class="cm-word">attribute</span>) <span class="cm-keyword">eq</span> <span class="cm-variable">$let</span> ], <span class="cm-keyword">//</span><span class="cm-word">fn:doc</span> }';
34
35 $("#sandbox").html('<textarea id="editor">' + input + '</textarea>');
36 var editor = CodeMirror.fromTextArea($("#editor")[0]);
37 var result = $(".CodeMirror-lines div div pre")[0].innerHTML;
38
39 equal(result, expected);
40 $("#editor").html("");
41 });
42 });
@@ -0,0 +1,16
1 $(document).ready(function(){
2 module("testEmptySequenceKeyword");
3 test("testEmptySequenceKeyword", function() {
4 expect(1);
5
6 var input = '"foo" instance of empty-sequence()';
7 var expected = '<span class="cm-string">"foo"</span> <span class="cm-keyword">instance</span> <span class="cm-keyword">of</span> <span class="cm-keyword">empty-sequence</span>()';
8
9 $("#sandbox").html('<textarea id="editor">' + input + '</textarea>');
10 var editor = CodeMirror.fromTextArea($("#editor")[0]);
11 var result = $(".CodeMirror-lines div div pre")[0].innerHTML;
12
13 equal(result, expected);
14 $("#editor").html("");
15 });
16 });
@@ -0,0 +1,16
1 $(document).ready(function(){
2 module("testMultiAttr");
3 test("test1", function() {
4 expect(1);
5
6 var expected = '<span class="cm-tag">&lt;p </span><span class="cm-attribute">a1</span>=<span class="cm-string">"foo"</span> <span class="cm-attribute">a2</span>=<span class="cm-string">"bar"</span><span class="cm-tag">&gt;</span><span class="cm-word">hello</span> <span class="cm-word">world</span><span class="cm-tag">&lt;/p&gt;</span>';
7
8 $("#sandbox").html('<textarea id="editor"></textarea>');
9 $("#editor").html('<p a1="foo" a2="bar">hello world</p>');
10 var editor = CodeMirror.fromTextArea($("#editor")[0]);
11 var result = $(".CodeMirror-lines div div pre")[0].innerHTML;
12
13 equal(result, expected);
14 $("#editor").html("");
15 });
16 }); No newline at end of file
@@ -0,0 +1,91
1 $(document).ready(function(){
2 module("test namespaces");
3
4 // --------------------------------------------------------------------------------
5 // this test is based on this:
6 //http://mbrevoort.github.com/CodeMirror2/#!exprSeqTypes/PrologExpr/VariableProlog/ExternalVariablesWith/K2-ExternalVariablesWith-10.xq
7 // --------------------------------------------------------------------------------
8 test("test namespaced variable", function() {
9 expect(1);
10
11 var input = 'declare namespace e = "http://example.com/ANamespace";\
12 declare variable $e:exampleComThisVarIsNotRecognized as element(*) external;';
13
14 var expected = '<span class="cm-keyword">declare</span> <span class="cm-keyword">namespace</span> <span class="cm-word">e</span> <span class="cm-keyword">=</span> <span class="cm-string">"http://example.com/ANamespace"</span><span class="cm-word">;declare</span> <span class="cm-keyword">variable</span> <span class="cm-variable">$e:exampleComThisVarIsNotRecognized</span> <span class="cm-keyword">as</span> <span class="cm-keyword">element</span>(<span class="cm-keyword">*</span>) <span class="cm-word">external;</span>';
15
16 $("#sandbox").html('<textarea id="editor">' + input + '</textarea>');
17 var editor = CodeMirror.fromTextArea($("#editor")[0]);
18 var result = $(".CodeMirror-lines div div pre")[0].innerHTML;
19
20 equal(result, expected);
21 $("#editor").html("");
22 });
23
24
25 // --------------------------------------------------------------------------------
26 // this test is based on:
27 // http://mbrevoort.github.com/CodeMirror2/#!Basics/EQNames/eqname-002.xq
28 // --------------------------------------------------------------------------------
29 test("test EQName variable", function() {
30 expect(1);
31
32 var input = 'declare variable $"http://www.example.com/ns/my":var := 12;\
33 <out>{$"http://www.example.com/ns/my":var}</out>';
34
35 var expected = '<span class="cm-keyword">declare</span> <span class="cm-keyword">variable</span> <span class="cm-variable">$"http://www.example.com/ns/my":var</span> <span class="cm-keyword">:=</span> <span class="cm-atom">12</span><span class="cm-word">;</span><span class="cm-tag">&lt;out&gt;</span>{<span class="cm-variable">$"http://www.example.com/ns/my":var</span>}<span class="cm-tag">&lt;/out&gt;</span>';
36
37 $("#sandbox").html('<textarea id="editor">' + input + '</textarea>');
38 var editor = CodeMirror.fromTextArea($("#editor")[0]);
39 var result = $(".CodeMirror-lines div div pre")[0].innerHTML;
40
41 equal(result, expected);
42 $("#editor").html("");
43 });
44
45 // --------------------------------------------------------------------------------
46 // this test is based on:
47 // http://mbrevoort.github.com/CodeMirror2/#!Basics/EQNames/eqname-003.xq
48 // --------------------------------------------------------------------------------
49 test("test EQName function", function() {
50 expect(1);
51
52 var input = 'declare function "http://www.example.com/ns/my":fn ($a as xs:integer) as xs:integer {\
53 $a + 2\
54 };\
55 <out>{"http://www.example.com/ns/my":fn(12)}</out>';
56
57 var expected = '<span class="cm-keyword">declare</span> <span class="cm-keyword">function</span> <span class="cm-variable cm-def">"http://www.example.com/ns/my":fn</span> (<span class="cm-variable">$a</span> <span class="cm-keyword">as</span> <span class="cm-atom">xs:integer</span>) <span class="cm-keyword">as</span> <span class="cm-atom">xs:integer</span> { <span class="cm-variable">$a</span> <span class="cm-keyword">+</span> <span class="cm-atom">2</span>}<span class="cm-word">;</span><span class="cm-tag">&lt;out&gt;</span>{<span class="cm-variable cm-def">"http://www.example.com/ns/my":fn</span>(<span class="cm-atom">12</span>)}<span class="cm-tag">&lt;/out&gt;</span>';
58
59 $("#sandbox").html('<textarea id="editor">' + input + '</textarea>');
60 var editor = CodeMirror.fromTextArea($("#editor")[0]);
61 var result = $(".CodeMirror-lines div div pre")[0].innerHTML;
62
63 equal(result, expected);
64 $("#editor").html("");
65 });
66
67 // --------------------------------------------------------------------------------
68 // this test is based on:
69 // http://mbrevoort.github.com/CodeMirror2/#!Basics/EQNames/eqname-003.xq
70 // --------------------------------------------------------------------------------
71 test("test EQName function with single quotes", function() {
72 expect(1);
73
74 var input = 'declare function \'http://www.example.com/ns/my\':fn ($a as xs:integer) as xs:integer {\
75 $a + 2\
76 };\
77 <out>{\'http://www.example.com/ns/my\':fn(12)}</out>';
78
79 var expected = '<span class="cm-keyword">declare</span> <span class="cm-keyword">function</span> <span class="cm-variable cm-def">\'http://www.example.com/ns/my\':fn</span> (<span class="cm-variable">$a</span> <span class="cm-keyword">as</span> <span class="cm-atom">xs:integer</span>) <span class="cm-keyword">as</span> <span class="cm-atom">xs:integer</span> { <span class="cm-variable">$a</span> <span class="cm-keyword">+</span> <span class="cm-atom">2</span>}<span class="cm-word">;</span><span class="cm-tag">&lt;out&gt;</span>{<span class="cm-variable cm-def">\'http://www.example.com/ns/my\':fn</span>(<span class="cm-atom">12</span>)}<span class="cm-tag">&lt;/out&gt;</span>';
80
81 $("#sandbox").html('<textarea id="editor">' + input + '</textarea>');
82 var editor = CodeMirror.fromTextArea($("#editor")[0]);
83 var result = $(".CodeMirror-lines div div pre")[0].innerHTML;
84
85 equal(result, expected);
86 $("#editor").html("");
87 });
88
89 });
90
91
@@ -0,0 +1,16
1 $(document).ready(function(){
2 module("testProcessingInstructions");
3 test("testProcessingInstructions", function() {
4 expect(1);
5
6 var input = 'data(<?target content?>) instance of xs:string';
7 var expected = '<span class="cm-variable cm-def">data</span>(<span class="cm-comment cm-meta">&lt;?target content?&gt;</span>) <span class="cm-keyword">instance</span> <span class="cm-keyword">of</span> <span class="cm-atom">xs:string</span>';
8
9 $("#sandbox").html('<textarea id="editor">' + input + '</textarea>');
10 var editor = CodeMirror.fromTextArea($("#editor")[0]);
11 var result = $(".CodeMirror-lines div div pre")[0].innerHTML;
12
13 equal(result, expected);
14 $("#editor").html("");
15 });
16 });
@@ -0,0 +1,19
1 $(document).ready(function(){
2 module("testQuoteEscape");
3 test("testQuoteEscapeDouble", function() {
4 expect(1);
5
6 var input = 'let $rootfolder := "c:\\builds\\winnt\\HEAD\\qa\\scripts\\"\
7 let $keysfolder := concat($rootfolder, "keys\\")\
8 return\
9 $keysfolder';
10 var expected = '<span class="cm-keyword">let</span> <span class="cm-variable">$rootfolder</span> <span class="cm-keyword">:=</span> <span class="cm-string">"c:\\builds\\winnt\\HEAD\\qa\\scripts\\"</span><span class="cm-keyword">let</span> <span class="cm-variable">$keysfolder</span> <span class="cm-keyword">:=</span> <span class="cm-variable cm-def">concat</span>(<span class="cm-variable">$rootfolder</span>, <span class="cm-string">"keys\\"</span>)<span class="cm-word">return$keysfolder</span>';
11
12 $("#sandbox").html('<textarea id="editor">' + input + '</textarea>');
13 var editor = CodeMirror.fromTextArea($("#editor")[0]);
14 var result = $(".CodeMirror-lines div div pre")[0].innerHTML;
15
16 equal(result, expected);
17 $("#editor").html("");
18 });
19 });
@@ -0,0 +1,448
1 /*
2 Copyright (C) 2011 by MarkLogic Corporation
3 Author: Mike Brevoort <mike@brevoort.com>
4
5 Permission is hereby granted, free of charge, to any person obtaining a copy
6 of this software and associated documentation files (the "Software"), to deal
7 in the Software without restriction, including without limitation the rights
8 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 copies of the Software, and to permit persons to whom the Software is
10 furnished to do so, subject to the following conditions:
11
12 The above copyright notice and this permission notice shall be included in
13 all copies or substantial portions of the Software.
14
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 THE SOFTWARE.
22 */
23 CodeMirror.defineMode("xquery", function(config, parserConfig) {
24
25 // The keywords object is set to the result of this self executing
26 // function. Each keyword is a property of the keywords object whose
27 // value is {type: atype, style: astyle}
28 var keywords = function(){
29 // conveinence functions used to build keywords object
30 function kw(type) {return {type: type, style: "keyword"};}
31 var A = kw("keyword a")
32 , B = kw("keyword b")
33 , C = kw("keyword c")
34 , operator = kw("operator")
35 , atom = {type: "atom", style: "atom"}
36 , punctuation = {type: "punctuation", style: ""}
37 , qualifier = {type: "axis_specifier", style: "qualifier"};
38
39 // kwObj is what is return from this function at the end
40 var kwObj = {
41 'if': A, 'switch': A, 'while': A, 'for': A,
42 'else': B, 'then': B, 'try': B, 'finally': B, 'catch': B,
43 'element': C, 'attribute': C, 'let': C, 'implements': C, 'import': C, 'module': C, 'namespace': C,
44 'return': C, 'super': C, 'this': C, 'throws': C, 'where': C, 'private': C,
45 ',': punctuation,
46 'null': atom, 'fn:false()': atom, 'fn:true()': atom
47 };
48
49 // a list of 'basic' keywords. For each add a property to kwObj with the value of
50 // {type: basic[i], style: "keyword"} e.g. 'after' --> {type: "after", style: "keyword"}
51 var basic = ['after','ancestor','ancestor-or-self','and','as','ascending','assert','attribute','before',
52 'by','case','cast','child','comment','declare','default','define','descendant','descendant-or-self',
53 'descending','document','document-node','element','else','eq','every','except','external','following',
54 'following-sibling','follows','for','function','if','import','in','instance','intersect','item',
55 'let','module','namespace','node','node','of','only','or','order','parent','precedes','preceding',
56 'preceding-sibling','processing-instruction','ref','return','returns','satisfies','schema','schema-element',
57 'self','some','sortby','stable','text','then','to','treat','typeswitch','union','variable','version','where',
58 'xquery', 'empty-sequence'];
59 for(var i=0, l=basic.length; i < l; i++) { kwObj[basic[i]] = kw(basic[i])};
60
61 // a list of types. For each add a property to kwObj with the value of
62 // {type: "atom", style: "atom"}
63 var types = ['xs:string', 'xs:float', 'xs:decimal', 'xs:double', 'xs:integer', 'xs:boolean', 'xs:date', 'xs:dateTime',
64 'xs:time', 'xs:duration', 'xs:dayTimeDuration', 'xs:time', 'xs:yearMonthDuration', 'numeric', 'xs:hexBinary',
65 'xs:base64Binary', 'xs:anyURI', 'xs:QName', 'xs:byte','xs:boolean','xs:anyURI','xf:yearMonthDuration'];
66 for(var i=0, l=types.length; i < l; i++) { kwObj[types[i]] = atom;};
67
68 // each operator will add a property to kwObj with value of {type: "operator", style: "keyword"}
69 var operators = ['eq', 'ne', 'lt', 'le', 'gt', 'ge', ':=', '=', '>', '>=', '<', '<=', '.', '|', '?', 'and', 'or', 'div', 'idiv', 'mod', '*', '/', '+', '-'];
70 for(var i=0, l=operators.length; i < l; i++) { kwObj[operators[i]] = operator;};
71
72 // each axis_specifiers will add a property to kwObj with value of {type: "axis_specifier", style: "qualifier"}
73 var axis_specifiers = ["self::", "attribute::", "child::", "descendant::", "descendant-or-self::", "parent::",
74 "ancestor::", "ancestor-or-self::", "following::", "preceding::", "following-sibling::", "preceding-sibling::"];
75 for(var i=0, l=axis_specifiers.length; i < l; i++) { kwObj[axis_specifiers[i]] = qualifier; };
76
77 return kwObj;
78 }();
79
80 // Used as scratch variables to communicate multiple values without
81 // consing up tons of objects.
82 var type, content;
83
84 function ret(tp, style, cont) {
85 type = tp; content = cont;
86 return style;
87 }
88
89 function chain(stream, state, f) {
90 state.tokenize = f;
91 return f(stream, state);
92 }
93
94 // the primary mode tokenizer
95 function tokenBase(stream, state) {
96 var ch = stream.next(),
97 mightBeFunction = false,
98 isEQName = isEQNameAhead(stream);
99
100 // an XML tag (if not in some sub, chained tokenizer)
101 if (ch == "<") {
102 if(stream.match("!--", true))
103 return chain(stream, state, tokenXMLComment);
104
105 if(stream.match("![CDATA", false)) {
106 state.tokenize = tokenCDATA;
107 return ret("tag", "tag");
108 }
109
110 if(stream.match("?", false)) {
111 return chain(stream, state, tokenPreProcessing);
112 }
113
114 var isclose = stream.eat("/");
115 stream.eatSpace();
116 var tagName = "", c;
117 while ((c = stream.eat(/[^\s\u00a0=<>\"\'\/?]/))) tagName += c;
118
119 return chain(stream, state, tokenTag(tagName, isclose));
120 }
121 // start code block
122 else if(ch == "{") {
123 pushStateStack(state,{ type: "codeblock"});
124 return ret("", "");
125 }
126 // end code block
127 else if(ch == "}") {
128 popStateStack(state);
129 return ret("", "");
130 }
131 // if we're in an XML block
132 else if(isInXmlBlock(state)) {
133 if(ch == ">")
134 return ret("tag", "tag");
135 else if(ch == "/" && stream.eat(">")) {
136 popStateStack(state);
137 return ret("tag", "tag");
138 }
139 else
140 return ret("word", "variable");
141 }
142 // if a number
143 else if (/\d/.test(ch)) {
144 stream.match(/^\d*(?:\.\d*)?(?:E[+\-]?\d+)?/);
145 return ret("number", "atom");
146 }
147 // comment start
148 else if (ch === "(" && stream.eat(":")) {
149 pushStateStack(state, { type: "comment"});
150 return chain(stream, state, tokenComment);
151 }
152 // quoted string
153 else if ( !isEQName && (ch === '"' || ch === "'"))
154 return chain(stream, state, tokenString(ch));
155 // variable
156 else if(ch === "$") {
157 return chain(stream, state, tokenVariable);
158 }
159 // assignment
160 else if(ch ===":" && stream.eat("=")) {
161 return ret("operator", "keyword");
162 }
163 // open paren
164 else if(ch === "(") {
165 pushStateStack(state, { type: "paren"});
166 return ret("", "");
167 }
168 // close paren
169 else if(ch === ")") {
170 popStateStack(state);
171 return ret("", "");
172 }
173 // open paren
174 else if(ch === "[") {
175 pushStateStack(state, { type: "bracket"});
176 return ret("", "");
177 }
178 // close paren
179 else if(ch === "]") {
180 popStateStack(state);
181 return ret("", "");
182 }
183 else {
184 var known = keywords.propertyIsEnumerable(ch) && keywords[ch];
185
186 // if there's a EQName ahead, consume the rest of the string portion, it's likely a function
187 if(isEQName && ch === '\"') while(stream.next() !== '"'){}
188 if(isEQName && ch === '\'') while(stream.next() !== '\''){}
189
190 // gobble up a word if the character is not known
191 if(!known) stream.eatWhile(/[\w\$_-]/);
192
193 // gobble a colon in the case that is a lib func type call fn:doc
194 var foundColon = stream.eat(":")
195
196 // if there's not a second colon, gobble another word. Otherwise, it's probably an axis specifier
197 // which should get matched as a keyword
198 if(!stream.eat(":") && foundColon) {
199 stream.eatWhile(/[\w\$_-]/);
200 }
201 // if the next non whitespace character is an open paren, this is probably a function (if not a keyword of other sort)
202 if(stream.match(/^[ \t]*\(/, false)) {
203 mightBeFunction = true;
204 }
205 // is the word a keyword?
206 var word = stream.current();
207 known = keywords.propertyIsEnumerable(word) && keywords[word];
208
209 // if we think it's a function call but not yet known,
210 // set style to variable for now for lack of something better
211 if(mightBeFunction && !known) known = {type: "function_call", style: "variable def"};
212
213 // if the previous word was element, attribute, axis specifier, this word should be the name of that
214 if(isInXmlConstructor(state)) {
215 popStateStack(state);
216 return ret("word", "variable", word);
217 }
218 // as previously checked, if the word is element,attribute, axis specifier, call it an "xmlconstructor" and
219 // push the stack so we know to look for it on the next word
220 if(word == "element" || word == "attribute" || known.type == "axis_specifier") pushStateStack(state, {type: "xmlconstructor"});
221
222 // if the word is known, return the details of that else just call this a generic 'word'
223 return known ? ret(known.type, known.style, word) :
224 ret("word", "variable", word);
225 }
226 }
227
228 // handle comments, including nested
229 function tokenComment(stream, state) {
230 var maybeEnd = false, maybeNested = false, nestedCount = 0, ch;
231 while (ch = stream.next()) {
232 if (ch == ")" && maybeEnd) {
233 if(nestedCount > 0)
234 nestedCount--;
235 else {
236 popStateStack(state);
237 break;
238 }
239 }
240 else if(ch == ":" && maybeNested) {
241 nestedCount++;
242 }
243 maybeEnd = (ch == ":");
244 maybeNested = (ch == "(");
245 }
246
247 return ret("comment", "comment");
248 }
249
250 // tokenizer for string literals
251 // optionally pass a tokenizer function to set state.tokenize back to when finished
252 function tokenString(quote, f) {
253 return function(stream, state) {
254 var ch;
255
256 if(isInString(state) && stream.current() == quote) {
257 popStateStack(state);
258 if(f) state.tokenize = f;
259 return ret("string", "string");
260 }
261
262 pushStateStack(state, { type: "string", name: quote, tokenize: tokenString(quote, f) });
263
264 // if we're in a string and in an XML block, allow an embedded code block
265 if(stream.match("{", false) && isInXmlAttributeBlock(state)) {
266 state.tokenize = tokenBase;
267 return ret("string", "string");
268 }
269
270
271 while (ch = stream.next()) {
272 if (ch == quote) {
273 popStateStack(state);
274 if(f) state.tokenize = f;
275 break;
276 }
277 else {
278 // if we're in a string and in an XML block, allow an embedded code block in an attribute
279 if(stream.match("{", false) && isInXmlAttributeBlock(state)) {
280 state.tokenize = tokenBase;
281 return ret("string", "string");
282 }
283
284 }
285 }
286
287 return ret("string", "string");
288 };
289 }
290
291 // tokenizer for variables
292 function tokenVariable(stream, state) {
293 var isVariableChar = /[\w\$_-]/;
294
295 // a variable may start with a quoted EQName so if the next character is quote, consume to the next quote
296 if(stream.eat("\"")) {
297 while(stream.next() !== '\"'){};
298 stream.eat(":");
299 } else {
300 stream.eatWhile(isVariableChar);
301 if(!stream.match(":=", false)) stream.eat(":");
302 }
303 stream.eatWhile(isVariableChar);
304 state.tokenize = tokenBase;
305 return ret("variable", "variable");
306 }
307
308 // tokenizer for XML tags
309 function tokenTag(name, isclose) {
310 return function(stream, state) {
311 stream.eatSpace();
312 if(isclose && stream.eat(">")) {
313 popStateStack(state);
314 state.tokenize = tokenBase;
315 return ret("tag", "tag");
316 }
317 // self closing tag without attributes?
318 if(!stream.eat("/"))
319 pushStateStack(state, { type: "tag", name: name, tokenize: tokenBase});
320 if(!stream.eat(">")) {
321 state.tokenize = tokenAttribute;
322 return ret("tag", "tag");
323 }
324 else {
325 state.tokenize = tokenBase;
326 }
327 return ret("tag", "tag");
328 }
329 }
330
331 // tokenizer for XML attributes
332 function tokenAttribute(stream, state) {
333 var ch = stream.next();
334
335 if(ch == "/" && stream.eat(">")) {
336 if(isInXmlAttributeBlock(state)) popStateStack(state);
337 if(isInXmlBlock(state)) popStateStack(state);
338 return ret("tag", "tag");
339 }
340 if(ch == ">") {
341 if(isInXmlAttributeBlock(state)) popStateStack(state);
342 return ret("tag", "tag");
343 }
344 if(ch == "=")
345 return ret("", "");
346 // quoted string
347 if (ch == '"' || ch == "'")
348 return chain(stream, state, tokenString(ch, tokenAttribute));
349
350 if(!isInXmlAttributeBlock(state))
351 pushStateStack(state, { type: "attribute", name: name, tokenize: tokenAttribute});
352
353 stream.eat(/[a-zA-Z_:]/);
354 stream.eatWhile(/[-a-zA-Z0-9_:.]/);
355 stream.eatSpace();
356
357 // the case where the attribute has not value and the tag was closed
358 if(stream.match(">", false) || stream.match("/", false)) {
359 popStateStack(state);
360 state.tokenize = tokenBase;
361 }
362
363 return ret("attribute", "attribute");
364 }
365
366 // handle comments, including nested
367 function tokenXMLComment(stream, state) {
368 while (ch = stream.next()) {
369 if (ch == "-" && stream.match("->", true)) {
370 state.tokenize = tokenBase;
371 return ret("comment", "comment");
372 }
373 }
374 }
375
376
377 // handle CDATA
378 function tokenCDATA(stream, state) {
379 while (ch = stream.next()) {
380 if (ch == "]" && stream.match("]", true)) {
381 state.tokenize = tokenBase;
382 return ret("comment", "comment");
383 }
384 }
385 }
386
387 // handle preprocessing instructions
388 function tokenPreProcessing(stream, state) {
389 while (ch = stream.next()) {
390 if (ch == "?" && stream.match(">", true)) {
391 state.tokenize = tokenBase;
392 return ret("comment", "comment meta");
393 }
394 }
395 }
396
397
398 // functions to test the current context of the state
399 function isInXmlBlock(state) { return isIn(state, "tag"); }
400 function isInXmlAttributeBlock(state) { return isIn(state, "attribute"); }
401 function isInCodeBlock(state) { return isIn(state, "codeblock"); }
402 function isInXmlConstructor(state) { return isIn(state, "xmlconstructor"); }
403 function isInString(state) { return isIn(state, "string"); }
404
405 function isEQNameAhead(stream) {
406 // assume we've already eaten a quote (")
407 if(stream.current() === '"')
408 return stream.match(/^[^\"]+\"\:/, false);
409 else if(stream.current() === '\'')
410 return stream.match(/^[^\"]+\'\:/, false);
411 else
412 return false;
413 }
414
415 function isIn(state, type) {
416 return (state.stack.length && state.stack[state.stack.length - 1].type == type);
417 }
418
419 function pushStateStack(state, newState) {
420 state.stack.push(newState);
421 }
422
423 function popStateStack(state) {
424 var popped = state.stack.pop();
425 var reinstateTokenize = state.stack.length && state.stack[state.stack.length-1].tokenize
426 state.tokenize = reinstateTokenize || tokenBase;
427 }
428
429 // the interface for the mode API
430 return {
431 startState: function(basecolumn) {
432 return {
433 tokenize: tokenBase,
434 cc: [],
435 stack: []
436 };
437 },
438
439 token: function(stream, state) {
440 if (stream.eatSpace()) return null;
441 var style = state.tokenize(stream, state);
442 return style;
443 }
444 };
445
446 });
447
448 CodeMirror.defineMIME("application/xquery", "xquery");
@@ -0,0 +1,67
1 <!doctype html>
2 <html>
3 <head>
4 <title>CodeMirror: YAML mode</title>
5 <link rel="stylesheet" href="../../lib/codemirror.css">
6 <script src="../../lib/codemirror.js"></script>
7 <script src="yaml.js"></script>
8 <style>.CodeMirror { border-top: 1px solid #ddd; border-bottom: 1px solid #ddd; }</style>
9 <link rel="stylesheet" href="../../doc/docs.css">
10 </head>
11 <body>
12 <h1>CodeMirror: YAML mode</h1>
13 <form><textarea id="code" name="code">
14 --- # Favorite movies
15 - Casablanca
16 - North by Northwest
17 - The Man Who Wasn't There
18 --- # Shopping list
19 [milk, pumpkin pie, eggs, juice]
20 --- # Indented Blocks, common in YAML data files, use indentation and new lines to separate the key: value pairs
21 name: John Smith
22 age: 33
23 --- # Inline Blocks, common in YAML data streams, use commas to separate the key: value pairs between braces
24 {name: John Smith, age: 33}
25 ---
26 receipt: Oz-Ware Purchase Invoice
27 date: 2007-08-06
28 customer:
29 given: Dorothy
30 family: Gale
31
32 items:
33 - part_no: A4786
34 descrip: Water Bucket (Filled)
35 price: 1.47
36 quantity: 4
37
38 - part_no: E1628
39 descrip: High Heeled "Ruby" Slippers
40 size: 8
41 price: 100.27
42 quantity: 1
43
44 bill-to: &id001
45 street: |
46 123 Tornado Alley
47 Suite 16
48 city: East Centerville
49 state: KS
50
51 ship-to: *id001
52
53 specialDelivery: >
54 Follow the Yellow Brick
55 Road to the Emerald City.
56 Pay no attention to the
57 man behind the curtain.
58 ...
59 </textarea></form>
60 <script>
61 var editor = CodeMirror.fromTextArea(document.getElementById("code"), {});
62 </script>
63
64 <p><strong>MIME types defined:</strong> <code>text/x-yaml</code>.</p>
65
66 </body>
67 </html>
@@ -0,0 +1,95
1 CodeMirror.defineMode("yaml", function() {
2
3 var cons = ['true', 'false', 'on', 'off', 'yes', 'no'];
4 var keywordRegex = new RegExp("\\b(("+cons.join(")|(")+"))$", 'i');
5
6 return {
7 token: function(stream, state) {
8 var ch = stream.peek();
9 var esc = state.escaped;
10 state.escaped = false;
11 /* comments */
12 if (ch == "#") { stream.skipToEnd(); return "comment"; }
13 if (state.literal && stream.indentation() > state.keyCol) {
14 stream.skipToEnd(); return "string";
15 } else if (state.literal) { state.literal = false; }
16 if (stream.sol()) {
17 state.keyCol = 0;
18 state.pair = false;
19 state.pairStart = false;
20 /* document start */
21 if(stream.match(/---/)) { return "def"; }
22 /* document end */
23 if (stream.match(/\.\.\./)) { return "def"; }
24 /* array list item */
25 if (stream.match(/\s*-\s+/)) { return 'meta'; }
26 }
27 /* pairs (associative arrays) -> key */
28 if (!state.pair && stream.match(/^\s*([a-z0-9\._-])+(?=\s*:)/i)) {
29 state.pair = true;
30 state.keyCol = stream.indentation();
31 return "atom";
32 }
33 if (state.pair && stream.match(/^:\s*/)) { state.pairStart = true; return 'meta'; }
34
35 /* inline pairs/lists */
36 if (stream.match(/^(\{|\}|\[|\])/)) {
37 if (ch == '{')
38 state.inlinePairs++;
39 else if (ch == '}')
40 state.inlinePairs--;
41 else if (ch == '[')
42 state.inlineList++;
43 else
44 state.inlineList--;
45 return 'meta';
46 }
47
48 /* list seperator */
49 if (state.inlineList > 0 && !esc && ch == ',') {
50 stream.next();
51 return 'meta';
52 }
53 /* pairs seperator */
54 if (state.inlinePairs > 0 && !esc && ch == ',') {
55 state.keyCol = 0;
56 state.pair = false;
57 state.pairStart = false;
58 stream.next();
59 return 'meta';
60 }
61
62 /* start of value of a pair */
63 if (state.pairStart) {
64 /* block literals */
65 if (stream.match(/^\s*(\||\>)\s*/)) { state.literal = true; return 'meta'; };
66 /* references */
67 if (stream.match(/^\s*(\&|\*)[a-z0-9\._-]+\b/i)) { return 'variable-2'; }
68 /* numbers */
69 if (state.inlinePairs == 0 && stream.match(/^\s*-?[0-9\.\,]+\s?$/)) { return 'number'; }
70 if (state.inlinePairs > 0 && stream.match(/^\s*-?[0-9\.\,]+\s?(?=(,|}))/)) { return 'number'; }
71 /* keywords */
72 if (stream.match(keywordRegex)) { return 'keyword'; }
73 }
74
75 /* nothing found, continue */
76 state.pairStart = false;
77 state.escaped = (ch == '\\');
78 stream.next();
79 return null;
80 },
81 startState: function() {
82 return {
83 pair: false,
84 pairStart: false,
85 keyCol: 0,
86 inlinePairs: 0,
87 inlineList: 0,
88 literal: false,
89 escaped: false
90 };
91 }
92 };
93 });
94
95 CodeMirror.defineMIME("text/x-yaml", "yaml");
@@ -0,0 +1,29
1 {
2 "name": "CodeMirror",
3 "version":"2.32.0",
4 "main": "codemirror.js",
5 "description": "In-browser code editing made bearable",
6 "licenses": [
7 {
8 "type": "MIT",
9 "url": "http://codemirror.net/LICENSE"
10 }
11 ],
12 "directories": {
13 "lib": "./lib"
14 },
15 "bugs": "http://github.com/marijnh/CodeMirror2/issues",
16 "keywords": ["JavaScript", "CodeMirror", "Editor"],
17 "homepage": "http://codemirror.net",
18 "maintainers":[ {
19 "name": "Marijn Haverbeke",
20 "email": "marijnh@gmail.com",
21 "web": "http://codemirror.net"
22 }],
23 "repositories": [
24 {
25 "type": "git",
26 "url": "https://github.com/marijnh/CodeMirror2.git"
27 }
28 ]
29 }
@@ -0,0 +1,81
1 /* ambiance theme for code-mirror */
2
3 /* Color scheme */
4
5 .cm-s-ambiance .cm-keyword { color: #cda869; }
6 .cm-s-ambiance .cm-atom { color: #CF7EA9; }
7 .cm-s-ambiance .cm-number { color: #78CF8A; }
8 .cm-s-ambiance .cm-def { color: #aac6e3; }
9 .cm-s-ambiance .cm-variable { color: #ffb795; }
10 .cm-s-ambiance .cm-variable-2 { color: #eed1b3; }
11 .cm-s-ambiance .cm-variable-3 { color: #faded3; }
12 .cm-s-ambiance .cm-property { color: #eed1b3; }
13 .cm-s-ambiance .cm-operator {color: #fa8d6a;}
14 .cm-s-ambiance .cm-comment { color: #555; font-style:italic; }
15 .cm-s-ambiance .cm-string { color: #8f9d6a; }
16 .cm-s-ambiance .cm-string-2 { color: #9d937c; }
17 .cm-s-ambiance .cm-meta { color: #D2A8A1; }
18 .cm-s-ambiance .cm-error { color: #AF2018; }
19 .cm-s-ambiance .cm-qualifier { color: yellow; }
20 .cm-s-ambiance .cm-builtin { color: #9999cc; }
21 .cm-s-ambiance .cm-bracket { color: #24C2C7; }
22 .cm-s-ambiance .cm-tag { color: #fee4ff }
23 .cm-s-ambiance .cm-attribute { color: #9B859D; }
24 .cm-s-ambiance .cm-header {color: blue;}
25 .cm-s-ambiance .cm-quote { color: #24C2C7; }
26 .cm-s-ambiance .cm-hr { color: pink; }
27 .cm-s-ambiance .cm-link { color: #F4C20B; }
28 .cm-s-ambiance .cm-special { color: #FF9D00; }
29
30 .cm-s-ambiance .CodeMirror-matchingbracket { color: #0f0; }
31 .cm-s-ambiance .CodeMirror-nonmatchingbracket { color: #f22; }
32
33 .cm-s-ambiance .CodeMirror-selected {
34 background: rgba(255, 255, 255, 0.15);
35 }
36 .CodeMirror-focused .cm-s-ambiance .CodeMirror-selected {
37 background: rgba(255, 255, 255, 0.10);
38 }
39
40 /* Editor styling */
41
42 .cm-s-ambiance {
43 line-height: 1.40em;
44 font-family: Monaco, Menlo,"Andale Mono","lucida console","Courier New",monospace !important;
45 color: #E6E1DC;
46 background-color: #202020;
47 -webkit-box-shadow: inset 0 0 10px black;
48 -moz-box-shadow: inset 0 0 10px black;
49 -o-box-shadow: inset 0 0 10px black;
50 box-shadow: inset 0 0 10px black;
51 }
52
53 .cm-s-ambiance .CodeMirror-gutter {
54 background: #3D3D3D;
55 padding: 0 5px;
56 text-shadow: #333 1px 1px;
57 border-right: 1px solid #4D4D4D;
58 box-shadow: 0 10px 20px black;
59 }
60
61 .cm-s-ambiance .CodeMirror-gutter .CodeMirror-gutter-text {
62 text-shadow: 0px 1px 1px #4d4d4d;
63 color: #222;
64 }
65
66 .cm-s-ambiance .CodeMirror-lines {
67
68 }
69
70 .cm-s-ambiance .CodeMirror-lines .CodeMirror-cursor {
71 border-left: 1px solid #7991E8;
72 }
73
74 .cm-s-ambiance .activeline {
75 background: none repeat scroll 0% 0% rgba(255, 255, 255, 0.031);
76 }
77
78 .cm-s-ambiance,
79 .cm-s-ambiance .CodeMirror-gutter {
80 background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAQAAAAHUWYVAABFFUlEQVQYGbzBCeDVU/74/6fj9HIcx/FRHx9JCFmzMyGRURhLZIkUsoeRfUjS2FNDtr6WkMhO9sm+S8maJfu+Jcsg+/o/c+Z4z/t97/vezy3z+z8ekGlnYICG/o7gdk+wmSHZ1z4pJItqapjoKXWahm8NmV6eOTbWUOp6/6a/XIg6GQqmenJ2lDHyvCFZ2cBDbmtHA043VFhHwXxClWmeYAdLhV00Bd85go8VmaFCkbVkzlQENzfBDZ5gtN7HwF0KDrTwJ0dypSOzpaKCMwQHKTIreYIxlmhXTzTWkVm+LTynZhiSBT3RZQ7aGfjGEd3qyXQ1FDymqbKxpspERQN2MiRjNZlFFQXfCNFm9nM1zpAsoYjmtRTc5ajwuaXc5xrWskT97RaKzAGe5ARHhVUsDbjKklziiX5WROcJwSNCNI+9w1Jwv4Zb2r7lCMZ4oq5C0EdTx+2GzNuKpJ+iFf38JEWkHJn9DNF7mmBDITrWEg0VWL3pHU20tSZnuqWu+R3BtYa8XxV1HO7GyD32UkOpL/yDloINFTmvtId+nmAjxRw40VMwVKiwrKLE4bK5UOVntYwhOcSSXKrJHKPJedocpGjVz/ZMIbnYUPB10/eKCrs5apqpgVmWzBYWpmtKHecJPjaUuEgRDDaU0oZghCJ6zNMQ5ZhDYx05r5v2muQdM0EILtXUsaKiQX9WMEUotagQzFbUNN6NUPC2nm5pxEWGCjMc3GdJHjSU2kORLK/JGSrkfGEIjncU/CYUnOipoYemwj8tST9NsJmB7TUVXtbUtXATJVZXBMvYeTXJfobgJUPmGMP/yFaWonaa6BcFO3nqcIqCozSZoZoSr1g4zJOzuyGnxTEX3lUEJ7WcZgme8ddaWvWJo2AJR9DZU3CUIbhCSG6ybSwN6qtJVnCU2svDTP2ZInOw2cBTrqtQahtNZn9NcJ4l2NaSmSkkP1noZWnVwkLmdUPOwLZEwy2Z3S3R+4rIG9hcbpPXHFVWcQdZkn2FOta3cKWQnNRC5g1LsJah4GCzSVsKnCOY5OAFRTBekyyryeyilhFKva75r4Mc0aWanGEaThcy31s439KKxTzJYY5WTHPU1FtIHjQU3Oip4xlNzj/lBw23dYZVliQa7WAXf4shetcQfatI+jWRDBPmyNeW6A1P5kdDgyYJlba0BIM8BZu1JfrFwItyjcAMR3K0BWOIrtMEXyhyrlVEx3ui5dUBjmB/Q3CXW85R4mBD0s7B+4q5tKUjOlb9qqmhi5AZ6GFIC5HXtOobdYGlVdMVbNJ8toNTFcHxnoL+muBagcctjWnbNMuR00uI7nQESwg5q2qqrKWIfrNUmeQocY6HuyxJV02wj36w00yhpmUFenv4p6fUkZYqLyuinx2RGOjhCXYyJF84oiU00YMOOhhquNdfbOB7gU88pY4xJO8LVdp6/q2voeB4R04vIdhSE40xZObx1HGGJ/ja0LBthFInKaLPPFzuCaYaoj8JjPME8yoyxo6zlBqkiUZYgq00OYMswbWO5NGmq+xhipxHLRW29ARjNKXO0wRnear8XSg4XFPLKEPUS1GqvyLwiuBUoa7zpZ0l5xxFwWmWZC1H5h5FwU8eQ7K+g8UcVY6TMQreVQT/8uQ8Z+ALIXnSEa2pYZQneE9RZbSBNYXfWYJzW/h/4j4Dp1tYVcFIC5019Vyi4ThPqSFCzjGWaHQTBU8q6vrVwgxP9Lkm840imWKpcLCjYTtrKuwvsKSnrvHCXGkSMk9p6lhckfRpIeis+N2PiszT+mFLspyGleUhDwcLrZqmyeylxwjBcKHEapqkmyangyLZRVOijwOtCY5SsG5zL0OwlCJ4y5KznF3EUNDDrinwiyLZRzOXtlBbK5ITHFGLp8Q0R6ab6mS7enI2cFrxOyHvOCFaT1HThS1krjCwqWeurCkk+willhCC+RSZnRXBiZaC5RXRIZYKp2lyfrHwiKPKR0JDzrdU2EFgpidawlFDR6FgXUMNa+g1FY3bUQh2cLCwosRdnuQTS/S+JVrGLeWIvtQUvONJxlqSQYYKpwoN2kaocLjdVsis4Mk80ESF2YpSkzwldjHkjFCUutI/r+EHDU8oCs6yzL3PhWiEooZdFMkymlas4AcI3KmoMMNSQ3tHzjGWCrcJJdYyZC7QFGwjRL9p+MrRkAGWzIaWCn9W0F3TsK01c2ZvQw0byvxuQU0r1lM0qJO7wW0kRIMdDTtXEdzi4VIh+EoIHm0mWtAtpCixlabgn83fKTI7anJe9ST7WIK1DMGpQmYeA58ImV6ezOGOzK2Kgq01pd60cKWiUi9Lievb/0vIDPHQ05Kzt4ddPckQBQtoaurjyHnek/nKzpQLrVgKPjIkh2v4uyezpv+Xoo7fPFXaGFp1vaLKxQ4uUpQQS5VuQs7BCq4xRJv7fwpVvvFEB3j+620haOuocqMhWd6TTPAEx+mdFNGHdranFe95WrWmIvlY4F1Dle2ECgc6cto7SryuqGGGha0tFQ5V53migUKmg6XKAo4qS3mik+0OZpAhOLeZKicacgaYcyx5hypYQE02ZA4xi/pNhOQxR4klNKyqacj+mpxnLTnnGSo85++3ZCZq6lrZkXlGEX3o+C9FieccJbZWVFjC0Yo1FZnJhoYMFoI1hEZ9r6hwg75HwzBNhbZCdJEfJwTPGzJvaKImw1yYX1HDAmpXR+ZJQ/SmgqMNVQb5vgamGwLtt7VwvP7Qk1xpiM5x5Cyv93E06MZmgs0Nya2azIKOYKCGBQQW97RmhKNKF02JZqHEJ4o58qp7X5EcZmc56trXEqzjCBZ1MFGR87Ql2tSTs6CGxS05PTzRQorkbw7aKoKXFDXsYW42VJih/q+FP2BdTzDTwVqOYB13liM50vG7wy28qagyuIXMeQI/Oqq8bcn5wJI50xH00CRntyfpL1T4hydYpoXgNiFzoIUTDZnLNRzh4TBHwbYGDvZkxmlyJloyr6tRihpeUG94GnKtIznREF0tzJG/OOr73JBcrSh1k6WuTprgLU+mnSGnv6Zge0NNz+kTDdH8nuAuTdJDCNb21LCiIuqlYbqGzT3RAoZofQfjFazkqeNWdYaGvYTM001EW2oKPvVk1ldUGSgUtHFwjKM1h9jnFcmy5lChoLNaQMGGDsYbKixlaMBmmsx1QjCfflwTfO/gckW0ruZ3jugKR3R5W9hGUWqCgxuFgsuaCHorotGKzGaeZB9DMsaTnKCpMtwTvOzhYk0rdrArKCqcaWmVk1+F372ur1YkKxgatI8Qfe1gIX9wE9FgS8ESmuABIXnRUbCapcKe+nO7slClSZFzpV/LkLncEb1qiO42fS3R855Su2mCLh62t1SYZZYVmKwIHjREF2uihTzB20JOkz7dkxzYQnK0UOU494wh+VWRc6Un2kpTaVgLDFEkJ/uhzRcI0YKGgpGWOlocBU/a4fKoJ/pEaNV6jip3+Es9VXY078rGnmAdf7t9ylPXS34RBSuYPs1UecZTU78WanhBCHpZ5sAoTz0LGZKjPf9TRypqWEiTvOFglL1fCEY3wY/++rbk7C8bWebA6p6om6PgOL2kp44TFJlVNBXae2rqqdZztOJpT87GQsE9jqCPIe9VReZuQ/CIgacsyZdCpIScSYqcZk8r+nsyCzhyfhOqHGOIvrLknC8wTpFcaYiGC/RU1NRbUeUpocQOnkRpGOrIOcNRx+1uA0UrzhSSt+VyS3SJpnFWkzNDqOFGIWcfR86DnmARTQ1HKIL33ExPiemeOhYSSjzlSUZZuE4TveoJLnBUOFof6KiysCbnAEcZgcUNTDOwkqWu3RWtmGpZwlHhJENdZ3miGz0lJlsKnjbwqSHQjpxnFDlTLLwqJPMZMjd7KrzkSG7VsxXBZE+F8YZkb01Oe00yyRK9psh5SYh29ySPKBo2ylNht7ZkZnsKenjKNJu9PNEyZpaCHv4Kt6RQsLvAVp7M9kIimmCUwGeWqLMmGuIotYMmWNpSahkhZw9FqZsVnKJhsjAHvtHMsTM9fCI06Dx/u3vfUXCqfsKRc4oFY2jMsoo/7DJDwZ1CsIKnJu+J9ldkpmiCxQx1rWjI+T9FwcWWzOuaYH0Hj7klNRVWEQpmaqosakiGNTFHdjS/qnUdmf0NJW5xsL0HhimCCZZSRzmSPTXJQ4aaztAwtZnoabebJ+htCaZ7Cm535ByoqXKbX1WRc4Eh2MkRXWzImVc96Cj4VdOKVxR84VdQsIUM8Psoou2byVHyZFuq7O8otbSQ2UAoeEWTudATLGSpZzVLlXVkPU2Jc+27lsw2jmg5T5VhbeE3BT083K9WsTTkFU/Osi0rC5lRlpwRHUiesNS0sOvmqGML1aRbPAxTJD9ZKtxuob+hhl8cwYGWpJ8nub7t5p6coYbMovZ1BTdaKn1jYD6h4GFDNFyT/Kqe1XCXphXHOKLZmuRSRdBPEfVUXQzJm5YGPGGJdvAEr7hHNdGZnuBvrpciGmopOLf5N0uVMy0FfYToJk90uUCbJupaVpO53UJXR2bVpoU00V2KOo4zMFrBd0Jtz2pa0clT5Q5L8IpQ177mWQejPMEJhuQjS10ref6HHjdEhy1P1EYR7GtO0uSsKJQYLiTnG1rVScj5lyazpqWGl5uBbRWl7m6ixGOOnEsMJR7z8J0n6KMnCdxhiNYQCoZ6CmYLnO8omC3MkW3bktlPmEt/VQQHejL3+dOE5FlPdK/Mq8hZxxJtLyRrepLThYKbLZxkSb5W52vYxNOaOxUF0yxMUPwBTYqCzy01XayYK0sJyWBLqX0MwU5CzoymRzV0EjjeUeLgDpTo6ij42ZAzvD01dHUUTPLU96MdLbBME8nFBn7zJCMtJcZokn8YoqU0FS5WFKyniHobguMcmW8N0XkWZjkyN3hqOMtS08r+/xTBwpZSZ3qiVRX8SzMHHjfUNFjgHEPmY9PL3ykEzxkSre/1ZD6z/NuznuB0RcE1TWTm9zRgfUWVJiG6yrzgmWPXC8EAR4Wxhlad0ZbgQyEz3pG5RVEwwDJH2mgKpjcTiCOzn1lfUWANFbZ2BA8balnEweJC9J0iuaeZoI+ippFCztEKVvckR2iice1JvhVytrQwUAZpgsubCPaU7xUe9vWnaOpaSBEspalykhC9bUlOMpT42ZHca6hyrqKmw/wMR8H5ZmdFoBVJb03O4UL0tSNnvIeRmkrLWqrs78gcrEn2tpcboh0UPOW3UUR9PMk4T4nnNKWmCjlrefhCwxRNztfmIQVdDElvS4m1/WuOujoZCs5XVOjtKPGokJzsYCtFYoWonSPT21DheU/wWhM19FcElwqNGOsp9Q8N/cwXaiND1MmeL1Q5XROtYYgGeFq1aTMsoMmcrKjQrOFQTQ1fmBYhmW6o8Jkjc7iDJRTBIo5kgJD5yMEYA3srCg7VFKwiVJkmRCc5ohGOKhsYMn/XBLdo5taZjlb9YAlGWRimqbCsoY7HFAXLa5I1HPRxMMsQDHFkWtRNniqT9UEeNjcE7RUlrCJ4R2CSJuqlKHWvJXjAUNcITYkenuBRB84TbeepcqTj3zZyFJzgYQdHnqfgI0ddUwS6GqWpsKWhjq9cV0vBAEMN2znq+EBfIWT+pClYw5xsTlJU6GeIBsjGmmANTzJZiIYpgrM0Oa8ZMjd7NP87jxhqGOhJlnQtjuQpB+8aEE00wZFznSJPyHxgH3HkPOsJFvYk8zqCHzTs1BYOa4J3PFU+UVRZxlHDM4YavlNUuMoRveiZA2d7grMNc2g+RbSCEKzmgYsUmWmazFJyoiOZ4KnyhKOGRzWJa0+moyV4TVHDzn51Awtqaphfk/lRQ08FX1iiqxTB/kLwd0VynKfEvI6cd4XMV5bMhZ7gZUWVzYQ6Nm2BYzxJbw3bGthEUUMfgbGeorae6DxHtJoZ6alhZ0+ytiVoK1R4z5PTrOECT/SugseEOlb1MMNR4VRNcJy+V1Hg9ONClSZFZjdHlc6W6FBLdJja2MC5hhpu0DBYEY1TFGwiFAxRRCsYkiM9JRb0JNMVkW6CZYT/2EiTGWmo8k+h4FhDNE7BvppoTSFnmCV5xZKzvcCdDo7VVPnIU+I+Rc68juApC90MwcFCsJ5hDqxgScYKreruyQwTqrzoqDCmhWi4IbhB0Yrt3RGa6GfDv52rKXWhh28dyZaWUvcZeMTBaZoSGyiCtRU5J8iviioHaErs7Jkj61syVzTTgOcUOQ8buFBTYWdL5g3T4qlpe0+wvD63heAXRfCCIed9RbCsp2CiI7raUOYOTU13N8PNHvpaGvayo4a3LLT1lDrVEPT2zLUlheB1R+ZTRfKWJ+dcocLJfi11vyJ51lLqJ0WD7tRwryezjiV5W28uJO9qykzX8JDe2lHl/9oyBwa2UMfOngpXCixvKdXTk3wrsKmiVYdZIqsoWEERjbcUNDuiaQomGoIbFdEHmsyWnuR+IeriKDVLnlawlyNHKwKlSU631PKep8J4Q+ayjkSLKYLhalNHlYvttb6fHm0p6OApsZ4l2VfdqZkjuysy6ysKLlckf1KUutCTs39bmCgEyyoasIWlVaMF7mgmWtBT8Kol5xpH9IGllo8cJdopcvZ2sImlDmMIbtDk3KIpeNiS08lQw11NFPTwVFlPP6pJ2gvRfI7gQUfmNAtf6Gs0wQxDsKGlVBdF8rCa3jzdwMaGHOsItrZk7hAyOzpK9VS06j5F49b0VNGOOfKs3lDToMsMBe9ZWtHFEgxTJLs7qrygKZjUnmCYoeAqeU6jqWuLJup4WghOdvCYJnrSkSzoyRkm5M2StQwVltPkfCAk58tET/CSg+8MUecmotMEnhBKfWBIZsg2ihruMJQaoIm+tkTLKEqspMh00w95gvFCQRtDwTT1gVDDSEVdlwqZfxoQRbK0g+tbiBZxzKlpnpypejdDwTaeOvorMk/IJE10h9CqRe28hhLbe0pMsdSwv4ZbhKivo2BjDWfL8UKJgeavwlwb5KlwhyE4u4XkGE2ytZCznKLCDZZq42VzT8HLCrpruFbIfOIINmh/qCdZ1ZBc65kLHR1Bkyf5zn6pN3SvGKIlFNGplhrO9QSXanLOMQTLCa0YJCRrCZm/CZmrLTm7WzCK4GJDiWUdFeYx1LCFg3NMd0XmCuF3Y5rITLDUsYS9zoHVzwnJoYpSTQoObyEzr4cFBNqYTopoaU/wkyLZ2lPhX/5Y95ulxGTV7KjhWrOZgl8MyUUafjYraNjNU1N3IWcjT5WzWqjwtoarHSUObGYO3GCJZpsBlnJGPd6ZYLyl1GdCA2625IwwJDP8GUKymbzuyPlZlvTUsaUh5zFDhRWFzPKKZLAlWdcQbObgF9tOqOsmB1dqcqYJmWstFbZRRI9poolmqiLnU0POvxScpah2iSL5UJNzgScY5+AuIbpO0YD3NCW+dLMszFSdFCWGqG6eVq2uYVNDdICGD6W7EPRWZEY5gpsE9rUkS3mijzzJnm6UpUFXG1hCUeVoS5WfNcFpblELL2qqrCvMvRfd45oalvKU2tiQ6ePJOVMRXase9iTtLJztPxJKLWpo2CRDcJwn2sWSLKIO1WQWNTCvpVUvOZhgSC40JD0dOctaSqzkCRbXsKlb11Oip6PCJ0IwSJM31j3akRxlP7Rwn6aGaUL0qiLnJkvB3xWZ2+Q1TfCwpQH3G0o92UzmX4o/oJNQMMSQc547wVHhdk+VCw01DFYEnTxzZKAm74QmeNNR1w6WzEhNK15VJzuCdxQ53dRUDws5KvwgBMOEgpcVNe0hZI6RXT1Jd0cyj5nsaEAHgVmGaJIlWdsc5Ui2ElrRR6jrRAttNMEAIWrTDFubkZaok7/AkzfIwfuWVq0jHzuCK4QabtLUMVPB3kJ0oyHTSVFlqMALilJf2Rf8k5aaHtMfayocLBS8L89oKoxpJvnAkDPa0qp5DAUTHKWmCcnthlou8iCKaFFLHWcINd1nyIwXqrSxMNmSs6KmoL2QrKuWtlQ5V0120xQ5vRyZS1rgFkWwhiOwiuQbR0OOVhQM9iS3tiXp4RawRPMp5tDletOOBL95MpM01dZTBM9pkn5qF010rIeHFcFZhmSGpYpTsI6nwhqe5C9ynhlpp5ophuRb6WcJFldkVnVEwwxVfrVkvnWUuNLCg5bgboFHPDlDPDmnK7hUrWiIbjadDclujlZcaokOFup4Ri1kacV6jmrrK1hN9bGwpKEBQ4Q6DvIUXOmo6U5LqQM6EPyiKNjVkPnJkDPNEaxhiFay5ExW1NXVUGqcpYYdPcGiCq7z/TSlbhL4pplWXKd7NZO5QQFrefhRQW/NHOsqcIglc4UhWklR8K0QzbAw08CBDnpbgqXdeD/QUsM4RZXDFBW6WJKe/mFPdH0LtBgiq57wFLzlyQzz82qYx5D5WJP5yVJDW01BfyHnS6HKO/reZqId1WGa4Hkh2kWodJ8i6KoIPlAj2hPt76CzXsVR6koPRzWTfKqIentatYpQw2me4AA3y1Kind3SwoOKZDcFXTwl9tWU6mfgRk9d71sKtlNwrjnYw5tC5n5LdKiGry3JKNlHEd3oaMCFHrazBPMp/uNJ+V7IudcSbeOIdjUEdwl0VHCOZo5t6YluEuaC9mQeMgSfOyKnYGFHcIeQ84yQWbuJYJpZw5CzglDH7gKnWqqM9ZTaXcN0TeYhR84eQtJT76JJ1lREe7WnnvsMmRc9FQ7SBBM9mV3lCUdmHk/S2RAMt0QjFNFqQpWjDPQ01DXWUdDBkXziKPjGEP3VP+zIWU2t7im41FOloyWzn/L6dkUy3VLDaZ6appgDLHPjJEsyvJngWEPUyVBiAaHCTEXwrLvSEbV1e1gKJniicWorC1MUrVjB3uDhJE/wgSOzk1DXpk0k73qCM8xw2UvD5kJmDUfOomqMpWCkJRlvKXGmoeBm18USjVIk04SClxTB6YrgLAPLWYK9HLUt5cmc0vYES8GnTeRc6skZbQkWdxRsIcyBRzx1DbTk9FbU0caTPOgJHhJKnOGIVhQqvKmo0llRw9sabrZkDtdg3PqaKi9oatjY8B+G371paMg6+mZFNNtQ04mWBq3rYLOmtWWQp8KJnpy9DdFensyjdqZ+yY40VJlH8wcdLzC8PZnvHMFUTZUrDTkLyQaGus5X5LzpYAf3i+e/ZlhqGqWhh6Ou6xTR9Z6oi5AZZtp7Mj2EEm8oSpxiYZCHU/1fbGdNNNRRoZMhmilEb2gqHOEJDtXkHK/JnG6IrvbPCwV3NhONVdS1thBMs1T4QOBcTWa2IzhMk2nW5Kyn9tXUtpv9RsG2msxk+ZsQzRQacJncpgke0+T8y5Fzj8BiGo7XlJjaTIlpQs7KFjpqGnKuoyEPeIKnFMkZHvopgh81ySxNFWvJWcKRs70j2FOT012IllEEO1n4pD1513Yg2ssQPOThOkvyrqHUdEXOSEsihmBbTbKX1kLBPWqWkLOqJbjB3GBIZmoa8qWl4CG/iZ7oiA72ZL7TJNeZUY7kFQftDcHHluBzRbCegzMtrRjVQpX2lgoPKKLJAkcbMl01XK2p7yhL8pCBbQ3BN2avJgKvttcrWDK3CiUOVxQ8ZP+pqXKyIxnmBymCg5vJjNfkPK4+c8cIfK8ocVt7kmfd/I5SR1hKvCzUtb+lhgc00ZaO6CyhIQP1Uv4yIZjload72PXX0OIJvnFU+0Zf6MhsJwTfW0r0UwQfW4LNLZl5HK261JCZ4qnBaAreVAS3WrjV0LBnNDUNNDToCEeFfwgcb4gOEqLRhirWkexrCEYKVV711DLYEE1XBEsp5tpTGjorkomKYF9FDXv7fR3BGwbettSxnyL53MBPjsxDZjMh+VUW9NRxq1DhVk+FSxQcaGjV9Pawv6eGByw5qzoy7xk4RsOShqjJwWKe/1pEEfzkobeD/dQJmpqedcyBTy2sr4nGNRH0c0SPWTLrqAc0OQcb/gemKgqucQT7ySWKCn2EUotoCvpZct7RO2sy/QW0IWcXd7pQRQyZVwT2USRO87uhjioTLKV2brpMUcMQRbKH/N2T+UlTpaMls6cmc6CCNy3JdYYSUzzJQ4oSD3oKLncULOiJvjBEC2oqnCJkJluCYy2ZQ5so9YYlZ1VLlQU1mXEW1jZERwj/MUSRc24TdexlqLKfQBtDTScJUV8FszXBEY5ktpD5Ur9hYB4Nb1iikw3JoYpkKX+RodRKFt53MMuRnKSpY31PwYaGaILh3wxJGz9TkTPEETxoCWZrgvOlmyMzxFEwVJE5xZKzvyJ4WxEc16Gd4Xe3Weq4XH2jKRikqOkGQ87hQnC7wBmGYLAnesX3M+S87eFATauuN+Qcrh7xIxXJbUIdMw3JGE3ylCWzrieaqCn4zhGM19TQ3z1oH1AX+pWEqIc7wNGAkULBo/ZxRaV9NNyh4Br3rCHZzbzmSfawBL0dNRwpW1kK9mxPXR9povcdrGSZK9c2k0xwFGzjuniCtRSZCZ6ccZ7gaktmgAOtKbG/JnOkJrjcQTdFMsxRQ2cLY3WTIrlCw1eWKn8R6pvt4GFDso3QoL4a3nLk3G6JrtME3dSenpx7PNFTmga0EaJTLQ061sEeQoWXhSo9LTXsaSjoJQRXeZLtDclbCrYzfzHHeaKjHCVOUkQHO3JeEepr56mhiyaYYKjjNU+Fed1wS5VlhWSqI/hYUdDOkaxiKehoyOnrCV5yBHtbWFqTHCCwtpDcYolesVR5yUzTZBb3RNMd0d6WP+SvhuBmRcGxnuQzT95IC285cr41cLGQ6aJJhmi4TMGempxeimBRQw1tFKV+8jd6KuzoSTqqDxzRtpZkurvKEHxlqXKRIjjfUNNXQsNOsRScoWFLT+YeRZVD3GRN0MdQcKqQjHDMrdGGVu3iYJpQx3WGUvfbmxwFfR20WBq0oYY7LMFhhgYtr8jpaEnaOzjawWWaTP8mMr0t/EPDPoqcnxTBI5o58L7uoWnMrpoqPwgVrlAUWE+V+TQl9rawoyP6QGAlQw2TPRX+YSkxyBC8Z6jhHkXBgQL7WII3DVFnRfCrBfxewv9D6xsyjys4VkhWb9pUU627JllV0YDNHMku/ldNMMXDEo4aFnAkk4U6frNEU4XgZUPmEKHUl44KrzmYamjAbh0JFvGnaTLPu1s9jPCwjFpYiN7z1DTOk/nc07CfDFzmCf7i+bfNHXhDtLeBXzTBT5rkMvWOIxpl4EMh2LGJBu2syDnAEx2naEhHDWMMzPZEhygyS1mS5RTJr5ZkoKbEUoYqr2kqdDUE8ztK7OaIntJkFrIECwv8LJTaVx5XJE86go8dFeZ3FN3rjabCAYpoYEeC9zzJVULBbmZhDyd7ko09ydpNZ3nm2Kee4FPPXHnYEF1nqOFEC08LUVcDvYXkJHW8gTaKCk9YGOeIJhqiE4ToPEepdp7IWFjdwnWaufGMwJJCMtUTTBBK9BGCOy2tGGrJTHIwyEOzp6aPzNMOtlZkDvcEWpP5SVNhfkvDxhmSazTJXYrM9U1E0xwFVwqZQwzJxw6+kGGGUj2FglGGmnb1/G51udRSMNlTw6GGnCcUwVcOpmsqTHa06o72sw1RL02p9z0VbnMLOaIX3QKaYKSCFQzBKEUNHTSc48k53RH9wxGMtpQa5KjjW0W0n6XCCCG4yxNNdhQ4R4l1Ff+2sSd6UFHiIEOyqqFgT01mEUMD+joy75jPhOA+oVVLm309FR4yVOlp4RhLiScNmSmaYF5Pw0STrOIoWMSR2UkRXOMp+M4SHW8o8Zoi6OZgjKOaFar8zZDzkWzvKOjkKBjmCXby8JahhjXULY4KlzgKLvAwxVGhvyd4zxB1d9T0piazmKLCVZY5sKiD0y2ZSYrkUEPUbIk+dlQ4SJHTR50k1DPaUWIdTZW9NJwnJMOECgd7ou/MnppMJ02O1VT4Wsh85MnZzcFTngpXGKo84qmwgKbCL/orR/SzJ2crA+t6Mp94KvxJUeIbT3CQu1uIdlQEOzlKfS3UMcrTiFmOuroocrZrT2AcmamOKg8YomeEKm/rlT2sociMaybaUlFhuqHCM2qIJ+rg4EcDFymiDSxzaHdPcpE62pD5kyM5SBMoA1PaUtfIthS85ig1VPiPPYXgYEMNk4Qq7TXBgo7oT57gPUdwgCHzhIVFPFU6OYJzHAX9m5oNrVjeE61miDrqQ4VSa1oiURTsKHC0IfjNwU2WzK6eqK8jWln4g15TVBnqmDteCJ501PGAocJhhqjZdtBEB6lnhLreFJKxmlKbeGrqLiSThVIbCdGzloasa6lpMQXHCME2boLpJgT7yWaemu6wBONbqGNVRS0PKIL7LckbjmQtR7K8I5qtqel+T/ChJTNIKLjdUMNIRyvOEko9YYl2cwQveBikCNawJKcLBbc7+JM92mysNvd/Fqp8a0k6CNEe7cnZrxlW0wQXaXjaktnRwNOGZKYiONwS7a1JVheq3WgJHlQUGKHKmp4KAxXR/ULURcNgoa4zhKSLpZR3kxRRb0NmD0OFn+UCS7CzI1nbP6+o4x47QZE5xRCt3ZagnYcvmpYQktXdk5YKXTzBC57kKEe0VVuiSYqapssMS3C9p2CKkHOg8B8Pa8p5atrIw3qezIWanMGa5HRDNF6RM9wcacl0N+Q8Z8hsIkSnaIIdHRUOEebAPy1zbCkhM062FCJtif7PU+UtoVXzWKqM1PxXO8cfdruhFQ/a6x3JKYagvVDhQEtNiyiiSQ7OsuRsZUku0CRNDs4Sog6KKjsZgk2bYJqijgsEenoKeniinRXBn/U3lgpPdyDZynQx8IiioMnCep5Ky8mjGs6Wty0l1hUQTcNWswS3WRp2kCNZwJG8omG8JphPUaFbC8lEfabwP7VtM9yoaNCAjpR41VNhrD9LkbN722v0CoZMByFzhaW+MyzRYEWFDQwN2M4/JiT76PuljT3VU/A36eaIThb+R9oZGOAJ9tewkgGvqOMNRWYjT/Cwu99Q8LqDE4TgbLWxJ1jaDDAERsFOFrobgjUsBScaguXU8kKm2RL19tRypSHnHNlHiIZqgufs4opgQdVdwxBNNFBR6kVFqb8ogimOzB6a6HTzrlDHEpYaxjiiA4TMQobkDg2vejjfwJGWmnbVFAw3H3hq2NyQfG7hz4aC+w3BbwbesG0swYayvpAs6++Ri1Vfzx93mFChvyN5xVHTS+0p9aqCAxyZ6ZacZyw5+7uuQkFPR9DDk9NOiE7X1PCYJVjVUqq7JlrHwWALF5nfHNGjApdpqgzx5OwilDhCiDYTgnc9waGW4BdLNNUQvOtpzDOWHDH8D7TR/A/85KljEQu3NREc4Pl/6B1Hhc8Umb5CsKMmGC9EPcxoT2amwHNCmeOEnOPbklnMkbOgIvO5UMOpQrS9UGVdt6iH/fURjhI/WOpaW9OKLYRod6HCUEdOX000wpDZQ6hwg6LgZfOqo1RfT/CrJzjekXOGhpc1VW71ZLbXyyp+93ILbC1kPtIEYx0FIx1VDrLoVzXRKRYWk809yYlC9ImcrinxtabKnzRJk3lAU1OLEN1j2zrYzr2myHRXJFf4h4QKT1qSTzTB5+ZNTzTRkAxX8FcLV2uS8eoQQ2aAkFzvCM72sJIcJET3WPjRk5wi32uSS9rfZajpWEvj9hW42F4o5NytSXYy8IKHay10VYdrcl4SkqscrXpMwyGOgtkajheSxdQqmpxP1L3t4R5PqasFnrQEjytq6qgp9Y09Qx9o4S1FzhUCn1kyHSzBWLemoSGvOqLNhZyBjmCaAUYpMgt4Ck7wBBMMwWKWgjsUwTaGVsxWC1mYoKiyqqeGKYqonSIRQ3KIkHO0pmAxTdBHkbOvfllfr+AA+7gnc50huVKYK393FOyg7rbPO/izI7hE4CnHHHnJ0ogNPRUGeUpsrZZTBJcrovUcJe51BPsr6GkJdhCCsZ6aTtMEb2pqWkqeVtDXE/QVggsU/Nl86d9RMF3DxvZTA58agu810RWawCiSzzXBeU3MMW9oyJUedvNEvQyNu1f10BSMddR1vaLCYpYa/mGocLSiYDcLbQz8aMn5iyF4xBNMs1P0QEOV7o5gaWGuzSeLue4tt3ro7y4Tgm4G/mopdZgl6q0o6KzJWE3mMksNr3r+a6CbT8g5wZNzT9O7fi/zpaOmnz3BRoqos+tv9zMbdpxsqDBOEewtJLt7cg5wtKKbvldpSzRRCD43VFheCI7yZLppggMVBS/KMAdHODJvOwq2NQSbKKKPLdFWQs7Fqo+mpl01JXYRgq8dnGLhTiFzqmWsUMdpllZdbKlyvSdYxhI9YghOtxR8LgSLWHK62mGGVoxzBE8LNWzqH9CUesQzFy5RQzTc56mhi6fgXEWwpKfE5Z7M05ZgZUPmo6auiv8YKzDYwWBLMErIbKHJvOwIrvEdhOBcQ9JdU1NHQ7CXn2XIDFBKU2WAgcX9UAUzDXWd5alwuyJ41Z9rjKLCL4aCp4WarhPm2rH+SaHUYE001JDZ2ZAzXPjdMpZWvC9wmqIB2lLhQ01D5jO06hghWMndbM7yRJMsoCj1vYbnFQVrW9jak3OlEJ3s/96+p33dEPRV5GxiqaGjIthUU6FFEZyqCa5qJrpBdzSw95IUnOPIrCUUjRZQFrbw5PR0R1qiYx3cb6nrWUMrBmmiBQxVHtTew5ICP/ip6g4hed/Akob/32wvBHsIOX83cI8hGeNeNPCIkPmXe8fPKx84OMSRM1MTdXSwjCZ4S30jVGhvqTRak/OVhgGazHuOCud5onEO1lJr6ecVyaOK6H7zqlBlIaHE0oroCgfvGJIdPcmfLNGLjpz7hZwZQpUbFME0A1cIJa7VNORkgfsMBatbKgwwJM9bSvQXeNOvbIjelg6WWvo5kvbKaJJNHexkKNHL9xRyFlH8Ti2riB5wVPhUk7nGkJnoCe428LR/wRGdYIlmWebCyxou1rCk4g/ShugBDX0V0ZQWkh0dOVsagkM0yV6OoLd5ye+pRlsCr0n+KiQrGuq5yJDzrTAXHtLUMduTDBVKrSm3eHL+6ijxhFDX9Z5gVU/wliHYTMiMFpKLNMEywu80wd3meoFmt6VbRMPenhrOc6DVe4pgXU8DnnHakLOIIrlF4FZPIw6R+zxBP0dyq6OOZ4Q5sLKCcz084ok+VsMMyQhNZmmBgX5xIXOEJTmi7VsGTvMTNdHHhpzdbE8Du2oKxgvBqQKdDDnTFOylCFaxR1syz2iqrOI/FEpNc3C6f11/7+ASS6l2inq2ciTrCCzgyemrCL5SVPjQkdPZUmGy2c9Sw9FtR1sS30RmsKPCS4rkIC/2U0MduwucYolGaPjKEyhzmiPYXagyWbYz8LWBDdzRimAXzxx4z8K9hpzlhLq+NiQ97HuKorMUfK/OVvC2JfiHUPCQI/q7J2gjK+tTDNxkCc4TMssqCs4TGtLVwQihyoAWgj9bosU80XGW6Ac9TJGziaUh5+hnFcHOnlaM1iRn29NaqGENTTTSUHCH2tWTeV0osUhH6psuVLjRUmGWhm6OZEshGeNowABHcJ2Bpy2ZszRcKkRXd2QuKVEeXnbfaEq825FguqfgfE2whlChSRMdron+LATTPQ2Z369t4B9C5gs/ylzv+CMmepIDPclFQl13W0rspPd1JOcbghGOEutqCv5qacURQl3dDKyvyJlqKXGPgcM9FfawJAMVmdcspcYKOZc4GjDYkFlK05olNMHyHn4zFNykyOxt99RkHlfwmiHo60l2EKI+mhreEKp080Tbug08BVPcgoqC5zWt+NLDTZ7oNSF51N1qie7Va3uCCwyZbkINf/NED6jzOsBdZjFN8oqG3wxVunqCSYYKf3EdhJyf9YWGf7tRU2oH3VHgPr1fe5J9hOgHd7xQ0y7qBwXr23aGErP0cm64JVjZwsOGqL+mhNgZmhJLW2oY4UhedsyBgzrCKrq7BmcpNVhR6jBPq64Vgi+kn6XE68pp8J5/+0wRHGOpsKenQn9DZntPzjRLZpDAdD2fnSgkG9tmIXnUwQ6WVighs7Yi2MxQ0N3CqYaCXkJ0oyOztMDJjmSSpcpvlrk0RMMOjmArQ04PRV1DO1FwhCVaUVPpKUM03JK5SxPsIWRu8/CGHi8UHChiqGFDTbSRJWeYUDDcH6vJWUxR4k1FXbMUwV6e4AJFXS8oMqsZKqzvYQ9DDQdZckY4aGsIhtlubbd2r3j4QBMoTamdPZk7O/Bf62lacZwneNjQoGcdVU7zJOd7ghsUHOkosagic6cnWc8+4gg285R6zZP5s1/LUbCKIznTwK36PkdwlOrl4U1LwfdCCa+IrvFkmgw1PCAUXKWo0sURXWcI2muKJlgyFzhynCY4RBOsqCjoI1R5zREco0n2Vt09BQtYSizgKNHfUmUrQ5UOCh51BFcLmY7umhYqXKQomOop8bUnWNNQcIiBcYaC6xzMNOS8JQQfeqKBmmglB+97ok/lfk3ygaHSyZaCRTzRxQo6GzLfa2jWBPepw+UmT7SQEJyiyRkhBLMVOfcoMjcK0eZChfUNzFAUzCsEN5vP/X1uP/n/aoMX+K+nw/Hjr/9xOo7j7Pju61tLcgvJpTWXNbfN5jLpi6VfCOviTktKlFusQixdEKWmEBUKNaIpjZRSSOXSgzaaKLdabrm1/9nZ+/f+vd/vz/v9+Xy+zZ7PRorYoZqyLrCwQdEAixxVOEXNNnjX2nUSRlkqGmWowk8lxR50JPy9Bo6qJXaXwNvREBvnThPEPrewryLhcAnj5WE15Fqi8W7R1sAuEu86S4ENikItFN4xkv9Af4nXSnUVcLiA9xzesFpivRRVeFKtsMRaKBhuSbjOELnAUtlSQUpXgdfB4Z1oSbnFEetbQ0IrAe+Y+pqnDcEJFj6S8LDZzZHwY4e3XONNlARraomNEt2bkvGsosA3ioyHm+6jCMbI59wqt4eeara28IzEmyPgoRaUOEDhTVdEJhmCoTWfC0p8aNkCp0oYqih2iqGi4yXeMkOsn4LdLLnmKfh/YogjNsPebeFGR4m9BJHLzB61XQ3BtpISfS2FugsK9FAtLWX1dCRcrCnUp44CNzuCowUZmxSRgYaE6Za0W2u/E7CVXCiI/UOR8aAm1+OSyE3mOUcwyc1zBBeoX1kiKy0Zfxck1Gsyulti11i83QTBF5Kg3pDQThFMVHiPSlK+0cSedng/VaS8bOZbtsBcTcZAR8JP5KeqQ1OYKAi20njdNNRpgnsU//K+JnaXJaGTomr7aYIphoRn9aeShJWKEq9LcozSF7QleEfDI5LYm5bgVkFkRwVDBCVu0DDIkGupo8TZBq+/pMQURYErJQmPKGKjNDkWOLx7Jd5QizdUweIaKrlP7SwJDhZvONjLkOsBBX9UpGxnydhXkfBLQ8IxgojQbLFnJf81JytSljclYYyEFyx0kVBvKWOFJmONpshGAcsduQY5giVNCV51eOdJYo/pLhbvM0uDHSevNKRcrKZIqnCtJeEsO95RoqcgGK4ocZcho1tTYtcZvH41pNQ7vA0WrhIfOSraIIntIAi+NXWCErdbkvrWwjRLrt0NKUdL6KSOscTOdMSOUtBHwL6OLA0vNSdynaWQEnCpIvKaIrJJEbvHkmuNhn6OjM8VkSGSqn1uYJCGHnq9I3aLhNME3t6GjIkO7xrNFumpyTNX/NrwX7CrIRiqqWijI9JO4d1iieykyfiposQIQ8YjjsjlBh6oHWbwRjgYJQn2NgSnNycmJAk3NiXhx44Sxykihxm8ybUwT1OVKySc7vi3OXVkdBJ4AyXBeksDXG0IhgtYY0lY5ahCD0ehborIk5aUWRJviMA7Xt5kyRjonrXENkm8yYqgs8VzgrJmClK20uMM3jRJ0FiQICQF9hdETlLQWRIb5ki6WDfWRPobvO6a4GP5mcOrNzDFELtTkONLh9dXE8xypEg7z8A9jkhrQ6Fhjlg/QVktJXxt4WXzT/03Q8IaQWSqIuEvloQ2mqC9Jfi7wRul4RX3pSPlzpoVlmCtI2jvKHCFhjcM3sN6lqF6HxnKelLjXWbwrpR4xzuCrTUZx2qq9oAh8p6ixCUGr78g8oyjRAtB5CZFwi80VerVpI0h+IeBxa6Zg6kWvpDHaioYYuEsRbDC3eOmC2JvGYLeioxGknL2UATNJN6hmtj1DlpLvDVmocYbrGCVJKOrg4X6DgddLA203BKMFngdJJFtFd7vJLm6KEpc5yjQrkk7M80SGe34X24nSex1Ra5Omgb71JKyg8SrU3i/kARKwWpH0kOGhKkObyfd0ZGjvyXlAkVZ4xRbYJ2irFMkFY1SwyWxr2oo4zlNiV+7zmaweFpT4kR3kaDAFW6xpSqzJay05FtYR4HmZhc9UxKbbfF2V8RG1MBmSaE+kmC6JnaRXK9gsiXhJHl/U0qM0WTcbyhwkYIvFGwjSbjfwhiJt8ZSQU+Bd5+marPMOkVkD0muxYLIfEuhh60x/J92itguihJSEMySVPQnTewnEm+620rTQEMsOfo4/kP/0ARvWjitlpSX7GxBgcMEsd3EEeYWvdytd+Saawi6aCIj1CkGb6Aj9rwhx16Cf3vAwFy5pyLhVonXzy51FDpdEblbkdJbUcEPDEFzQ8qNmhzzLTmmKWKbFCXeEuRabp6rxbvAtLF442QjQ+wEA9eL1xSR7Q0JXzlSHjJ4exq89yR0laScJ/FW6z4a73pFMEfDiRZvuvijIt86RaSFOl01riV2mD1UEvxGk/Geg5aWwGki1zgKPG9J2U8PEg8qYvMsZeytiTRXBMslCU8JSlxi8EabjwUldlDNLfzTUmCgxWsjqWCOHavYAqsknKFIO0yQ61VL5AVFxk6WhEaCAkdJgt9aSkzXlKNX2jEa79waYuc7gq0N3GDJGCBhoiTXUEPsdknCUE1CK0fwsiaylSF2uiDyO4XX3pFhNd7R4itFGc0k/ElBZwWvq+GC6szVeEoS/MZ+qylwpKNKv9Z469UOjqCjwlusicyTxG6VpNxcQ8IncoR4RhLbR+NdpGGmJWOcIzJGUuKPGpQg8rrG21dOMqQssJQ4RxH5jaUqnZuQ0F4Q+cjxLwPtpZbIAk3QTJHQWBE5S1BokoVtDd6lhqr9UpHSUxMcIYl9pojsb8h4SBOsMQcqvOWC2E8EVehqiJ1hrrAEbQxeK0NGZ0Gkq+guSRgniM23bIHVkqwx4hiHd7smaOyglyIyQuM978j4VS08J/A2G1KeMBRo4fBaSNhKUEZfQewVQ/C1I+MgfbEleEzCUw7mKXI0M3hd1EESVji8x5uQ41nxs1q4RMJCCXs7Iq9acpxn22oSDnQ/sJTxsCbHIYZiLyhY05TY0ZLIOQrGaSJDDN4t8pVaIrsqqFdEegtizc1iTew5Q4ayBDMUsQMkXocaYkc0hZua412siZ1rSXlR460zRJ5SlHGe5j801RLMlJTxtaOM3Q1pvxJ45zUlWFD7rsAbpfEm1JHxG0eh8w2R7QQVzBUw28FhFp5QZzq8t2rx2joqulYTWSuJdTYfWwqMFMcovFmSyJPNyLhE4E10pHzYjOC3huArRa571ZsGajQpQx38SBP5pyZB6lMU3khDnp0MBV51BE9o2E+TY5Ml2E8S7C0o6w1xvCZjf0HkVEHCzFoyNmqC+9wdcqN+Tp7jSDheE9ws8Y5V0NJCn2bk2tqSY4okdrEhx1iDN8cSudwepWmAGXKcJXK65H9to8jYQRH7SBF01ESUJdd0TayVInaWhLkOjlXE5irKGOnI6GSWGCJa482zBI9rCr0jyTVcEuzriC1vcr6mwFGSiqy5zMwxBH/TJHwjSPhL8+01kaaSUuMFKTcLEvaUePcrSmwn8DZrgikWb7CGPxkSjhQwrRk57tctmxLsb9sZvL9LSlyuSLlWkqOjwduo8b6Uv1DkmudIeFF2dHCgxVtk8dpIvHpBxhEOdhKk7OLIUSdJ+cSRY57B+0DgGUUlNfpthTfGkauzxrvTsUUaCVhlKeteTXCoJDCa2NOKhOmC4G1H8JBd4OBZReSRGkqcb/CO1PyLJTLB4j1q8JYaIutEjSLX8YKM+a6phdMsdLFUoV5RTm9JSkuDN8WcIon0NZMNZWh1q8C7SJEwV5HxrmnnTrf3KoJBlmCYI2ilSLlfEvlE4011NNgjgthzEua0oKK7JLE7HZHlEl60BLMVFewg4EWNt0ThrVNEVkkiTwpKXSWJzdRENgvKGq4IhjsiezgSFtsfCUq8qki5S1LRQeYQQ4nemmCkImWMw3tFUoUBZk4NOeZYEp4XRKTGa6wJjrWNHBVJR4m3FCnbuD6aak2WsMTh3SZImGCIPKNgsDpVwnsa70K31lCFJZYcwwSMFcQulGTsZuEaSdBXkPGZhu0FsdUO73RHjq8MPGGIfaGIbVTk6iuI3GFgucHrIQkmWSJdBd7BBu+uOryWAhY7+Lki9rK5wtEQzWwvtbqGhIMFwWRJsElsY4m9IIg9L6lCX0VklaPAYkfkZEGDnOWowlBJjtMUkcGK4Lg6EtoZInMUBVYLgn0UsdmCyCz7gIGHFfk+k1QwTh5We7A9x+IdJ6CvIkEagms0hR50eH9UnTQJ+2oiKyVlLFUE+8gBGu8MQ3CppUHesnjTHN4QB/UGPhCTHLFPHMFrCqa73gqObUJGa03wgbhHkrCfpEpzNLE7JDS25FMKhlhKKWKfCgqstLCPu1zBXy0J2ztwjtixBu8UTRn9LVtkmCN2iyFhtME70JHRQ1KVZXqKI/KNIKYMCYs1GUMEKbM1bKOI9LDXC7zbHS+bt+1MTWS9odA9DtrYtpbImQJ2VHh/lisEwaHqUk1kjKTAKknkBEXkbkdMGwq0dnhzLJF3NJH3JVwrqOB4Sca2hti75nmJN0WzxS6UxDYoEpxpa4htVlRjkYE7DZGzJVU72uC9IyhQL4i8YfGWSYLLNcHXloyz7QhNifmKSE9JgfGmuyLhc403Xm9vqcp6gXe3xuuv8F6VJNxkyTHEkHG2g0aKXL0MsXc1bGfgas2//dCONXiNLCX+5mB7eZIl1kHh7ajwpikyzlUUWOVOsjSQlsS+M0R+pPje/dzBXRZGO0rMtgQrLLG9VSu9n6CMXS3BhwYmSoIBhsjNBmZbgusE9BCPCP5triU4VhNbJfE+swSP27aayE8tuTpYYjtrYjMVGZdp2NpS1s6aBnKSHDsbKuplKbHM4a0wMFd/5/DmGyKrJSUaW4IBrqUhx0vyfzTBBLPIUcnZdrAkNsKR0sWRspumSns6Ch0v/qqIbBYUWKvPU/CFoyrDJGwSNFhbA/MlzKqjrO80hRbpKx0Jewsi/STftwGSlKc1JZyAzx05dhLEdnfQvhZOqiHWWEAHC7+30FuRcZUgaO5gpaIK+xsiHRUsqaPElTV40xQZQ107Q9BZE1nryDVGU9ZSQ47bmhBpLcYpUt7S+xuK/FiT8qKjwXYw5ypS2iuCv7q1gtgjhuBuB8LCFY5cUuCNtsQOFcT+4Ih9JX+k8Ea6v0iCIRZOtCT0Et00JW5UeC85Cg0ScK0k411HcG1zKtre3SeITBRk7WfwDhEvaYLTHP9le0m8By0JDwn4TlLW/aJOvGHxdjYUes+ScZigCkYQdNdEOhkiezgShqkx8ueKjI8lDfK2oNiOFvrZH1hS+tk7NV7nOmLHicGWEgubkXKdwdtZknCLJXaCpkrjZBtLZFsDP9CdxWsSr05Sxl6CMmoFbCOgryX40uDtamB7SVmXW4Ihlgpmq+00tBKUUa83WbjLUNkzDmY7cow1JDygyPGlhgGKYKz4vcV7QBNbJIgM11TUqZaMdwTeSguH6rOaw1JRKzaaGyxVm2EJ/uCIrVWUcZUkcp2grMsEjK+DMwS59jQk3Kd6SEq1d0S6uVmO4Bc1lDXTUcHjluCXEq+1OlBDj1pi9zgiXxnKuE0SqTXwhqbETW6RggMEnGl/q49UT2iCzgJvRwVXS2K/d6+ZkyUl7jawSVLit46EwxVljDZwoSQ20sDBihztHfk2yA8NVZghiXwrYHQdfKAOtzsayjhY9bY0yE2CWEeJ9xfzO423xhL5syS2TFJofO2pboHob0nY4GiAgRrvGQEDa/FWSsoaaYl0syRsEt3kWoH3B01shCXhTUWe9w3Bt44SC9QCh3eShQctwbaK2ApLroGCMlZrYqvlY3qYhM0aXpFkPOuoqJ3Dm6fxXrGwVF9gCWZagjPqznfkuMKQ8DPTQRO8ZqG1hPGKEm9IgpGW4DZDgTNriTxvFiq+Lz+0cKfp4wj6OCK9JSnzNSn9LFU7UhKZZMnYwcJ8s8yRsECScK4j5UOB95HFO0CzhY4xJxuCix0lDlEUeMdS6EZBkTsUkZ4K74dugyTXS7aNgL8aqjDfkCE0ZbwkCXpaWCKhl8P7VD5jxykivSyxyZrYERbe168LYu9ZYh86IkscgVLE7tWPKmJv11CgoyJltMEbrohtVAQfO4ImltiHEroYEs7RxAarVpY8AwXMcMReFOTYWe5iiLRQxJ5Q8DtJ8LQhWOhIeFESPGsILhbNDRljNbHzNRlTFbk2S3L0NOS6V1KFJYKUbSTcIIhM0wQ/s2TM0SRMNcQmSap3jCH4yhJZKSkwyRHpYYgsFeQ4U7xoCB7VVOExhXepo9ABBsYbvGWKXPME3lyH95YioZ0gssQRWWbI+FaSMkXijZXwgiTlYdPdkNLaETxlyDVIwqeaEus0aTcYcg0RVOkpR3CSJqIddK+90JCxzsDVloyrFd5ZAr4TBKfaWa6boEA7C7s6EpYaeFPjveooY72mjIccLHJ9HUwVlDhKkmutJDJBwnp1rvulJZggKDRfbXAkvC/4l3ozQOG9a8lxjx0i7nV4jSXc7vhe3OwIxjgSHjdEhhsif9YkPGlus3iLFDnWOFhtCZbJg0UbQcIaR67JjthoCyMEZRwhiXWyxO5QxI6w5NhT4U1WsJvDO60J34fW9hwzwlKij6ZAW9ne4L0s8C6XeBMEkd/LQy1VucBRot6QMlbivaBhoBgjqGiCJNhsqVp/S2SsG6DIONCR0dXhvWbJ+MRRZJkkuEjgDXJjFQW6SSL7GXK8Z2CZg7cVsbWGoKmEpzQ5elpiy8Ryg7dMkLLUEauzeO86CuwlSOlgYLojZWeJ9xM3S1PWfEfKl5ISLQ0MEKR8YOB2QfCxJBjrKPCN4f9MkaSsqoVXJBmP7EpFZ9UQfOoOFwSzBN4MQ8LsGrymlipcJQhmy0GaQjPqCHaXRwuCZwRbqK2Fg9wlClZqYicrIgMdZfxTQ0c7TBIbrChxmuzoKG8XRaSrIhhiyNFJkrC7oIAWMEOQa5aBekPCRknCo4IKPrYkvCDI8aYmY7WFtprgekcJZ3oLIqssCSMtFbQTJKwXYy3BY5oCh2iKPCpJOE+zRdpYgi6O2KmOAgvVCYaU4ySRek1sgyFhJ403QFHiVEmJHwtybO1gs8Hr5+BETQX3War0qZngYGgtVZtoqd6vFSk/UwdZElYqyjrF4HXUeFspIi9IGKf4j92pKGAdCYMVsbcV3kRF0N+R8LUd5PCsIGWoxDtBkCI0nKofdJQxT+LtZflvuc8Q3CjwWkq8KwUpHzkK/NmSsclCL0nseQdj5FRH5CNHSgtLiW80Of5HU9Hhlsga9bnBq3fEVltKfO5IaSTmGjjc4J0otcP7QsJUSQM8pEj5/wCuUuC2DWz8AAAAAElFTkSuQmCC");
81 }
@@ -0,0 +1,25
1 /* Port of TextMate's Blackboard theme */
2
3 .cm-s-blackboard { background: #0C1021; color: #F8F8F8; }
4 .cm-s-blackboard .CodeMirror-selected { background: #253B76 !important; }
5 .cm-s-blackboard .CodeMirror-gutter { background: #0C1021; border-right: 0; }
6 .cm-s-blackboard .CodeMirror-gutter-text { color: #888; }
7 .cm-s-blackboard .CodeMirror-cursor { border-left: 1px solid #A7A7A7 !important; }
8
9 .cm-s-blackboard .cm-keyword { color: #FBDE2D; }
10 .cm-s-blackboard .cm-atom { color: #D8FA3C; }
11 .cm-s-blackboard .cm-number { color: #D8FA3C; }
12 .cm-s-blackboard .cm-def { color: #8DA6CE; }
13 .cm-s-blackboard .cm-variable { color: #FF6400; }
14 .cm-s-blackboard .cm-operator { color: #FBDE2D;}
15 .cm-s-blackboard .cm-comment { color: #AEAEAE; }
16 .cm-s-blackboard .cm-string { color: #61CE3C; }
17 .cm-s-blackboard .cm-string-2 { color: #61CE3C; }
18 .cm-s-blackboard .cm-meta { color: #D8FA3C; }
19 .cm-s-blackboard .cm-error { background: #9D1E15; color: #F8F8F8; }
20 .cm-s-blackboard .cm-builtin { color: #8DA6CE; }
21 .cm-s-blackboard .cm-tag { color: #8DA6CE; }
22 .cm-s-blackboard .cm-attribute { color: #8DA6CE; }
23 .cm-s-blackboard .cm-header { color: #FF6400; }
24 .cm-s-blackboard .cm-hr { color: #AEAEAE; }
25 .cm-s-blackboard .cm-link { color: #8DA6CE; }
@@ -0,0 +1,21
1 .cm-s-erlang-dark { background: #002240; color: white; }
2 .cm-s-erlang-dark div.CodeMirror-selected { background: #b36539 !important; }
3 .cm-s-erlang-dark .CodeMirror-gutter { background: #002240; border-right: 1px solid #aaa; }
4 .cm-s-erlang-dark .CodeMirror-gutter-text { color: #d0d0d0; }
5 .cm-s-erlang-dark .CodeMirror-cursor { border-left: 1px solid white !important; }
6
7 .cm-s-erlang-dark span.cm-atom { color: #845dc4; }
8 .cm-s-erlang-dark span.cm-attribute { color: #ff80e1; }
9 .cm-s-erlang-dark span.cm-bracket { color: #ff9d00; }
10 .cm-s-erlang-dark span.cm-builtin { color: #eeaaaa; }
11 .cm-s-erlang-dark span.cm-comment { color: #7777ff; }
12 .cm-s-erlang-dark span.cm-def { color: #ee77aa; }
13 .cm-s-erlang-dark span.cm-error { color: #9d1e15; }
14 .cm-s-erlang-dark span.cm-keyword { color: #ffee80; }
15 .cm-s-erlang-dark span.cm-meta { color: #50fefe; }
16 .cm-s-erlang-dark span.cm-number { color: #ffd0d0; }
17 .cm-s-erlang-dark span.cm-operator { color: #dd1111; }
18 .cm-s-erlang-dark span.cm-string { color: #3ad900; }
19 .cm-s-erlang-dark span.cm-tag { color: #9effff; }
20 .cm-s-erlang-dark span.cm-variable { color: #50fe50; }
21 .cm-s-erlang-dark span.cm-variable-2 { color: #ee00ee; }
@@ -0,0 +1,44
1 /*
2 http://lesscss.org/ dark theme
3 Ported to CodeMirror by Peter Kroon
4 */
5 .cm-s-lesser-dark {
6 line-height: 1.3em;
7 }
8 .cm-s-lesser-dark {
9 font-family: 'Bitstream Vera Sans Mono', 'DejaVu Sans Mono', 'Monaco', Courier, monospace !important;
10 }
11
12 .cm-s-lesser-dark { background: #262626; color: #EBEFE7; text-shadow: 0 -1px 1px #262626; }
13 .cm-s-lesser-dark div.CodeMirror-selected {background: #45443B !important;} /* 33322B*/
14 .cm-s-lesser-dark .CodeMirror-cursor { border-left: 1px solid white !important; }
15 .cm-s-lesser-dark .CodeMirror-lines { margin-left:3px; margin-right:3px; }/*editable code holder*/
16
17 div.CodeMirror span.CodeMirror-matchingbracket { color: #7EFC7E; }/*65FC65*/
18
19 .cm-s-lesser-dark .CodeMirror-gutter { background: #262626; border-right:1px solid #aaa; padding-right:3px; min-width:2.5em; }
20 .cm-s-lesser-dark .CodeMirror-gutter-text { color: #777; }
21
22 .cm-s-lesser-dark span.cm-keyword { color: #599eff; }
23 .cm-s-lesser-dark span.cm-atom { color: #C2B470; }
24 .cm-s-lesser-dark span.cm-number { color: #B35E4D; }
25 .cm-s-lesser-dark span.cm-def {color: white;}
26 .cm-s-lesser-dark span.cm-variable { color:#D9BF8C; }
27 .cm-s-lesser-dark span.cm-variable-2 { color: #669199; }
28 .cm-s-lesser-dark span.cm-variable-3 { color: white; }
29 .cm-s-lesser-dark span.cm-property {color: #92A75C;}
30 .cm-s-lesser-dark span.cm-operator {color: #92A75C;}
31 .cm-s-lesser-dark span.cm-comment { color: #666; }
32 .cm-s-lesser-dark span.cm-string { color: #BCD279; }
33 .cm-s-lesser-dark span.cm-string-2 {color: #f50;}
34 .cm-s-lesser-dark span.cm-meta { color: #738C73; }
35 .cm-s-lesser-dark span.cm-error { color: #9d1e15; }
36 .cm-s-lesser-dark span.cm-qualifier {color: #555;}
37 .cm-s-lesser-dark span.cm-builtin { color: #ff9e59; }
38 .cm-s-lesser-dark span.cm-bracket { color: #EBEFE7; }
39 .cm-s-lesser-dark span.cm-tag { color: #669199; }
40 .cm-s-lesser-dark span.cm-attribute {color: #00c;}
41 .cm-s-lesser-dark span.cm-header {color: #a0a;}
42 .cm-s-lesser-dark span.cm-quote {color: #090;}
43 .cm-s-lesser-dark span.cm-hr {color: #999;}
44 .cm-s-lesser-dark span.cm-link {color: #00c;}
@@ -0,0 +1,27
1 /* Taken from the popular Visual Studio Vibrant Ink Schema */
2
3 .cm-s-vibrant-ink { background: black; color: white; }
4 .cm-s-vibrant-ink .CodeMirror-selected { background: #35493c !important; }
5
6 .cm-s-vibrant-ink .CodeMirror-gutter { background: #002240; border-right: 1px solid #aaa; }
7 .cm-s-vibrant-ink .CodeMirror-gutter-text { color: #d0d0d0; }
8 .cm-s-vibrant-ink .CodeMirror-cursor { border-left: 1px solid white !important; }
9
10 .cm-s-vibrant-ink .cm-keyword { color: #CC7832; }
11 .cm-s-vibrant-ink .cm-atom { color: #FC0; }
12 .cm-s-vibrant-ink .cm-number { color: #FFEE98; }
13 .cm-s-vibrant-ink .cm-def { color: #8DA6CE; }
14 .cm-s-vibrant-ink span.cm-variable-2, .cm-s-cobalt span.cm-tag { color: #FFC66D }
15 .cm-s-vibrant-ink span.cm-variable-3, .cm-s-cobalt span.cm-def { color: #FFC66D }
16 .cm-s-vibrant-ink .cm-operator { color: #888; }
17 .cm-s-vibrant-ink .cm-comment { color: gray; font-weight: bold; }
18 .cm-s-vibrant-ink .cm-string { color: #A5C25C }
19 .cm-s-vibrant-ink .cm-string-2 { color: red }
20 .cm-s-vibrant-ink .cm-meta { color: #D8FA3C; }
21 .cm-s-vibrant-ink .cm-error { border-bottom: 1px solid red; }
22 .cm-s-vibrant-ink .cm-builtin { color: #8DA6CE; }
23 .cm-s-vibrant-ink .cm-tag { color: #8DA6CE; }
24 .cm-s-vibrant-ink .cm-attribute { color: #8DA6CE; }
25 .cm-s-vibrant-ink .cm-header { color: #FF6400; }
26 .cm-s-vibrant-ink .cm-hr { color: #AEAEAE; }
27 .cm-s-vibrant-ink .cm-link { color: blue; }
@@ -0,0 +1,46
1 /*
2 Copyright (C) 2011 by MarkLogic Corporation
3 Author: Mike Brevoort <mike@brevoort.com>
4
5 Permission is hereby granted, free of charge, to any person obtaining a copy
6 of this software and associated documentation files (the "Software"), to deal
7 in the Software without restriction, including without limitation the rights
8 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 copies of the Software, and to permit persons to whom the Software is
10 furnished to do so, subject to the following conditions:
11
12 The above copyright notice and this permission notice shall be included in
13 all copies or substantial portions of the Software.
14
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 THE SOFTWARE.
22 */
23 .cm-s-xq-dark { background: #0a001f; color: #f8f8f8; }
24 .cm-s-xq-dark span.CodeMirror-selected { background: #a8f !important; }
25 .cm-s-xq-dark .CodeMirror-gutter { background: #0a001f; border-right: 1px solid #aaa; }
26 .cm-s-xq-dark .CodeMirror-gutter-text { color: #f8f8f8; }
27 .cm-s-xq-dark .CodeMirror-cursor { border-left: 1px solid white !important; }
28
29 .cm-s-xq-dark span.cm-keyword {color: #FFBD40;}
30 .cm-s-xq-dark span.cm-atom {color: #6C8CD5;}
31 .cm-s-xq-dark span.cm-number {color: #164;}
32 .cm-s-xq-dark span.cm-def {color: #FFF; text-decoration:underline;}
33 .cm-s-xq-dark span.cm-variable {color: #FFF;}
34 .cm-s-xq-dark span.cm-variable-2 {color: #EEE;}
35 .cm-s-xq-dark span.cm-variable-3 {color: #DDD;}
36 .cm-s-xq-dark span.cm-property {}
37 .cm-s-xq-dark span.cm-operator {}
38 .cm-s-xq-dark span.cm-comment {color: gray;}
39 .cm-s-xq-dark span.cm-string {color: #9FEE00;}
40 .cm-s-xq-dark span.cm-meta {color: yellow;}
41 .cm-s-xq-dark span.cm-error {color: #f00;}
42 .cm-s-xq-dark span.cm-qualifier {color: #FFF700;}
43 .cm-s-xq-dark span.cm-builtin {color: #30a;}
44 .cm-s-xq-dark span.cm-bracket {color: #cc7;}
45 .cm-s-xq-dark span.cm-tag {color: #FFBD40;}
46 .cm-s-xq-dark span.cm-attribute {color: #FFF700;}
@@ -1,4 +1,4
1 Copyright (C) 2011 by Marijn Haverbeke <marijnh@gmail.com>
1 Copyright (C) 2012 by Marijn Haverbeke <marijnh@gmail.com>
2
2
3 Permission is hereby granted, free of charge, to any person obtaining a copy
3 Permission is hereby granted, free of charge, to any person obtaining a copy
4 of this software and associated documentation files (the "Software"), to deal
4 of this software and associated documentation files (the "Software"), to deal
@@ -1,6 +1,8
1 # CodeMirror 2
1 # CodeMirror 2
2
2
3 CodeMirror 2 is a rewrite of [CodeMirror
3 CodeMirror is a JavaScript component that provides a code editor in
4 1](http://github.com/marijnh/CodeMirror). The docs live
4 the browser. When a mode is available for the language you are coding
5 [here](http://codemirror.net/doc/manual.html), and the project page is
5 in, it will color your code, and optionally help with indentation.
6 [http://codemirror.net/](http://codemirror.net/).
6
7 The project page is http://codemirror.net
8 The manual is at http://codemirror.net/doc/manual.html
@@ -1,14 +1,52
1 .CodeMirror {
1 .CodeMirror {
2 line-height: 1em;
2 line-height: 1em;
3 font-family: monospace;
3 font-family: monospace;
4
5 /* Necessary so the scrollbar can be absolutely positioned within the wrapper on Lion. */
6 position: relative;
7 /* This prevents unwanted scrollbars from showing up on the body and wrapper in IE. */
8 overflow: hidden;
4 }
9 }
5
10
6 .CodeMirror-scroll {
11 .CodeMirror-scroll {
7 overflow: auto;
12 overflow-x: auto;
13 overflow-y: hidden;
8 height: 300px;
14 height: 300px;
9 /* This is needed to prevent an IE[67] bug where the scrolled content
15 /* This is needed to prevent an IE[67] bug where the scrolled content
10 is visible outside of the scrolling box. */
16 is visible outside of the scrolling box. */
11 position: relative;
17 position: relative;
18 outline: none;
19 }
20
21 /* Vertical scrollbar */
22 .CodeMirror-scrollbar {
23 float: right;
24 overflow-x: hidden;
25 overflow-y: scroll;
26
27 /* This corrects for the 1px gap introduced to the left of the scrollbar
28 by the rule for .CodeMirror-scrollbar-inner. */
29 margin-left: -1px;
30 }
31 .CodeMirror-scrollbar-inner {
32 /* This needs to have a nonzero width in order for the scrollbar to appear
33 in Firefox and IE9. */
34 width: 1px;
35 }
36 .CodeMirror-scrollbar.cm-sb-overlap {
37 /* Ensure that the scrollbar appears in Lion, and that it overlaps the content
38 rather than sitting to the right of it. */
39 position: absolute;
40 z-index: 1;
41 float: none;
42 right: 0;
43 min-width: 12px;
44 }
45 .CodeMirror-scrollbar.cm-sb-nonoverlap {
46 min-width: 12px;
47 }
48 .CodeMirror-scrollbar.cm-sb-ie7 {
49 min-width: 18px;
12 }
50 }
13
51
14 .CodeMirror-gutter {
52 .CodeMirror-gutter {
@@ -24,9 +62,16
24 text-align: right;
62 text-align: right;
25 padding: .4em .2em .4em .4em;
63 padding: .4em .2em .4em .4em;
26 white-space: pre !important;
64 white-space: pre !important;
65 cursor: default;
27 }
66 }
28 .CodeMirror-lines {
67 .CodeMirror-lines {
29 padding: .4em;
68 padding: .4em;
69 white-space: pre;
70 cursor: text;
71 }
72 .CodeMirror-lines * {
73 /* Necessary for throw-scrolling to decelerate properly on Safari. */
74 pointer-events: none;
30 }
75 }
31
76
32 .CodeMirror pre {
77 .CodeMirror pre {
@@ -40,11 +85,14
40 padding: 0; margin: 0;
85 padding: 0; margin: 0;
41 white-space: pre;
86 white-space: pre;
42 word-wrap: normal;
87 word-wrap: normal;
88 line-height: inherit;
89 color: inherit;
43 }
90 }
44
91
45 .CodeMirror-wrap pre {
92 .CodeMirror-wrap pre {
46 word-wrap: break-word;
93 word-wrap: break-word;
47 white-space: pre-wrap;
94 white-space: pre-wrap;
95 word-break: normal;
48 }
96 }
49 .CodeMirror-wrap .CodeMirror-scroll {
97 .CodeMirror-wrap .CodeMirror-scroll {
50 overflow-x: hidden;
98 overflow-x: hidden;
@@ -59,7 +107,21
59 position: absolute;
107 position: absolute;
60 visibility: hidden;
108 visibility: hidden;
61 border-left: 1px solid black;
109 border-left: 1px solid black;
110 border-right: none;
111 width: 0;
112 }
113 .cm-keymap-fat-cursor pre.CodeMirror-cursor {
114 width: auto;
115 border: 0;
116 background: transparent;
117 background: rgba(0, 200, 0, .4);
118 filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#6600c800, endColorstr=#4c00c800);
119 }
120 /* Kludge to turn off filter in ie9+, which also accepts rgba */
121 .cm-keymap-fat-cursor pre.CodeMirror-cursor:not(#nonsense_id) {
122 filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
62 }
123 }
124 .CodeMirror pre.CodeMirror-cursor.CodeMirror-overwrite {}
63 .CodeMirror-focused pre.CodeMirror-cursor {
125 .CodeMirror-focused pre.CodeMirror-cursor {
64 visibility: visible;
126 visibility: visible;
65 }
127 }
@@ -93,7 +155,7 div.CodeMirror-selected { background: #d9d9d9; }
93 .cm-s-default span.cm-bracket {color: #cc7;}
155 .cm-s-default span.cm-bracket {color: #cc7;}
94 .cm-s-default span.cm-tag {color: #170;}
156 .cm-s-default span.cm-tag {color: #170;}
95 .cm-s-default span.cm-attribute {color: #00c;}
157 .cm-s-default span.cm-attribute {color: #00c;}
96 .cm-s-default span.cm-header {color: #a0a;}
158 .cm-s-default span.cm-header {color: blue;}
97 .cm-s-default span.cm-quote {color: #090;}
159 .cm-s-default span.cm-quote {color: #090;}
98 .cm-s-default span.cm-hr {color: #999;}
160 .cm-s-default span.cm-hr {color: #999;}
99 .cm-s-default span.cm-link {color: #00c;}
161 .cm-s-default span.cm-link {color: #00c;}
This diff has been collapsed as it changes many lines, (1180 lines changed) Show them Hide them
@@ -4,7 +4,7
4
4
5 // CodeMirror is the only global var we claim
5 // CodeMirror is the only global var we claim
6 var CodeMirror = (function() {
6 var CodeMirror = (function() {
7 // This is the function that produces an editor instance. It's
7 // This is the function that produces an editor instance. Its
8 // closure is used to store the editor state.
8 // closure is used to store the editor state.
9 function CodeMirror(place, givenOptions) {
9 function CodeMirror(place, givenOptions) {
10 // Determine effective options based on given values and defaults.
10 // Determine effective options based on given values and defaults.
@@ -13,23 +13,27 var CodeMirror = (function() {
13 if (defaults.hasOwnProperty(opt))
13 if (defaults.hasOwnProperty(opt))
14 options[opt] = (givenOptions && givenOptions.hasOwnProperty(opt) ? givenOptions : defaults)[opt];
14 options[opt] = (givenOptions && givenOptions.hasOwnProperty(opt) ? givenOptions : defaults)[opt];
15
15
16 var targetDocument = options["document"];
17 // The element in which the editor lives.
16 // The element in which the editor lives.
18 var wrapper = targetDocument.createElement("div");
17 var wrapper = document.createElement("div");
19 wrapper.className = "CodeMirror" + (options.lineWrapping ? " CodeMirror-wrap" : "");
18 wrapper.className = "CodeMirror" + (options.lineWrapping ? " CodeMirror-wrap" : "");
20 // This mess creates the base DOM structure for the editor.
19 // This mess creates the base DOM structure for the editor.
21 wrapper.innerHTML =
20 wrapper.innerHTML =
22 '<div style="overflow: hidden; position: relative; width: 3px; height: 0px;">' + // Wraps and hides input textarea
21 '<div style="overflow: hidden; position: relative; width: 3px; height: 0px;">' + // Wraps and hides input textarea
23 '<textarea style="position: absolute; padding: 0; width: 1px; height: 1em" wrap="off" ' +
22 '<textarea style="position: absolute; padding: 0; width: 1px; height: 1em" wrap="off" ' +
24 'autocorrect="off" autocapitalize="off"></textarea></div>' +
23 'autocorrect="off" autocapitalize="off"></textarea></div>' +
24 '<div class="CodeMirror-scrollbar">' + // The vertical scrollbar. Horizontal scrolling is handled by the scroller itself.
25 '<div class="CodeMirror-scrollbar-inner">' + // The empty scrollbar content, used solely for managing the scrollbar thumb.
26 '</div></div>' + // This must be before the scroll area because it's float-right.
25 '<div class="CodeMirror-scroll" tabindex="-1">' +
27 '<div class="CodeMirror-scroll" tabindex="-1">' +
26 '<div style="position: relative">' + // Set to the height of the text, causes scrolling
28 '<div style="position: relative">' + // Set to the height of the text, causes scrolling
27 '<div style="position: relative">' + // Moved around its parent to cover visible view
29 '<div style="position: relative">' + // Moved around its parent to cover visible view
28 '<div class="CodeMirror-gutter"><div class="CodeMirror-gutter-text"></div></div>' +
30 '<div class="CodeMirror-gutter"><div class="CodeMirror-gutter-text"></div></div>' +
29 // Provides positioning relative to (visible) text origin
31 // Provides positioning relative to (visible) text origin
30 '<div class="CodeMirror-lines"><div style="position: relative; z-index: 0">' +
32 '<div class="CodeMirror-lines"><div style="position: relative; z-index: 0">' +
31 '<div style="position: absolute; width: 100%; height: 0; overflow: hidden; visibility: hidden; outline: 5px auto none"></div>' +
33 // Used to measure text size
34 '<div style="position: absolute; width: 100%; height: 0px; overflow: hidden; visibility: hidden;"></div>' +
32 '<pre class="CodeMirror-cursor">&#160;</pre>' + // Absolutely positioned blinky cursor
35 '<pre class="CodeMirror-cursor">&#160;</pre>' + // Absolutely positioned blinky cursor
36 '<pre class="CodeMirror-cursor" style="visibility: hidden">&#160;</pre>' + // Used to force a width
33 '<div style="position: relative; z-index: -1"></div><div></div>' + // DIVs containing the selection and the actual code
37 '<div style="position: relative; z-index: -1"></div><div></div>' + // DIVs containing the selection and the actual code
34 '</div></div></div></div></div>';
38 '</div></div></div></div></div>';
35 if (place.appendChild) place.appendChild(wrapper); else place(wrapper);
39 if (place.appendChild) place.appendChild(wrapper); else place(wrapper);
@@ -38,15 +42,30 var CodeMirror = (function() {
38 scroller = wrapper.lastChild, code = scroller.firstChild,
42 scroller = wrapper.lastChild, code = scroller.firstChild,
39 mover = code.firstChild, gutter = mover.firstChild, gutterText = gutter.firstChild,
43 mover = code.firstChild, gutter = mover.firstChild, gutterText = gutter.firstChild,
40 lineSpace = gutter.nextSibling.firstChild, measure = lineSpace.firstChild,
44 lineSpace = gutter.nextSibling.firstChild, measure = lineSpace.firstChild,
41 cursor = measure.nextSibling, selectionDiv = cursor.nextSibling,
45 cursor = measure.nextSibling, widthForcer = cursor.nextSibling,
42 lineDiv = selectionDiv.nextSibling;
46 selectionDiv = widthForcer.nextSibling, lineDiv = selectionDiv.nextSibling,
43 themeChanged();
47 scrollbar = inputDiv.nextSibling, scrollbarInner = scrollbar.firstChild;
48 themeChanged(); keyMapChanged();
44 // Needed to hide big blue blinking cursor on Mobile Safari
49 // Needed to hide big blue blinking cursor on Mobile Safari
45 if (ios) input.style.width = "0px";
50 if (ios) input.style.width = "0px";
46 if (!webkit) lineSpace.draggable = true;
51 if (!webkit) scroller.draggable = true;
47 lineSpace.style.outline = "none";
52 lineSpace.style.outline = "none";
48 if (options.tabindex != null) input.tabIndex = options.tabindex;
53 if (options.tabindex != null) input.tabIndex = options.tabindex;
54 if (options.autofocus) focusInput();
49 if (!options.gutter && !options.lineNumbers) gutter.style.display = "none";
55 if (!options.gutter && !options.lineNumbers) gutter.style.display = "none";
56 // Needed to handle Tab key in KHTML
57 if (khtml) inputDiv.style.height = "1px", inputDiv.style.position = "absolute";
58
59 // Check for OS X >= 10.7. If so, we need to force a width on the scrollbar, and
60 // make it overlap the content. (But we only do this if the scrollbar doesn't already
61 // have a natural width. If the mouse is plugged in or the user sets the system pref
62 // to always show scrollbars, the scrollbar shouldn't overlap.)
63 if (mac_geLion) {
64 scrollbar.className += (overlapScrollbars() ? " cm-sb-overlap" : " cm-sb-nonoverlap");
65 } else if (ie_lt8) {
66 // Need to set a minimum width to see the scrollbar on IE7 (but must not set it on IE8).
67 scrollbar.className += " cm-sb-ie7";
68 }
50
69
51 // Check for problem with IE innerHTML not working when we have a
70 // Check for problem with IE innerHTML not working when we have a
52 // P (or similar) parent node.
71 // P (or similar) parent node.
@@ -71,7 +90,7 var CodeMirror = (function() {
71 var sel = {from: {line: 0, ch: 0}, to: {line: 0, ch: 0}, inverted: false};
90 var sel = {from: {line: 0, ch: 0}, to: {line: 0, ch: 0}, inverted: false};
72 // Selection-related flags. shiftSelecting obviously tracks
91 // Selection-related flags. shiftSelecting obviously tracks
73 // whether the user is holding shift.
92 // whether the user is holding shift.
74 var shiftSelecting, lastClick, lastDoubleClick, lastScrollPos = 0, draggingText,
93 var shiftSelecting, lastClick, lastDoubleClick, lastScrollTop = 0, lastScrollLeft = 0, draggingText,
75 overwrite = false, suppressEdits = false;
94 overwrite = false, suppressEdits = false;
76 // Variables used by startOperation/endOperation to track what
95 // Variables used by startOperation/endOperation to track what
77 // happened during the operation.
96 // happened during the operation.
@@ -79,12 +98,13 var CodeMirror = (function() {
79 gutterDirty, callbacks;
98 gutterDirty, callbacks;
80 // Current visible range (may be bigger than the view window).
99 // Current visible range (may be bigger than the view window).
81 var displayOffset = 0, showingFrom = 0, showingTo = 0, lastSizeC = 0;
100 var displayOffset = 0, showingFrom = 0, showingTo = 0, lastSizeC = 0;
82 // bracketHighlighted is used to remember that a backet has been
101 // bracketHighlighted is used to remember that a bracket has been
83 // marked.
102 // marked.
84 var bracketHighlighted;
103 var bracketHighlighted;
85 // Tracks the maximum line length so that the horizontal scrollbar
104 // Tracks the maximum line length so that the horizontal scrollbar
86 // can be kept static when scrolling.
105 // can be kept static when scrolling.
87 var maxLine = "", maxWidth, tabText = computeTabText();
106 var maxLine = "", updateMaxLine = false, maxLineChanged = true;
107 var tabCache = {};
88
108
89 // Initialize the content.
109 // Initialize the content.
90 operation(function(){setValue(options.value || ""); updateInput = false;})();
110 operation(function(){setValue(options.value || ""); updateInput = false;})();
@@ -93,18 +113,16 var CodeMirror = (function() {
93 // Register our event handlers.
113 // Register our event handlers.
94 connect(scroller, "mousedown", operation(onMouseDown));
114 connect(scroller, "mousedown", operation(onMouseDown));
95 connect(scroller, "dblclick", operation(onDoubleClick));
115 connect(scroller, "dblclick", operation(onDoubleClick));
96 connect(lineSpace, "dragstart", onDragStart);
97 connect(lineSpace, "selectstart", e_preventDefault);
116 connect(lineSpace, "selectstart", e_preventDefault);
98 // Gecko browsers fire contextmenu *after* opening the menu, at
117 // Gecko browsers fire contextmenu *after* opening the menu, at
99 // which point we can't mess with it anymore. Context menu is
118 // which point we can't mess with it anymore. Context menu is
100 // handled in onMouseDown for Gecko.
119 // handled in onMouseDown for Gecko.
101 if (!gecko) connect(scroller, "contextmenu", onContextMenu);
120 if (!gecko) connect(scroller, "contextmenu", onContextMenu);
102 connect(scroller, "scroll", function() {
121 connect(scroller, "scroll", onScroll);
103 lastScrollPos = scroller.scrollTop;
122 connect(scrollbar, "scroll", onScroll);
104 updateDisplay([]);
123 connect(scrollbar, "mousedown", function() {if (focused) setTimeout(focusInput, 0);});
105 if (options.fixedGutter) gutter.style.left = scroller.scrollLeft + "px";
124 connect(scroller, "mousewheel", onMouseWheel);
106 if (options.onScroll) options.onScroll(instance);
125 connect(scroller, "DOMMouseScroll", onMouseWheel);
107 });
108 connect(window, "resize", function() {updateDisplay(true);});
126 connect(window, "resize", function() {updateDisplay(true);});
109 connect(input, "keyup", operation(onKeyUp));
127 connect(input, "keyup", operation(onKeyUp));
110 connect(input, "input", fastPoll);
128 connect(input, "input", fastPoll);
@@ -113,19 +131,32 var CodeMirror = (function() {
113 connect(input, "focus", onFocus);
131 connect(input, "focus", onFocus);
114 connect(input, "blur", onBlur);
132 connect(input, "blur", onBlur);
115
133
116 connect(scroller, "dragenter", e_stop);
134 if (options.dragDrop) {
117 connect(scroller, "dragover", e_stop);
135 connect(scroller, "dragstart", onDragStart);
118 connect(scroller, "drop", operation(onDrop));
136 function drag_(e) {
137 if (options.onDragEvent && options.onDragEvent(instance, addStop(e))) return;
138 e_stop(e);
139 }
140 connect(scroller, "dragenter", drag_);
141 connect(scroller, "dragover", drag_);
142 connect(scroller, "drop", operation(onDrop));
143 }
119 connect(scroller, "paste", function(){focusInput(); fastPoll();});
144 connect(scroller, "paste", function(){focusInput(); fastPoll();});
120 connect(input, "paste", fastPoll);
145 connect(input, "paste", fastPoll);
121 connect(input, "cut", operation(function(){
146 connect(input, "cut", operation(function(){
122 if (!options.readOnly) replaceSelection("");
147 if (!options.readOnly) replaceSelection("");
123 }));
148 }));
124
149
150 // Needed to handle Tab key in KHTML
151 if (khtml) connect(code, "mouseup", function() {
152 if (document.activeElement == input) input.blur();
153 focusInput();
154 });
155
125 // IE throws unspecified error in certain cases, when
156 // IE throws unspecified error in certain cases, when
126 // trying to access activeElement before onload
157 // trying to access activeElement before onload
127 var hasFocus; try { hasFocus = (targetDocument.activeElement == input); } catch(e) { }
158 var hasFocus; try { hasFocus = (document.activeElement == input); } catch(e) { }
128 if (hasFocus) setTimeout(onFocus, 20);
159 if (hasFocus || options.autofocus) setTimeout(onFocus, 20);
129 else onBlur();
160 else onBlur();
130
161
131 function isLine(l) {return l >= 0 && l < doc.size;}
162 function isLine(l) {return l >= 0 && l < doc.size;}
@@ -139,7 +170,7 var CodeMirror = (function() {
139 setValue: operation(setValue),
170 setValue: operation(setValue),
140 getSelection: getSelection,
171 getSelection: getSelection,
141 replaceSelection: operation(replaceSelection),
172 replaceSelection: operation(replaceSelection),
142 focus: function(){focusInput(); onFocus(); fastPoll();},
173 focus: function(){window.focus(); focusInput(); onFocus(); fastPoll();},
143 setOption: function(option, value) {
174 setOption: function(option, value) {
144 var oldVal = options[option];
175 var oldVal = options[option];
145 options[option] = value;
176 options[option] = value;
@@ -148,7 +179,8 var CodeMirror = (function() {
148 else if (option == "readOnly" && !value) {resetInput(true);}
179 else if (option == "readOnly" && !value) {resetInput(true);}
149 else if (option == "theme") themeChanged();
180 else if (option == "theme") themeChanged();
150 else if (option == "lineWrapping" && oldVal != value) operation(wrappingChanged)();
181 else if (option == "lineWrapping" && oldVal != value) operation(wrappingChanged)();
151 else if (option == "tabSize") operation(tabsChanged)();
182 else if (option == "tabSize") updateDisplay(true);
183 else if (option == "keyMap") keyMapChanged();
152 if (option == "lineNumbers" || option == "gutter" || option == "firstLineNumber" || option == "theme") {
184 if (option == "lineNumbers" || option == "gutter" || option == "firstLineNumber" || option == "theme") {
153 gutterChanged();
185 gutterChanged();
154 updateDisplay(true);
186 updateDisplay(true);
@@ -167,6 +199,15 var CodeMirror = (function() {
167 indentSelection: operation(indentSelected),
199 indentSelection: operation(indentSelected),
168 historySize: function() {return {undo: history.done.length, redo: history.undone.length};},
200 historySize: function() {return {undo: history.done.length, redo: history.undone.length};},
169 clearHistory: function() {history = new History();},
201 clearHistory: function() {history = new History();},
202 setHistory: function(histData) {
203 history = new History();
204 history.done = histData.done;
205 history.undone = histData.undone;
206 },
207 getHistory: function() {
208 history.time = 0;
209 return {done: history.done.concat([]), undone: history.undone.concat([])};
210 },
170 matchBrackets: operation(function(){matchBrackets(true);}),
211 matchBrackets: operation(function(){matchBrackets(true);}),
171 getTokenAt: operation(function(pos) {
212 getTokenAt: operation(function(pos) {
172 pos = clipPos(pos);
213 pos = clipPos(pos);
@@ -176,17 +217,23 var CodeMirror = (function() {
176 line = clipLine(line == null ? doc.size - 1: line);
217 line = clipLine(line == null ? doc.size - 1: line);
177 return getStateBefore(line + 1);
218 return getStateBefore(line + 1);
178 },
219 },
179 cursorCoords: function(start){
220 cursorCoords: function(start, mode) {
180 if (start == null) start = sel.inverted;
221 if (start == null) start = sel.inverted;
181 return pageCoords(start ? sel.from : sel.to);
222 return this.charCoords(start ? sel.from : sel.to, mode);
223 },
224 charCoords: function(pos, mode) {
225 pos = clipPos(pos);
226 if (mode == "local") return localCoords(pos, false);
227 if (mode == "div") return localCoords(pos, true);
228 return pageCoords(pos);
182 },
229 },
183 charCoords: function(pos){return pageCoords(clipPos(pos));},
184 coordsChar: function(coords) {
230 coordsChar: function(coords) {
185 var off = eltOffset(lineSpace);
231 var off = eltOffset(lineSpace);
186 return coordsChar(coords.x - off.left, coords.y - off.top);
232 return coordsChar(coords.x - off.left, coords.y - off.top);
187 },
233 },
188 markText: operation(markText),
234 markText: operation(markText),
189 setBookmark: setBookmark,
235 setBookmark: setBookmark,
236 findMarksAt: findMarksAt,
190 setMarker: operation(addGutterMarker),
237 setMarker: operation(addGutterMarker),
191 clearMarker: operation(removeGutterMarker),
238 clearMarker: operation(removeGutterMarker),
192 setLineClass: operation(setLineClass),
239 setLineClass: operation(setLineClass),
@@ -252,14 +299,23 var CodeMirror = (function() {
252 if (isLine(line)) replaceRange("", {line: line, ch: 0}, clipPos({line: line+1, ch: 0}));
299 if (isLine(line)) replaceRange("", {line: line, ch: 0}, clipPos({line: line+1, ch: 0}));
253 }),
300 }),
254 replaceRange: operation(replaceRange),
301 replaceRange: operation(replaceRange),
255 getRange: function(from, to) {return getRange(clipPos(from), clipPos(to));},
302 getRange: function(from, to, lineSep) {return getRange(clipPos(from), clipPos(to), lineSep);},
256
303
304 triggerOnKeyDown: operation(onKeyDown),
257 execCommand: function(cmd) {return commands[cmd](instance);},
305 execCommand: function(cmd) {return commands[cmd](instance);},
258 // Stuff used by commands, probably not much use to outside code.
306 // Stuff used by commands, probably not much use to outside code.
259 moveH: operation(moveH),
307 moveH: operation(moveH),
260 deleteH: operation(deleteH),
308 deleteH: operation(deleteH),
261 moveV: operation(moveV),
309 moveV: operation(moveV),
262 toggleOverwrite: function() {overwrite = !overwrite;},
310 toggleOverwrite: function() {
311 if(overwrite){
312 overwrite = false;
313 cursor.className = cursor.className.replace(" CodeMirror-overwrite", "");
314 } else {
315 overwrite = true;
316 cursor.className += " CodeMirror-overwrite";
317 }
318 },
263
319
264 posFromIndex: function(off) {
320 posFromIndex: function(off) {
265 var lineNo = 0, ch;
321 var lineNo = 0, ch;
@@ -281,15 +337,28 var CodeMirror = (function() {
281 },
337 },
282 scrollTo: function(x, y) {
338 scrollTo: function(x, y) {
283 if (x != null) scroller.scrollLeft = x;
339 if (x != null) scroller.scrollLeft = x;
284 if (y != null) scroller.scrollTop = y;
340 if (y != null) scrollbar.scrollTop = y;
285 updateDisplay([]);
341 updateDisplay([]);
286 },
342 },
343 getScrollInfo: function() {
344 return {x: scroller.scrollLeft, y: scrollbar.scrollTop,
345 height: scrollbar.scrollHeight, width: scroller.scrollWidth};
346 },
347 setSize: function(width, height) {
348 function interpret(val) {
349 val = String(val);
350 return /^\d+$/.test(val) ? val + "px" : val;
351 }
352 if (width != null) wrapper.style.width = interpret(width);
353 if (height != null) scroller.style.height = interpret(height);
354 },
287
355
288 operation: function(f){return operation(f)();},
356 operation: function(f){return operation(f)();},
357 compoundChange: function(f){return compoundChange(f);},
289 refresh: function(){
358 refresh: function(){
290 updateDisplay(true);
359 updateDisplay(true, null, lastScrollTop);
291 if (scroller.scrollHeight > lastScrollPos)
360 if (scrollbar.scrollHeight > lastScrollTop)
292 scroller.scrollTop = lastScrollPos;
361 scrollbar.scrollTop = lastScrollTop;
293 },
362 },
294 getInputField: function(){return input;},
363 getInputField: function(){return input;},
295 getWrapperElement: function(){return wrapper;},
364 getWrapperElement: function(){return wrapper;},
@@ -310,10 +379,24 var CodeMirror = (function() {
310 splitLines(code), top, top);
379 splitLines(code), top, top);
311 updateInput = true;
380 updateInput = true;
312 }
381 }
313 function getValue(code) {
382 function getValue(lineSep) {
314 var text = [];
383 var text = [];
315 doc.iter(0, doc.size, function(line) { text.push(line.text); });
384 doc.iter(0, doc.size, function(line) { text.push(line.text); });
316 return text.join("\n");
385 return text.join(lineSep || "\n");
386 }
387
388 function onScroll(e) {
389 if (scroller.scrollTop) {
390 scrollbar.scrollTop += scroller.scrollTop;
391 scroller.scrollTop = 0;
392 }
393 if (lastScrollTop != scrollbar.scrollTop || lastScrollLeft != scroller.scrollLeft) {
394 lastScrollTop = scrollbar.scrollTop;
395 lastScrollLeft = scroller.scrollLeft;
396 updateDisplay([]);
397 if (options.fixedGutter) gutter.style.left = scroller.scrollLeft + "px";
398 if (options.onScroll) options.onScroll(instance);
399 }
317 }
400 }
318
401
319 function onMouseDown(e) {
402 function onMouseDown(e) {
@@ -334,10 +417,12 var CodeMirror = (function() {
334
417
335 switch (e_button(e)) {
418 switch (e_button(e)) {
336 case 3:
419 case 3:
337 if (gecko && !mac) onContextMenu(e);
420 if (gecko) onContextMenu(e);
338 return;
421 return;
339 case 2:
422 case 2:
340 if (start) setCursor(start.line, start.ch, true);
423 if (start) setCursor(start.line, start.ch, true);
424 setTimeout(focusInput, 20);
425 e_preventDefault(e);
341 return;
426 return;
342 }
427 }
343 // For button 1, if it was clicked inside the editor
428 // For button 1, if it was clicked inside the editor
@@ -347,44 +432,66 var CodeMirror = (function() {
347
432
348 if (!focused) onFocus();
433 if (!focused) onFocus();
349
434
350 var now = +new Date;
435 var now = +new Date, type = "single";
351 if (lastDoubleClick && lastDoubleClick.time > now - 400 && posEq(lastDoubleClick.pos, start)) {
436 if (lastDoubleClick && lastDoubleClick.time > now - 400 && posEq(lastDoubleClick.pos, start)) {
437 type = "triple";
352 e_preventDefault(e);
438 e_preventDefault(e);
353 setTimeout(focusInput, 20);
439 setTimeout(focusInput, 20);
354 return selectLine(start.line);
440 selectLine(start.line);
355 } else if (lastClick && lastClick.time > now - 400 && posEq(lastClick.pos, start)) {
441 } else if (lastClick && lastClick.time > now - 400 && posEq(lastClick.pos, start)) {
442 type = "double";
356 lastDoubleClick = {time: now, pos: start};
443 lastDoubleClick = {time: now, pos: start};
357 e_preventDefault(e);
444 e_preventDefault(e);
358 return selectWordAt(start);
445 var word = findWordAt(start);
446 setSelectionUser(word.from, word.to);
359 } else { lastClick = {time: now, pos: start}; }
447 } else { lastClick = {time: now, pos: start}; }
360
448
361 var last = start, going;
449 var last = start, going;
362 if (dragAndDrop && !options.readOnly && !posEq(sel.from, sel.to) &&
450 if (options.dragDrop && dragAndDrop && !options.readOnly && !posEq(sel.from, sel.to) &&
363 !posLess(start, sel.from) && !posLess(sel.to, start)) {
451 !posLess(start, sel.from) && !posLess(sel.to, start) && type == "single") {
364 // Let the drag handler handle this.
452 // Let the drag handler handle this.
365 if (webkit) lineSpace.draggable = true;
453 if (webkit) scroller.draggable = true;
366 var up = connect(targetDocument, "mouseup", operation(function(e2) {
454 function dragEnd(e2) {
367 if (webkit) lineSpace.draggable = false;
455 if (webkit) scroller.draggable = false;
368 draggingText = false;
456 draggingText = false;
369 up();
457 up(); drop();
370 if (Math.abs(e.clientX - e2.clientX) + Math.abs(e.clientY - e2.clientY) < 10) {
458 if (Math.abs(e.clientX - e2.clientX) + Math.abs(e.clientY - e2.clientY) < 10) {
371 e_preventDefault(e2);
459 e_preventDefault(e2);
372 setCursor(start.line, start.ch, true);
460 setCursor(start.line, start.ch, true);
373 focusInput();
461 focusInput();
374 }
462 }
375 }), true);
463 }
464 var up = connect(document, "mouseup", operation(dragEnd), true);
465 var drop = connect(scroller, "drop", operation(dragEnd), true);
376 draggingText = true;
466 draggingText = true;
467 // IE's approach to draggable
468 if (scroller.dragDrop) scroller.dragDrop();
377 return;
469 return;
378 }
470 }
379 e_preventDefault(e);
471 e_preventDefault(e);
380 setCursor(start.line, start.ch, true);
472 if (type == "single") setCursor(start.line, start.ch, true);
473
474 var startstart = sel.from, startend = sel.to;
475
476 function doSelect(cur) {
477 if (type == "single") {
478 setSelectionUser(start, cur);
479 } else if (type == "double") {
480 var word = findWordAt(cur);
481 if (posLess(cur, startstart)) setSelectionUser(word.from, startend);
482 else setSelectionUser(startstart, word.to);
483 } else if (type == "triple") {
484 if (posLess(cur, startstart)) setSelectionUser(startend, clipPos({line: cur.line, ch: 0}));
485 else setSelectionUser(startstart, clipPos({line: cur.line + 1, ch: 0}));
486 }
487 }
381
488
382 function extend(e) {
489 function extend(e) {
383 var cur = posFromMouse(e, true);
490 var cur = posFromMouse(e, true);
384 if (cur && !posEq(cur, last)) {
491 if (cur && !posEq(cur, last)) {
385 if (!focused) onFocus();
492 if (!focused) onFocus();
386 last = cur;
493 last = cur;
387 setSelectionUser(start, cur);
494 doSelect(cur);
388 updateInput = false;
495 updateInput = false;
389 var visible = visibleLines();
496 var visible = visibleLines();
390 if (cur.line >= visible.to || cur.line < visible.from)
497 if (cur.line >= visible.to || cur.line < visible.from)
@@ -392,31 +499,30 var CodeMirror = (function() {
392 }
499 }
393 }
500 }
394
501
395 var move = connect(targetDocument, "mousemove", operation(function(e) {
502 function done(e) {
396 clearTimeout(going);
397 e_preventDefault(e);
398 extend(e);
399 }), true);
400 var up = connect(targetDocument, "mouseup", operation(function(e) {
401 clearTimeout(going);
503 clearTimeout(going);
402 var cur = posFromMouse(e);
504 var cur = posFromMouse(e);
403 if (cur) setSelectionUser(start, cur);
505 if (cur) doSelect(cur);
404 e_preventDefault(e);
506 e_preventDefault(e);
405 focusInput();
507 focusInput();
406 updateInput = true;
508 updateInput = true;
407 move(); up();
509 move(); up();
510 }
511 var move = connect(document, "mousemove", operation(function(e) {
512 clearTimeout(going);
513 e_preventDefault(e);
514 if (!ie && !e_button(e)) done(e);
515 else extend(e);
408 }), true);
516 }), true);
517 var up = connect(document, "mouseup", operation(done), true);
409 }
518 }
410 function onDoubleClick(e) {
519 function onDoubleClick(e) {
411 for (var n = e_target(e); n != wrapper; n = n.parentNode)
520 for (var n = e_target(e); n != wrapper; n = n.parentNode)
412 if (n.parentNode == gutterText) return e_preventDefault(e);
521 if (n.parentNode == gutterText) return e_preventDefault(e);
413 var start = posFromMouse(e);
414 if (!start) return;
415 lastDoubleClick = {time: +new Date, pos: start};
416 e_preventDefault(e);
522 e_preventDefault(e);
417 selectWordAt(start);
418 }
523 }
419 function onDrop(e) {
524 function onDrop(e) {
525 if (options.onDragEvent && options.onDragEvent(instance, addStop(e))) return;
420 e.preventDefault();
526 e.preventDefault();
421 var pos = posFromMouse(e, true), files = e.dataTransfer.files;
527 var pos = posFromMouse(e, true), files = e.dataTransfer.files;
422 if (!pos || options.readOnly) return;
528 if (!pos || options.readOnly) return;
@@ -426,86 +532,124 var CodeMirror = (function() {
426 reader.onload = function() {
532 reader.onload = function() {
427 text[i] = reader.result;
533 text[i] = reader.result;
428 if (++read == n) {
534 if (++read == n) {
429 pos = clipPos(pos);
535 pos = clipPos(pos);
430 operation(function() {
536 operation(function() {
431 var end = replaceRange(text.join(""), pos, pos);
537 var end = replaceRange(text.join(""), pos, pos);
432 setSelectionUser(pos, end);
538 setSelectionUser(pos, end);
433 })();
539 })();
434 }
540 }
435 };
541 };
436 reader.readAsText(file);
542 reader.readAsText(file);
437 }
543 }
438 var n = files.length, text = Array(n), read = 0;
544 var n = files.length, text = Array(n), read = 0;
439 for (var i = 0; i < n; ++i) loadFile(files[i], i);
545 for (var i = 0; i < n; ++i) loadFile(files[i], i);
440 }
546 } else {
441 else {
547 // Don't do a replace if the drop happened inside of the selected text.
548 if (draggingText && !(posLess(pos, sel.from) || posLess(sel.to, pos))) return;
442 try {
549 try {
443 var text = e.dataTransfer.getData("Text");
550 var text = e.dataTransfer.getData("Text");
444 if (text) {
551 if (text) {
445 var curFrom = sel.from, curTo = sel.to;
552 compoundChange(function() {
446 setSelectionUser(pos, pos);
553 var curFrom = sel.from, curTo = sel.to;
447 if (draggingText) replaceRange("", curFrom, curTo);
554 setSelectionUser(pos, pos);
448 replaceSelection(text);
555 if (draggingText) replaceRange("", curFrom, curTo);
449 focusInput();
556 replaceSelection(text);
450 }
557 focusInput();
558 });
559 }
451 }
560 }
452 catch(e){}
561 catch(e){}
453 }
562 }
454 }
563 }
455 function onDragStart(e) {
564 function onDragStart(e) {
456 var txt = getSelection();
565 var txt = getSelection();
457 // This will reset escapeElement
458 htmlEscape(txt);
459 e.dataTransfer.setDragImage(escapeElement, 0, 0);
460 e.dataTransfer.setData("Text", txt);
566 e.dataTransfer.setData("Text", txt);
461 }
567
462 function handleKeyBinding(e) {
568 // Use dummy image instead of default browsers image.
463 var name = keyNames[e_prop(e, "keyCode")], next = keyMap[options.keyMap].auto, bound, dropShift;
569 if (gecko || chrome || opera) {
464 function handleNext() {
570 var img = document.createElement('img');
465 return next.call ? next.call(null, instance) : next;
571 img.scr = 'data:image/gif;base64,R0lGODdhAgACAIAAAAAAAP///ywAAAAAAgACAAACAoRRADs='; //1x1 image
466 }
572 e.dataTransfer.setDragImage(img, 0, 0);
467 if (name == null || e.altGraphKey) {
468 if (next) options.keyMap = handleNext();
469 return null;
470 }
471 if (e_prop(e, "altKey")) name = "Alt-" + name;
472 if (e_prop(e, "ctrlKey")) name = "Ctrl-" + name;
473 if (e_prop(e, "metaKey")) name = "Cmd-" + name;
474 if (e_prop(e, "shiftKey") &&
475 (bound = lookupKey("Shift-" + name, options.extraKeys, options.keyMap))) {
476 dropShift = true;
477 } else {
478 bound = lookupKey(name, options.extraKeys, options.keyMap);
479 }
573 }
574 }
575
576 function doHandleBinding(bound, dropShift) {
480 if (typeof bound == "string") {
577 if (typeof bound == "string") {
481 if (commands.propertyIsEnumerable(bound)) bound = commands[bound];
578 bound = commands[bound];
482 else bound = null;
579 if (!bound) return false;
483 }
580 }
484 if (next && (bound || !isModifierKey(e))) options.keyMap = handleNext();
485 if (!bound) return false;
486 var prevShift = shiftSelecting;
581 var prevShift = shiftSelecting;
487 try {
582 try {
488 if (options.readOnly) suppressEdits = true;
583 if (options.readOnly) suppressEdits = true;
489 if (dropShift) shiftSelecting = null;
584 if (dropShift) shiftSelecting = null;
490 bound(instance);
585 bound(instance);
586 } catch(e) {
587 if (e != Pass) throw e;
588 return false;
491 } finally {
589 } finally {
492 shiftSelecting = prevShift;
590 shiftSelecting = prevShift;
493 suppressEdits = false;
591 suppressEdits = false;
494 }
592 }
495 e_preventDefault(e);
496 return true;
593 return true;
497 }
594 }
498 var lastStoppedKey = null;
595 function handleKeyBinding(e) {
596 // Handle auto keymap transitions
597 var startMap = getKeyMap(options.keyMap), next = startMap.auto;
598 clearTimeout(maybeTransition);
599 if (next && !isModifierKey(e)) maybeTransition = setTimeout(function() {
600 if (getKeyMap(options.keyMap) == startMap) {
601 options.keyMap = (next.call ? next.call(null, instance) : next);
602 }
603 }, 50);
604
605 var name = keyNames[e_prop(e, "keyCode")], handled = false;
606 if (name == null || e.altGraphKey) return false;
607 if (e_prop(e, "altKey")) name = "Alt-" + name;
608 if (e_prop(e, "ctrlKey")) name = "Ctrl-" + name;
609 if (e_prop(e, "metaKey")) name = "Cmd-" + name;
610
611 var stopped = false;
612 function stop() { stopped = true; }
613
614 if (e_prop(e, "shiftKey")) {
615 handled = lookupKey("Shift-" + name, options.extraKeys, options.keyMap,
616 function(b) {return doHandleBinding(b, true);}, stop)
617 || lookupKey(name, options.extraKeys, options.keyMap, function(b) {
618 if (typeof b == "string" && /^go[A-Z]/.test(b)) return doHandleBinding(b);
619 }, stop);
620 } else {
621 handled = lookupKey(name, options.extraKeys, options.keyMap, doHandleBinding, stop);
622 }
623 if (stopped) handled = false;
624 if (handled) {
625 e_preventDefault(e);
626 restartBlink();
627 if (ie) { e.oldKeyCode = e.keyCode; e.keyCode = 0; }
628 }
629 return handled;
630 }
631 function handleCharBinding(e, ch) {
632 var handled = lookupKey("'" + ch + "'", options.extraKeys,
633 options.keyMap, function(b) { return doHandleBinding(b, true); });
634 if (handled) {
635 e_preventDefault(e);
636 restartBlink();
637 }
638 return handled;
639 }
640
641 var lastStoppedKey = null, maybeTransition;
499 function onKeyDown(e) {
642 function onKeyDown(e) {
500 if (!focused) onFocus();
643 if (!focused) onFocus();
501 if (ie && e.keyCode == 27) { e.returnValue = false; }
644 if (ie && e.keyCode == 27) { e.returnValue = false; }
645 if (pollingFast) { if (readInput()) pollingFast = false; }
502 if (options.onKeyEvent && options.onKeyEvent(instance, addStop(e))) return;
646 if (options.onKeyEvent && options.onKeyEvent(instance, addStop(e))) return;
503 var code = e_prop(e, "keyCode");
647 var code = e_prop(e, "keyCode");
504 // IE does strange things with escape.
648 // IE does strange things with escape.
505 setShift(code == 16 || e_prop(e, "shiftKey"));
649 setShift(code == 16 || e_prop(e, "shiftKey"));
506 // First give onKeyEvent option a chance to handle this.
650 // First give onKeyEvent option a chance to handle this.
507 var handled = handleKeyBinding(e);
651 var handled = handleKeyBinding(e);
508 if (window.opera) {
652 if (opera) {
509 lastStoppedKey = handled ? code : null;
653 lastStoppedKey = handled ? code : null;
510 // Opera has no cut event... we try to at least catch the key combo
654 // Opera has no cut event... we try to at least catch the key combo
511 if (!handled && code == 88 && e_prop(e, mac ? "metaKey" : "ctrlKey"))
655 if (!handled && code == 88 && e_prop(e, mac ? "metaKey" : "ctrlKey"))
@@ -513,15 +657,17 var CodeMirror = (function() {
513 }
657 }
514 }
658 }
515 function onKeyPress(e) {
659 function onKeyPress(e) {
660 if (pollingFast) readInput();
516 if (options.onKeyEvent && options.onKeyEvent(instance, addStop(e))) return;
661 if (options.onKeyEvent && options.onKeyEvent(instance, addStop(e))) return;
517 var keyCode = e_prop(e, "keyCode"), charCode = e_prop(e, "charCode");
662 var keyCode = e_prop(e, "keyCode"), charCode = e_prop(e, "charCode");
518 if (window.opera && keyCode == lastStoppedKey) {lastStoppedKey = null; e_preventDefault(e); return;}
663 if (opera && keyCode == lastStoppedKey) {lastStoppedKey = null; e_preventDefault(e); return;}
519 if (window.opera && !e.which && handleKeyBinding(e)) return;
664 if (((opera && (!e.which || e.which < 10)) || khtml) && handleKeyBinding(e)) return;
665 var ch = String.fromCharCode(charCode == null ? keyCode : charCode);
520 if (options.electricChars && mode.electricChars && options.smartIndent && !options.readOnly) {
666 if (options.electricChars && mode.electricChars && options.smartIndent && !options.readOnly) {
521 var ch = String.fromCharCode(charCode == null ? keyCode : charCode);
522 if (mode.electricChars.indexOf(ch) > -1)
667 if (mode.electricChars.indexOf(ch) > -1)
523 setTimeout(operation(function() {indentLine(sel.to.line, "smart");}), 75);
668 setTimeout(operation(function() {indentLine(sel.to.line, "smart");}), 75);
524 }
669 }
670 if (handleCharBinding(e, ch)) return;
525 fastPoll();
671 fastPoll();
526 }
672 }
527 function onKeyUp(e) {
673 function onKeyUp(e) {
@@ -534,8 +680,8 var CodeMirror = (function() {
534 if (!focused) {
680 if (!focused) {
535 if (options.onFocus) options.onFocus(instance);
681 if (options.onFocus) options.onFocus(instance);
536 focused = true;
682 focused = true;
537 if (wrapper.className.search(/\bCodeMirror-focused\b/) == -1)
683 if (scroller.className.search(/\bCodeMirror-focused\b/) == -1)
538 wrapper.className += " CodeMirror-focused";
684 scroller.className += " CodeMirror-focused";
539 if (!leaveInputAlone) resetInput(true);
685 if (!leaveInputAlone) resetInput(true);
540 }
686 }
541 slowPoll();
687 slowPoll();
@@ -549,12 +695,48 var CodeMirror = (function() {
549 operation(function(){
695 operation(function(){
550 if (bracketHighlighted) { bracketHighlighted(); bracketHighlighted = null; }
696 if (bracketHighlighted) { bracketHighlighted(); bracketHighlighted = null; }
551 })();
697 })();
552 wrapper.className = wrapper.className.replace(" CodeMirror-focused", "");
698 scroller.className = scroller.className.replace(" CodeMirror-focused", "");
553 }
699 }
554 clearInterval(blinker);
700 clearInterval(blinker);
555 setTimeout(function() {if (!focused) shiftSelecting = null;}, 150);
701 setTimeout(function() {if (!focused) shiftSelecting = null;}, 150);
556 }
702 }
557
703
704 function chopDelta(delta) {
705 // Make sure we always scroll a little bit for any nonzero delta.
706 if (delta > 0.0 && delta < 1.0) return 1;
707 else if (delta > -1.0 && delta < 0.0) return -1;
708 else return Math.round(delta);
709 }
710
711 function onMouseWheel(e) {
712 var deltaX = 0, deltaY = 0;
713 if (e.type == "DOMMouseScroll") { // Firefox
714 var delta = -e.detail * 8.0;
715 if (e.axis == e.HORIZONTAL_AXIS) deltaX = delta;
716 else if (e.axis == e.VERTICAL_AXIS) deltaY = delta;
717 } else if (e.wheelDeltaX !== undefined && e.wheelDeltaY !== undefined) { // WebKit
718 deltaX = e.wheelDeltaX / 3.0;
719 deltaY = e.wheelDeltaY / 3.0;
720 } else if (e.wheelDelta !== undefined) { // IE or Opera
721 deltaY = e.wheelDelta / 3.0;
722 }
723
724 var scrolled = false;
725 deltaX = chopDelta(deltaX);
726 deltaY = chopDelta(deltaY);
727 if ((deltaX > 0 && scroller.scrollLeft > 0) ||
728 (deltaX < 0 && scroller.scrollLeft + scroller.clientWidth < scroller.scrollWidth)) {
729 scroller.scrollLeft -= deltaX;
730 scrolled = true;
731 }
732 if ((deltaY > 0 && scrollbar.scrollTop > 0) ||
733 (deltaY < 0 && scrollbar.scrollTop + scrollbar.clientHeight < scrollbar.scrollHeight)) {
734 scrollbar.scrollTop -= deltaY;
735 scrolled = true;
736 }
737 if (scrolled) e_stop(e);
738 }
739
558 // Replace the range from from to to by the strings in newText.
740 // Replace the range from from to to by the strings in newText.
559 // Afterwards, set the selection to selFrom, selTo.
741 // Afterwards, set the selection to selFrom, selTo.
560 function updateLines(from, to, newText, selFrom, selTo) {
742 function updateLines(from, to, newText, selFrom, selTo) {
@@ -567,29 +749,30 var CodeMirror = (function() {
567 }
749 }
568 updateLinesNoUndo(from, to, newText, selFrom, selTo);
750 updateLinesNoUndo(from, to, newText, selFrom, selTo);
569 }
751 }
570 function unredoHelper(from, to, dir) {
752 function unredoHelper(from, to) {
571 var set = from.pop(), len = set ? set.length : 0, out = [];
753 if (!from.length) return;
572 for (var i = dir > 0 ? 0 : len - 1, e = dir > 0 ? len : -1; i != e; i += dir) {
754 var set = from.pop(), out = [];
755 for (var i = set.length - 1; i >= 0; i -= 1) {
573 var change = set[i];
756 var change = set[i];
574 var replaced = [], end = change.start + change.added;
757 var replaced = [], end = change.start + change.added;
575 doc.iter(change.start, end, function(line) { replaced.push(line.text); });
758 doc.iter(change.start, end, function(line) { replaced.push(line.text); });
576 out.push({start: change.start, added: change.old.length, old: replaced});
759 out.push({start: change.start, added: change.old.length, old: replaced});
577 var pos = clipPos({line: change.start + change.old.length - 1,
760 var pos = {line: change.start + change.old.length - 1,
578 ch: editEnd(replaced[replaced.length-1], change.old[change.old.length-1])});
761 ch: editEnd(replaced[replaced.length-1], change.old[change.old.length-1])};
579 updateLinesNoUndo({line: change.start, ch: 0}, {line: end - 1, ch: getLine(end-1).text.length}, change.old, pos, pos);
762 updateLinesNoUndo({line: change.start, ch: 0}, {line: end - 1, ch: getLine(end-1).text.length}, change.old, pos, pos);
580 }
763 }
581 updateInput = true;
764 updateInput = true;
582 to.push(out);
765 to.push(out);
583 }
766 }
584 function undo() {unredoHelper(history.done, history.undone, -1);}
767 function undo() {unredoHelper(history.done, history.undone);}
585 function redo() {unredoHelper(history.undone, history.done, 1);}
768 function redo() {unredoHelper(history.undone, history.done);}
586
769
587 function updateLinesNoUndo(from, to, newText, selFrom, selTo) {
770 function updateLinesNoUndo(from, to, newText, selFrom, selTo) {
588 if (suppressEdits) return;
771 if (suppressEdits) return;
589 var recomputeMaxLength = false, maxLineLength = maxLine.length;
772 var recomputeMaxLength = false, maxLineLength = maxLine.length;
590 if (!options.lineWrapping)
773 if (!options.lineWrapping)
591 doc.iter(from.line, to.line, function(line) {
774 doc.iter(from.line, to.line + 1, function(line) {
592 if (line.text.length == maxLineLength) {recomputeMaxLength = true; return true;}
775 if (!line.hidden && line.text.length == maxLineLength) {recomputeMaxLength = true; return true;}
593 });
776 });
594 if (from.line != to.line || newText.length > 1) gutterDirty = true;
777 if (from.line != to.line || newText.length > 1) gutterDirty = true;
595
778
@@ -636,29 +819,21 var CodeMirror = (function() {
636 doc.insert(from.line + 1, added);
819 doc.insert(from.line + 1, added);
637 }
820 }
638 if (options.lineWrapping) {
821 if (options.lineWrapping) {
639 var perLine = scroller.clientWidth / charWidth() - 3;
822 var perLine = Math.max(5, scroller.clientWidth / charWidth() - 3);
640 doc.iter(from.line, from.line + newText.length, function(line) {
823 doc.iter(from.line, from.line + newText.length, function(line) {
641 if (line.hidden) return;
824 if (line.hidden) return;
642 var guess = Math.ceil(line.text.length / perLine) || 1;
825 var guess = Math.ceil(line.text.length / perLine) || 1;
643 if (guess != line.height) updateLineHeight(line, guess);
826 if (guess != line.height) updateLineHeight(line, guess);
644 });
827 });
645 } else {
828 } else {
646 doc.iter(from.line, i + newText.length, function(line) {
829 doc.iter(from.line, from.line + newText.length, function(line) {
647 var l = line.text;
830 var l = line.text;
648 if (l.length > maxLineLength) {
831 if (!line.hidden && l.length > maxLineLength) {
649 maxLine = l; maxLineLength = l.length; maxWidth = null;
832 maxLine = l; maxLineLength = l.length; maxLineChanged = true;
650 recomputeMaxLength = false;
833 recomputeMaxLength = false;
651 }
834 }
652 });
835 });
653 if (recomputeMaxLength) {
836 if (recomputeMaxLength) updateMaxLine = true;
654 maxLineLength = 0; maxLine = ""; maxWidth = null;
655 doc.iter(0, doc.size, function(line) {
656 var l = line.text;
657 if (l.length > maxLineLength) {
658 maxLineLength = l.length; maxLine = l;
659 }
660 });
661 }
662 }
837 }
663
838
664 // Add these lines to the work array, so that they will be
839 // Add these lines to the work array, so that they will be
@@ -684,11 +859,55 var CodeMirror = (function() {
684
859
685 // Update the selection
860 // Update the selection
686 function updateLine(n) {return n <= Math.min(to.line, to.line + lendiff) ? n : n + lendiff;}
861 function updateLine(n) {return n <= Math.min(to.line, to.line + lendiff) ? n : n + lendiff;}
687 setSelection(selFrom, selTo, updateLine(sel.from.line), updateLine(sel.to.line));
862 setSelection(clipPos(selFrom), clipPos(selTo),
863 updateLine(sel.from.line), updateLine(sel.to.line));
864 }
865
866 function needsScrollbar() {
867 var realHeight = doc.height * textHeight() + 2 * paddingTop();
868 return realHeight - 1 > scroller.offsetHeight ? realHeight : false;
869 }
870
871 function updateVerticalScroll(scrollTop) {
872 var scrollHeight = needsScrollbar();
873 scrollbar.style.display = scrollHeight ? "block" : "none";
874 if (scrollHeight) {
875 scrollbarInner.style.height = scrollHeight + "px";
876 scrollbar.style.height = scroller.offsetHeight + "px";
877 if (scrollTop != null) scrollbar.scrollTop = scrollTop;
878 }
879 // Position the mover div to align with the current virtual scroll position
880 mover.style.top = (displayOffset * textHeight() - scrollbar.scrollTop) + "px";
881 }
882
883 // On Mac OS X Lion and up, detect whether the mouse is plugged in by measuring
884 // the width of a div with a scrollbar in it. If the width is <= 1, then
885 // the mouse isn't plugged in and scrollbars should overlap the content.
886 function overlapScrollbars() {
887 var tmpSb = document.createElement('div'),
888 tmpSbInner = document.createElement('div');
889 tmpSb.className = "CodeMirror-scrollbar";
890 tmpSb.style.cssText = "position: absolute; left: -9999px; height: 100px;";
891 tmpSbInner.className = "CodeMirror-scrollbar-inner";
892 tmpSbInner.style.height = "200px";
893 tmpSb.appendChild(tmpSbInner);
894
895 document.body.appendChild(tmpSb);
896 var result = (tmpSb.offsetWidth <= 1);
897 document.body.removeChild(tmpSb);
898 return result;
899 }
688
900
689 // Make sure the scroll-size div has the correct height.
901 function computeMaxLength() {
690 if (scroller.clientHeight)
902 var maxLineLength = 0;
691 code.style.height = (doc.height * textHeight() + 2 * paddingTop()) + "px";
903 maxLine = ""; maxLineChanged = true;
904 doc.iter(0, doc.size, function(line) {
905 var l = line.text;
906 if (!line.hidden && l.length > maxLineLength) {
907 maxLineLength = l.length; maxLine = l;
908 }
909 });
910 updateMaxLine = false;
692 }
911 }
693
912
694 function replaceRange(code, from, to) {
913 function replaceRange(code, from, to) {
@@ -724,16 +943,16 var CodeMirror = (function() {
724 updateLines(from, to, code, newSel.from, newSel.to);
943 updateLines(from, to, code, newSel.from, newSel.to);
725 }
944 }
726
945
727 function getRange(from, to) {
946 function getRange(from, to, lineSep) {
728 var l1 = from.line, l2 = to.line;
947 var l1 = from.line, l2 = to.line;
729 if (l1 == l2) return getLine(l1).text.slice(from.ch, to.ch);
948 if (l1 == l2) return getLine(l1).text.slice(from.ch, to.ch);
730 var code = [getLine(l1).text.slice(from.ch)];
949 var code = [getLine(l1).text.slice(from.ch)];
731 doc.iter(l1 + 1, l2, function(line) { code.push(line.text); });
950 doc.iter(l1 + 1, l2, function(line) { code.push(line.text); });
732 code.push(getLine(l2).text.slice(0, to.ch));
951 code.push(getLine(l2).text.slice(0, to.ch));
733 return code.join("\n");
952 return code.join(lineSep || "\n");
734 }
953 }
735 function getSelection() {
954 function getSelection(lineSep) {
736 return getRange(sel.from, sel.to);
955 return getRange(sel.from, sel.to, lineSep);
737 }
956 }
738
957
739 var pollingFast = false; // Ensures slowPoll doesn't cancel fastPoll
958 var pollingFast = false; // Ensures slowPoll doesn't cancel fastPoll
@@ -777,7 +996,8 var CodeMirror = (function() {
777 else if (overwrite && posEq(sel.from, sel.to))
996 else if (overwrite && posEq(sel.from, sel.to))
778 sel.to = {line: sel.to.line, ch: Math.min(getLine(sel.to.line).text.length, sel.to.ch + (text.length - same))};
997 sel.to = {line: sel.to.line, ch: Math.min(getLine(sel.to.line).text.length, sel.to.ch + (text.length - same))};
779 replaceSelection(text.slice(same), "end");
998 replaceSelection(text.slice(same), "end");
780 prevInput = text;
999 if (text.length > 1000) { input.value = prevInput = ""; }
1000 else prevInput = text;
781 return true;
1001 return true;
782 }
1002 }
783 function resetInput(user) {
1003 function resetInput(user) {
@@ -793,60 +1013,72 var CodeMirror = (function() {
793 }
1013 }
794
1014
795 function scrollEditorIntoView() {
1015 function scrollEditorIntoView() {
796 if (!cursor.getBoundingClientRect) return;
797 var rect = cursor.getBoundingClientRect();
1016 var rect = cursor.getBoundingClientRect();
798 // IE returns bogus coordinates when the instance sits inside of an iframe and the cursor is hidden
1017 // IE returns bogus coordinates when the instance sits inside of an iframe and the cursor is hidden
799 if (ie && rect.top == rect.bottom) return;
1018 if (ie && rect.top == rect.bottom) return;
800 var winH = window.innerHeight || Math.max(document.body.offsetHeight, document.documentElement.offsetHeight);
1019 var winH = window.innerHeight || Math.max(document.body.offsetHeight, document.documentElement.offsetHeight);
801 if (rect.top < 0 || rect.bottom > winH) cursor.scrollIntoView();
1020 if (rect.top < 0 || rect.bottom > winH) scrollCursorIntoView();
802 }
1021 }
803 function scrollCursorIntoView() {
1022 function scrollCursorIntoView() {
1023 var coords = calculateCursorCoords();
1024 return scrollIntoView(coords.x, coords.y, coords.x, coords.yBot);
1025 }
1026 function calculateCursorCoords() {
804 var cursor = localCoords(sel.inverted ? sel.from : sel.to);
1027 var cursor = localCoords(sel.inverted ? sel.from : sel.to);
805 var x = options.lineWrapping ? Math.min(cursor.x, lineSpace.offsetWidth) : cursor.x;
1028 var x = options.lineWrapping ? Math.min(cursor.x, lineSpace.offsetWidth) : cursor.x;
806 return scrollIntoView(x, cursor.y, x, cursor.yBot);
1029 return {x: x, y: cursor.y, yBot: cursor.yBot};
807 }
1030 }
808 function scrollIntoView(x1, y1, x2, y2) {
1031 function scrollIntoView(x1, y1, x2, y2) {
809 var pl = paddingLeft(), pt = paddingTop(), lh = textHeight();
1032 var scrollPos = calculateScrollPos(x1, y1, x2, y2), scrolled = false;
1033 if (scrollPos.scrollLeft != null) {scroller.scrollLeft = scrollPos.scrollLeft; scrolled = true;}
1034 if (scrollPos.scrollTop != null) {scrollbar.scrollTop = scrollPos.scrollTop; scrolled = true;}
1035 if (scrolled && options.onScroll) options.onScroll(instance);
1036 }
1037 function calculateScrollPos(x1, y1, x2, y2) {
1038 var pl = paddingLeft(), pt = paddingTop();
810 y1 += pt; y2 += pt; x1 += pl; x2 += pl;
1039 y1 += pt; y2 += pt; x1 += pl; x2 += pl;
811 var screen = scroller.clientHeight, screentop = scroller.scrollTop, scrolled = false, result = true;
1040 var screen = scroller.clientHeight, screentop = scrollbar.scrollTop, result = {};
812 if (y1 < screentop) {scroller.scrollTop = Math.max(0, y1 - 2*lh); scrolled = true;}
1041 var docBottom = scroller.scrollHeight;
813 else if (y2 > screentop + screen) {scroller.scrollTop = y2 + lh - screen; scrolled = true;}
1042 var atTop = y1 < pt + 10, atBottom = y2 + pt > docBottom - 10;;
1043 if (y1 < screentop) result.scrollTop = atTop ? 0 : Math.max(0, y1);
1044 else if (y2 > screentop + screen) result.scrollTop = (atBottom ? docBottom : y2) - screen;
814
1045
815 var screenw = scroller.clientWidth, screenleft = scroller.scrollLeft;
1046 var screenw = scroller.clientWidth, screenleft = scroller.scrollLeft;
816 var gutterw = options.fixedGutter ? gutter.clientWidth : 0;
1047 var gutterw = options.fixedGutter ? gutter.clientWidth : 0;
817 if (x1 < screenleft + gutterw) {
1048 var atLeft = x1 < gutterw + pl + 10;
818 if (x1 < 50) x1 = 0;
1049 if (x1 < screenleft + gutterw || atLeft) {
819 scroller.scrollLeft = Math.max(0, x1 - 10 - gutterw);
1050 if (atLeft) x1 = 0;
820 scrolled = true;
1051 result.scrollLeft = Math.max(0, x1 - 10 - gutterw);
821 }
1052 } else if (x2 > screenw + screenleft - 3) {
822 else if (x2 > screenw + screenleft - 3) {
1053 result.scrollLeft = x2 + 10 - screenw;
823 scroller.scrollLeft = x2 + 10 - screenw;
824 scrolled = true;
825 if (x2 > code.clientWidth) result = false;
826 }
1054 }
827 if (scrolled && options.onScroll) options.onScroll(instance);
828 return result;
1055 return result;
829 }
1056 }
830
1057
831 function visibleLines() {
1058 function visibleLines(scrollTop) {
832 var lh = textHeight(), top = scroller.scrollTop - paddingTop();
1059 var lh = textHeight(), top = (scrollTop != null ? scrollTop : scrollbar.scrollTop) - paddingTop();
833 var from_height = Math.max(0, Math.floor(top / lh));
1060 var fromHeight = Math.max(0, Math.floor(top / lh));
834 var to_height = Math.ceil((top + scroller.clientHeight) / lh);
1061 var toHeight = Math.ceil((top + scroller.clientHeight) / lh);
835 return {from: lineAtHeight(doc, from_height),
1062 return {from: lineAtHeight(doc, fromHeight),
836 to: lineAtHeight(doc, to_height)};
1063 to: lineAtHeight(doc, toHeight)};
837 }
1064 }
838 // Uses a set of changes plus the current scroll position to
1065 // Uses a set of changes plus the current scroll position to
839 // determine which DOM updates have to be made, and makes the
1066 // determine which DOM updates have to be made, and makes the
840 // updates.
1067 // updates.
841 function updateDisplay(changes, suppressCallback) {
1068 function updateDisplay(changes, suppressCallback, scrollTop) {
842 if (!scroller.clientWidth) {
1069 if (!scroller.clientWidth) {
843 showingFrom = showingTo = displayOffset = 0;
1070 showingFrom = showingTo = displayOffset = 0;
844 return;
1071 return;
845 }
1072 }
846 // Compute the new visible window
1073 // Compute the new visible window
847 var visible = visibleLines();
1074 // If scrollTop is specified, use that to determine which lines
1075 // to render instead of the current scrollbar position.
1076 var visible = visibleLines(scrollTop);
848 // Bail out if the visible area is already rendered and nothing changed.
1077 // Bail out if the visible area is already rendered and nothing changed.
849 if (changes !== true && changes.length == 0 && visible.from > showingFrom && visible.to < showingTo) return;
1078 if (changes !== true && changes.length == 0 && visible.from > showingFrom && visible.to < showingTo) {
1079 updateVerticalScroll(scrollTop);
1080 return;
1081 }
850 var from = Math.max(visible.from - 100, 0), to = Math.min(doc.size, visible.to + 100);
1082 var from = Math.max(visible.from - 100, 0), to = Math.min(doc.size, visible.to + 100);
851 if (showingFrom < from && from - showingFrom < 20) from = showingFrom;
1083 if (showingFrom < from && from - showingFrom < 20) from = showingFrom;
852 if (showingTo > to && showingTo - to < 20) to = Math.min(doc.size, showingTo);
1084 if (showingTo > to && showingTo - to < 20) to = Math.min(doc.size, showingTo);
@@ -864,7 +1096,10 var CodeMirror = (function() {
864 if (range.from >= range.to) intact.splice(i--, 1);
1096 if (range.from >= range.to) intact.splice(i--, 1);
865 else intactLines += range.to - range.from;
1097 else intactLines += range.to - range.from;
866 }
1098 }
867 if (intactLines == to - from) return;
1099 if (intactLines == to - from && from == showingFrom && to == showingTo) {
1100 updateVerticalScroll(scrollTop);
1101 return;
1102 }
868 intact.sort(function(a, b) {return a.domStart - b.domStart;});
1103 intact.sort(function(a, b) {return a.domStart - b.domStart;});
869
1104
870 var th = textHeight(), gutterDisplay = gutter.style.display;
1105 var th = textHeight(), gutterDisplay = gutter.style.display;
@@ -872,17 +1107,12 var CodeMirror = (function() {
872 patchDisplay(from, to, intact);
1107 patchDisplay(from, to, intact);
873 lineDiv.style.display = gutter.style.display = "";
1108 lineDiv.style.display = gutter.style.display = "";
874
1109
875 // Position the mover div to align with the lines it's supposed
876 // to be showing (which will cover the visible display)
877 var different = from != showingFrom || to != showingTo || lastSizeC != scroller.clientHeight + th;
1110 var different = from != showingFrom || to != showingTo || lastSizeC != scroller.clientHeight + th;
878 // This is just a bogus formula that detects when the editor is
1111 // This is just a bogus formula that detects when the editor is
879 // resized or the font size changes.
1112 // resized or the font size changes.
880 if (different) lastSizeC = scroller.clientHeight + th;
1113 if (different) lastSizeC = scroller.clientHeight + th;
881 showingFrom = from; showingTo = to;
1114 showingFrom = from; showingTo = to;
882 displayOffset = heightAtLine(doc, from);
1115 displayOffset = heightAtLine(doc, from);
883 mover.style.top = (displayOffset * th) + "px";
884 if (scroller.clientHeight)
885 code.style.height = (doc.height * th + 2 * paddingTop()) + "px";
886
1116
887 // Since this is all rather error prone, it is honoured with the
1117 // Since this is all rather error prone, it is honoured with the
888 // only assertion in the whole file.
1118 // only assertion in the whole file.
@@ -890,8 +1120,7 var CodeMirror = (function() {
890 throw new Error("BAD PATCH! " + JSON.stringify(intact) + " size=" + (showingTo - showingFrom) +
1120 throw new Error("BAD PATCH! " + JSON.stringify(intact) + " size=" + (showingTo - showingFrom) +
891 " nodes=" + lineDiv.childNodes.length);
1121 " nodes=" + lineDiv.childNodes.length);
892
1122
893 if (options.lineWrapping) {
1123 function checkHeights() {
894 maxWidth = scroller.clientWidth;
895 var curNode = lineDiv.firstChild, heightChanged = false;
1124 var curNode = lineDiv.firstChild, heightChanged = false;
896 doc.iter(showingFrom, showingTo, function(line) {
1125 doc.iter(showingFrom, showingTo, function(line) {
897 if (!line.hidden) {
1126 if (!line.hidden) {
@@ -903,21 +1132,26 var CodeMirror = (function() {
903 }
1132 }
904 curNode = curNode.nextSibling;
1133 curNode = curNode.nextSibling;
905 });
1134 });
906 if (heightChanged)
1135 return heightChanged;
907 code.style.height = (doc.height * th + 2 * paddingTop()) + "px";
1136 }
908 } else {
1137
909 if (maxWidth == null) maxWidth = stringWidth(maxLine);
1138 if (options.lineWrapping) {
910 if (maxWidth > scroller.clientWidth) {
1139 checkHeights();
911 lineSpace.style.width = maxWidth + "px";
1140 var scrollHeight = needsScrollbar();
912 // Needed to prevent odd wrapping/hiding of widgets placed in here.
1141 var shouldHaveScrollbar = scrollHeight ? "block" : "none";
913 code.style.width = "";
1142 if (scrollbar.style.display != shouldHaveScrollbar) {
914 code.style.width = scroller.scrollWidth + "px";
1143 scrollbar.style.display = shouldHaveScrollbar;
915 } else {
1144 if (scrollHeight) scrollbarInner.style.height = scrollHeight + "px";
916 lineSpace.style.width = code.style.width = "";
1145 checkHeights();
917 }
1146 }
918 }
1147 }
1148
919 gutter.style.display = gutterDisplay;
1149 gutter.style.display = gutterDisplay;
920 if (different || gutterDirty) updateGutter();
1150 if (different || gutterDirty) {
1151 // If the gutter grew in size, re-check heights. If those changed, re-draw gutter.
1152 updateGutter() && options.lineWrapping && checkHeights() && updateGutter();
1153 }
1154 updateVerticalScroll(scrollTop);
921 updateSelection();
1155 updateSelection();
922 if (!suppressCallback && options.onUpdate) options.onUpdate(instance);
1156 if (!suppressCallback && options.onUpdate) options.onUpdate(instance);
923 return true;
1157 return true;
@@ -965,16 +1199,17 var CodeMirror = (function() {
965 }
1199 }
966 // This pass fills in the lines that actually changed.
1200 // This pass fills in the lines that actually changed.
967 var nextIntact = intact.shift(), curNode = lineDiv.firstChild, j = from;
1201 var nextIntact = intact.shift(), curNode = lineDiv.firstChild, j = from;
968 var scratch = targetDocument.createElement("div"), newElt;
1202 var scratch = document.createElement("div");
969 doc.iter(from, to, function(line) {
1203 doc.iter(from, to, function(line) {
970 if (nextIntact && nextIntact.to == j) nextIntact = intact.shift();
1204 if (nextIntact && nextIntact.to == j) nextIntact = intact.shift();
971 if (!nextIntact || nextIntact.from > j) {
1205 if (!nextIntact || nextIntact.from > j) {
972 if (line.hidden) var html = scratch.innerHTML = "<pre></pre>";
1206 if (line.hidden) var html = scratch.innerHTML = "<pre></pre>";
973 else {
1207 else {
974 var html = '<pre>' + line.getHTML(tabText) + '</pre>';
1208 var html = '<pre' + (line.className ? ' class="' + line.className + '"' : '') + '>'
1209 + line.getHTML(makeTab) + '</pre>';
975 // Kludge to make sure the styled element lies behind the selection (by z-index)
1210 // Kludge to make sure the styled element lies behind the selection (by z-index)
976 if (line.className)
1211 if (line.bgClassName)
977 html = '<div style="position: relative"><pre class="' + line.className +
1212 html = '<div style="position: relative"><pre class="' + line.bgClassName +
978 '" style="position: absolute; left: 0; right: 0; top: 0; bottom: 0; z-index: -2">&#160;</pre>' + html + "</div>";
1213 '" style="position: absolute; left: 0; right: 0; top: 0; bottom: 0; z-index: -2">&#160;</pre>' + html + "</div>";
979 }
1214 }
980 scratch.innerHTML = html;
1215 scratch.innerHTML = html;
@@ -990,13 +1225,13 var CodeMirror = (function() {
990 if (!options.gutter && !options.lineNumbers) return;
1225 if (!options.gutter && !options.lineNumbers) return;
991 var hText = mover.offsetHeight, hEditor = scroller.clientHeight;
1226 var hText = mover.offsetHeight, hEditor = scroller.clientHeight;
992 gutter.style.height = (hText - hEditor < 2 ? hEditor : hText) + "px";
1227 gutter.style.height = (hText - hEditor < 2 ? hEditor : hText) + "px";
993 var html = [], i = showingFrom;
1228 var html = [], i = showingFrom, normalNode;
994 doc.iter(showingFrom, Math.max(showingTo, showingFrom + 1), function(line) {
1229 doc.iter(showingFrom, Math.max(showingTo, showingFrom + 1), function(line) {
995 if (line.hidden) {
1230 if (line.hidden) {
996 html.push("<pre></pre>");
1231 html.push("<pre></pre>");
997 } else {
1232 } else {
998 var marker = line.gutterMarker;
1233 var marker = line.gutterMarker;
999 var text = options.lineNumbers ? i + options.firstLineNumber : null;
1234 var text = options.lineNumbers ? options.lineNumberFormatter(i + options.firstLineNumber) : null;
1000 if (marker && marker.text)
1235 if (marker && marker.text)
1001 text = marker.text.replace("%N%", text != null ? text : "");
1236 text = marker.text.replace("%N%", text != null ? text : "");
1002 else if (text == null)
1237 else if (text == null)
@@ -1004,17 +1239,24 var CodeMirror = (function() {
1004 html.push((marker && marker.style ? '<pre class="' + marker.style + '">' : "<pre>"), text);
1239 html.push((marker && marker.style ? '<pre class="' + marker.style + '">' : "<pre>"), text);
1005 for (var j = 1; j < line.height; ++j) html.push("<br/>&#160;");
1240 for (var j = 1; j < line.height; ++j) html.push("<br/>&#160;");
1006 html.push("</pre>");
1241 html.push("</pre>");
1242 if (!marker) normalNode = i;
1007 }
1243 }
1008 ++i;
1244 ++i;
1009 });
1245 });
1010 gutter.style.display = "none";
1246 gutter.style.display = "none";
1011 gutterText.innerHTML = html.join("");
1247 gutterText.innerHTML = html.join("");
1012 var minwidth = String(doc.size).length, firstNode = gutterText.firstChild, val = eltText(firstNode), pad = "";
1248 // Make sure scrolling doesn't cause number gutter size to pop
1013 while (val.length + pad.length < minwidth) pad += "\u00a0";
1249 if (normalNode != null && options.lineNumbers) {
1014 if (pad) firstNode.insertBefore(targetDocument.createTextNode(pad), firstNode.firstChild);
1250 var node = gutterText.childNodes[normalNode - showingFrom];
1251 var minwidth = String(doc.size).length, val = eltText(node.firstChild), pad = "";
1252 while (val.length + pad.length < minwidth) pad += "\u00a0";
1253 if (pad) node.insertBefore(document.createTextNode(pad), node.firstChild);
1254 }
1015 gutter.style.display = "";
1255 gutter.style.display = "";
1256 var resized = Math.abs((parseInt(lineSpace.style.marginLeft) || 0) - gutter.offsetWidth) > 2;
1016 lineSpace.style.marginLeft = gutter.offsetWidth + "px";
1257 lineSpace.style.marginLeft = gutter.offsetWidth + "px";
1017 gutterDirty = false;
1258 gutterDirty = false;
1259 return resized;
1018 }
1260 }
1019 function updateSelection() {
1261 function updateSelection() {
1020 var collapsed = posEq(sel.from, sel.to);
1262 var collapsed = posEq(sel.from, sel.to);
@@ -1031,20 +1273,24 var CodeMirror = (function() {
1031 selectionDiv.style.display = "none";
1273 selectionDiv.style.display = "none";
1032 } else {
1274 } else {
1033 var sameLine = fromPos.y == toPos.y, html = "";
1275 var sameLine = fromPos.y == toPos.y, html = "";
1276 var clientWidth = lineSpace.clientWidth || lineSpace.offsetWidth;
1277 var clientHeight = lineSpace.clientHeight || lineSpace.offsetHeight;
1034 function add(left, top, right, height) {
1278 function add(left, top, right, height) {
1279 var rstyle = quirksMode ? "width: " + (!right ? clientWidth : clientWidth - right - left) + "px"
1280 : "right: " + right + "px";
1035 html += '<div class="CodeMirror-selected" style="position: absolute; left: ' + left +
1281 html += '<div class="CodeMirror-selected" style="position: absolute; left: ' + left +
1036 'px; top: ' + top + 'px; right: ' + right + 'px; height: ' + height + 'px"></div>';
1282 'px; top: ' + top + 'px; ' + rstyle + '; height: ' + height + 'px"></div>';
1037 }
1283 }
1038 if (sel.from.ch && fromPos.y >= 0) {
1284 if (sel.from.ch && fromPos.y >= 0) {
1039 var right = sameLine ? lineSpace.clientWidth - toPos.x : 0;
1285 var right = sameLine ? clientWidth - toPos.x : 0;
1040 add(fromPos.x, fromPos.y, right, th);
1286 add(fromPos.x, fromPos.y, right, th);
1041 }
1287 }
1042 var middleStart = Math.max(0, fromPos.y + (sel.from.ch ? th : 0));
1288 var middleStart = Math.max(0, fromPos.y + (sel.from.ch ? th : 0));
1043 var middleHeight = Math.min(toPos.y, lineSpace.clientHeight) - middleStart;
1289 var middleHeight = Math.min(toPos.y, clientHeight) - middleStart;
1044 if (middleHeight > 0.2 * th)
1290 if (middleHeight > 0.2 * th)
1045 add(0, middleStart, 0, middleHeight);
1291 add(0, middleStart, 0, middleHeight);
1046 if ((!sameLine || !sel.from.ch) && toPos.y < lineSpace.clientHeight - .5 * th)
1292 if ((!sameLine || !sel.from.ch) && toPos.y < clientHeight - .5 * th)
1047 add(0, toPos.y, lineSpace.clientWidth - toPos.x, th);
1293 add(0, toPos.y, clientWidth - toPos.x, th);
1048 selectionDiv.innerHTML = html;
1294 selectionDiv.innerHTML = html;
1049 cursor.style.display = "none";
1295 cursor.style.display = "none";
1050 selectionDiv.style.display = "";
1296 selectionDiv.style.display = "";
@@ -1074,13 +1320,32 var CodeMirror = (function() {
1074 if (posLess(to, from)) {var tmp = to; to = from; from = tmp;}
1320 if (posLess(to, from)) {var tmp = to; to = from; from = tmp;}
1075
1321
1076 // Skip over hidden lines.
1322 // Skip over hidden lines.
1077 if (from.line != oldFrom) from = skipHidden(from, oldFrom, sel.from.ch);
1323 if (from.line != oldFrom) {
1324 var from1 = skipHidden(from, oldFrom, sel.from.ch);
1325 // If there is no non-hidden line left, force visibility on current line
1326 if (!from1) setLineHidden(from.line, false);
1327 else from = from1;
1328 }
1078 if (to.line != oldTo) to = skipHidden(to, oldTo, sel.to.ch);
1329 if (to.line != oldTo) to = skipHidden(to, oldTo, sel.to.ch);
1079
1330
1080 if (posEq(from, to)) sel.inverted = false;
1331 if (posEq(from, to)) sel.inverted = false;
1081 else if (posEq(from, sel.to)) sel.inverted = false;
1332 else if (posEq(from, sel.to)) sel.inverted = false;
1082 else if (posEq(to, sel.from)) sel.inverted = true;
1333 else if (posEq(to, sel.from)) sel.inverted = true;
1083
1334
1335 if (options.autoClearEmptyLines && posEq(sel.from, sel.to)) {
1336 var head = sel.inverted ? from : to;
1337 if (head.line != sel.from.line && sel.from.line < doc.size) {
1338 var oldLine = getLine(sel.from.line);
1339 if (/^\s+$/.test(oldLine.text))
1340 setTimeout(operation(function() {
1341 if (oldLine.parent && /^\s+$/.test(oldLine.text)) {
1342 var no = lineNo(oldLine);
1343 replaceRange("", {line: no, ch: 0}, {line: no, ch: oldLine.text.length});
1344 }
1345 }, 10));
1346 }
1347 }
1348
1084 sel.from = from; sel.to = to;
1349 sel.from = from; sel.to = to;
1085 selectionChanged = true;
1350 selectionChanged = true;
1086 }
1351 }
@@ -1091,13 +1356,14 var CodeMirror = (function() {
1091 var line = getLine(lNo);
1356 var line = getLine(lNo);
1092 if (!line.hidden) {
1357 if (!line.hidden) {
1093 var ch = pos.ch;
1358 var ch = pos.ch;
1094 if (ch > oldCh || ch > line.text.length) ch = line.text.length;
1359 if (toEnd || ch > oldCh || ch > line.text.length) ch = line.text.length;
1095 return {line: lNo, ch: ch};
1360 return {line: lNo, ch: ch};
1096 }
1361 }
1097 lNo += dir;
1362 lNo += dir;
1098 }
1363 }
1099 }
1364 }
1100 var line = getLine(pos.line);
1365 var line = getLine(pos.line);
1366 var toEnd = pos.ch == line.text.length && pos.ch != oldCh;
1101 if (!line.hidden) return pos;
1367 if (!line.hidden) return pos;
1102 if (pos.line >= oldLine) return getNonHidden(1) || getNonHidden(-1);
1368 if (pos.line >= oldLine) return getNonHidden(1) || getNonHidden(-1);
1103 else return getNonHidden(-1) || getNonHidden(1);
1369 else return getNonHidden(-1) || getNonHidden(1);
@@ -1164,19 +1430,22 var CodeMirror = (function() {
1164 if (unit == "page") dist = Math.min(scroller.clientHeight, window.innerHeight || document.documentElement.clientHeight);
1430 if (unit == "page") dist = Math.min(scroller.clientHeight, window.innerHeight || document.documentElement.clientHeight);
1165 else if (unit == "line") dist = textHeight();
1431 else if (unit == "line") dist = textHeight();
1166 var target = coordsChar(pos.x, pos.y + dist * dir + 2);
1432 var target = coordsChar(pos.x, pos.y + dist * dir + 2);
1433 if (unit == "page") scrollbar.scrollTop += localCoords(target, true).y - pos.y;
1167 setCursor(target.line, target.ch, true);
1434 setCursor(target.line, target.ch, true);
1168 goalColumn = pos.x;
1435 goalColumn = pos.x;
1169 }
1436 }
1170
1437
1171 function selectWordAt(pos) {
1438 function findWordAt(pos) {
1172 var line = getLine(pos.line).text;
1439 var line = getLine(pos.line).text;
1173 var start = pos.ch, end = pos.ch;
1440 var start = pos.ch, end = pos.ch;
1174 while (start > 0 && isWordChar(line.charAt(start - 1))) --start;
1441 var check = isWordChar(line.charAt(start < line.length ? start : start - 1)) ?
1175 while (end < line.length && isWordChar(line.charAt(end))) ++end;
1442 isWordChar : function(ch) {return !isWordChar(ch);};
1176 setSelectionUser({line: pos.line, ch: start}, {line: pos.line, ch: end});
1443 while (start > 0 && check(line.charAt(start - 1))) --start;
1444 while (end < line.length && check(line.charAt(end))) ++end;
1445 return {from: {line: pos.line, ch: start}, to: {line: pos.line, ch: end}};
1177 }
1446 }
1178 function selectLine(line) {
1447 function selectLine(line) {
1179 setSelectionUser({line: line, ch: 0}, {line: line, ch: getLine(line).text.length});
1448 setSelectionUser({line: line, ch: 0}, clipPos({line: line + 1, ch: 0}));
1180 }
1449 }
1181 function indentSelected(mode) {
1450 function indentSelected(mode) {
1182 if (posEq(sel.from, sel.to)) return indentLine(sel.from.line, mode);
1451 if (posEq(sel.from, sel.to)) return indentLine(sel.from.line, mode);
@@ -1193,26 +1462,23 var CodeMirror = (function() {
1193
1462
1194 var line = getLine(n), curSpace = line.indentation(options.tabSize),
1463 var line = getLine(n), curSpace = line.indentation(options.tabSize),
1195 curSpaceString = line.text.match(/^\s*/)[0], indentation;
1464 curSpaceString = line.text.match(/^\s*/)[0], indentation;
1465 if (how == "smart") {
1466 indentation = mode.indent(state, line.text.slice(curSpaceString.length), line.text);
1467 if (indentation == Pass) how = "prev";
1468 }
1196 if (how == "prev") {
1469 if (how == "prev") {
1197 if (n) indentation = getLine(n-1).indentation(options.tabSize);
1470 if (n) indentation = getLine(n-1).indentation(options.tabSize);
1198 else indentation = 0;
1471 else indentation = 0;
1199 }
1472 }
1200 else if (how == "smart") indentation = mode.indent(state, line.text.slice(curSpaceString.length), line.text);
1201 else if (how == "add") indentation = curSpace + options.indentUnit;
1473 else if (how == "add") indentation = curSpace + options.indentUnit;
1202 else if (how == "subtract") indentation = curSpace - options.indentUnit;
1474 else if (how == "subtract") indentation = curSpace - options.indentUnit;
1203 indentation = Math.max(0, indentation);
1475 indentation = Math.max(0, indentation);
1204 var diff = indentation - curSpace;
1476 var diff = indentation - curSpace;
1205
1477
1206 if (!diff) {
1478 var indentString = "", pos = 0;
1207 if (sel.from.line != n && sel.to.line != n) return;
1479 if (options.indentWithTabs)
1208 var indentString = curSpaceString;
1480 for (var i = Math.floor(indentation / options.tabSize); i; --i) {pos += options.tabSize; indentString += "\t";}
1209 }
1481 while (pos < indentation) {++pos; indentString += " ";}
1210 else {
1211 var indentString = "", pos = 0;
1212 if (options.indentWithTabs)
1213 for (var i = Math.floor(indentation / options.tabSize); i; --i) {pos += options.tabSize; indentString += "\t";}
1214 while (pos < indentation) {++pos; indentString += " ";}
1215 }
1216
1482
1217 replaceRange(indentString, {line: n, ch: 0}, {line: n, ch: curSpaceString.length});
1483 replaceRange(indentString, {line: n, ch: 0}, {line: n, ch: curSpaceString.length});
1218 }
1484 }
@@ -1239,9 +1505,10 var CodeMirror = (function() {
1239 if (guess != 1) updateLineHeight(line, guess);
1505 if (guess != 1) updateLineHeight(line, guess);
1240 });
1506 });
1241 lineSpace.style.width = code.style.width = "";
1507 lineSpace.style.width = code.style.width = "";
1508 widthForcer.style.left = "";
1242 } else {
1509 } else {
1243 wrapper.className = wrapper.className.replace(" CodeMirror-wrap", "");
1510 wrapper.className = wrapper.className.replace(" CodeMirror-wrap", "");
1244 maxWidth = null; maxLine = "";
1511 maxLine = ""; maxLineChanged = true;
1245 doc.iter(0, doc.size, function(line) {
1512 doc.iter(0, doc.size, function(line) {
1246 if (line.height != 1 && !line.hidden) updateLineHeight(line, 1);
1513 if (line.height != 1 && !line.hidden) updateLineHeight(line, 1);
1247 if (line.text.length > maxLine.length) maxLine = line.text;
1514 if (line.text.length > maxLine.length) maxLine = line.text;
@@ -1249,18 +1516,21 var CodeMirror = (function() {
1249 }
1516 }
1250 changes.push({from: 0, to: doc.size});
1517 changes.push({from: 0, to: doc.size});
1251 }
1518 }
1252 function computeTabText() {
1519 function makeTab(col) {
1253 for (var str = '<span class="cm-tab">', i = 0; i < options.tabSize; ++i) str += " ";
1520 var w = options.tabSize - col % options.tabSize, cached = tabCache[w];
1254 return str + "</span>";
1521 if (cached) return cached;
1255 }
1522 for (var str = '<span class="cm-tab">', i = 0; i < w; ++i) str += " ";
1256 function tabsChanged() {
1523 return (tabCache[w] = {html: str + "</span>", width: w});
1257 tabText = computeTabText();
1258 updateDisplay(true);
1259 }
1524 }
1260 function themeChanged() {
1525 function themeChanged() {
1261 scroller.className = scroller.className.replace(/\s*cm-s-\w+/g, "") +
1526 scroller.className = scroller.className.replace(/\s*cm-s-\S+/g, "") +
1262 options.theme.replace(/(^|\s)\s*/g, " cm-s-");
1527 options.theme.replace(/(^|\s)\s*/g, " cm-s-");
1263 }
1528 }
1529 function keyMapChanged() {
1530 var style = keyMap[options.keyMap].style;
1531 wrapper.className = wrapper.className.replace(/\s*cm-keymap-\S+/g, "") +
1532 (style ? " cm-keymap-" + style : "");
1533 }
1264
1534
1265 function TextMarker() { this.set = []; }
1535 function TextMarker() { this.set = []; }
1266 TextMarker.prototype.clear = operation(function() {
1536 TextMarker.prototype.clear = operation(function() {
@@ -1271,7 +1541,7 var CodeMirror = (function() {
1271 var lineN = lineNo(line);
1541 var lineN = lineNo(line);
1272 min = Math.min(min, lineN); max = Math.max(max, lineN);
1542 min = Math.min(min, lineN); max = Math.max(max, lineN);
1273 for (var j = 0; j < mk.length; ++j)
1543 for (var j = 0; j < mk.length; ++j)
1274 if (mk[j].set == this.set) mk.splice(j--, 1);
1544 if (mk[j].marker == this) mk.splice(j--, 1);
1275 }
1545 }
1276 if (min != Infinity)
1546 if (min != Infinity)
1277 changes.push({from: min, to: max + 1});
1547 changes.push({from: min, to: max + 1});
@@ -1282,7 +1552,7 var CodeMirror = (function() {
1282 var line = this.set[i], mk = line.marked;
1552 var line = this.set[i], mk = line.marked;
1283 for (var j = 0; j < mk.length; ++j) {
1553 for (var j = 0; j < mk.length; ++j) {
1284 var mark = mk[j];
1554 var mark = mk[j];
1285 if (mark.set == this.set) {
1555 if (mark.marker == this) {
1286 if (mark.from != null || mark.to != null) {
1556 if (mark.from != null || mark.to != null) {
1287 var found = lineNo(line);
1557 var found = lineNo(line);
1288 if (found != null) {
1558 if (found != null) {
@@ -1299,8 +1569,9 var CodeMirror = (function() {
1299 function markText(from, to, className) {
1569 function markText(from, to, className) {
1300 from = clipPos(from); to = clipPos(to);
1570 from = clipPos(from); to = clipPos(to);
1301 var tm = new TextMarker();
1571 var tm = new TextMarker();
1572 if (!posLess(from, to)) return tm;
1302 function add(line, from, to, className) {
1573 function add(line, from, to, className) {
1303 getLine(line).addMark(new MarkedText(from, to, className, tm.set));
1574 getLine(line).addMark(new MarkedText(from, to, className, tm));
1304 }
1575 }
1305 if (from.line == to.line) add(from.line, from.ch, to.ch, className);
1576 if (from.line == to.line) add(from.line, from.ch, to.ch, className);
1306 else {
1577 else {
@@ -1320,6 +1591,19 var CodeMirror = (function() {
1320 return bm;
1591 return bm;
1321 }
1592 }
1322
1593
1594 function findMarksAt(pos) {
1595 pos = clipPos(pos);
1596 var markers = [], marked = getLine(pos.line).marked;
1597 if (!marked) return markers;
1598 for (var i = 0, e = marked.length; i < e; ++i) {
1599 var m = marked[i];
1600 if ((m.from == null || m.from <= pos.ch) &&
1601 (m.to == null || m.to >= pos.ch))
1602 markers.push(m.marker || m);
1603 }
1604 return markers;
1605 }
1606
1323 function addGutterMarker(line, text, className) {
1607 function addGutterMarker(line, text, className) {
1324 if (typeof line == "number") line = getLine(clipLine(line));
1608 if (typeof line == "number") line = getLine(clipLine(line));
1325 line.gutterMarker = {text: text, style: className};
1609 line.gutterMarker = {text: text, style: className};
@@ -1341,10 +1625,11 var CodeMirror = (function() {
1341 else return null;
1625 else return null;
1342 return line;
1626 return line;
1343 }
1627 }
1344 function setLineClass(handle, className) {
1628 function setLineClass(handle, className, bgClassName) {
1345 return changeLine(handle, function(line) {
1629 return changeLine(handle, function(line) {
1346 if (line.className != className) {
1630 if (line.className != className || line.bgClassName != bgClassName) {
1347 line.className = className;
1631 line.className = className;
1632 line.bgClassName = bgClassName;
1348 return true;
1633 return true;
1349 }
1634 }
1350 });
1635 });
@@ -1353,11 +1638,21 var CodeMirror = (function() {
1353 return changeLine(handle, function(line, no) {
1638 return changeLine(handle, function(line, no) {
1354 if (line.hidden != hidden) {
1639 if (line.hidden != hidden) {
1355 line.hidden = hidden;
1640 line.hidden = hidden;
1641 if (!options.lineWrapping) {
1642 var l = line.text;
1643 if (hidden && l.length == maxLine.length) {
1644 updateMaxLine = true;
1645 } else if (!hidden && l.length > maxLine.length) {
1646 maxLine = l; updateMaxLine = false;
1647 }
1648 }
1356 updateLineHeight(line, hidden ? 0 : 1);
1649 updateLineHeight(line, hidden ? 0 : 1);
1357 var fline = sel.from.line, tline = sel.to.line;
1650 var fline = sel.from.line, tline = sel.to.line;
1358 if (hidden && (fline == no || tline == no)) {
1651 if (hidden && (fline == no || tline == no)) {
1359 var from = fline == no ? skipHidden({line: fline, ch: 0}, fline, 0) : sel.from;
1652 var from = fline == no ? skipHidden({line: fline, ch: 0}, fline, 0) : sel.from;
1360 var to = tline == no ? skipHidden({line: tline, ch: 0}, tline, 0) : sel.to;
1653 var to = tline == no ? skipHidden({line: tline, ch: 0}, tline, 0) : sel.to;
1654 // Can't hide the last visible line, we'd have no place to put the cursor
1655 if (!to) return;
1361 setSelection(from, to);
1656 setSelection(from, to);
1362 }
1657 }
1363 return (gutterDirty = true);
1658 return (gutterDirty = true);
@@ -1371,14 +1666,13 var CodeMirror = (function() {
1371 var n = line;
1666 var n = line;
1372 line = getLine(line);
1667 line = getLine(line);
1373 if (!line) return null;
1668 if (!line) return null;
1374 }
1669 } else {
1375 else {
1376 var n = lineNo(line);
1670 var n = lineNo(line);
1377 if (n == null) return null;
1671 if (n == null) return null;
1378 }
1672 }
1379 var marker = line.gutterMarker;
1673 var marker = line.gutterMarker;
1380 return {line: n, handle: line, text: line.text, markerText: marker && marker.text,
1674 return {line: n, handle: line, text: line.text, markerText: marker && marker.text,
1381 markerClass: marker && marker.style, lineClass: line.className};
1675 markerClass: marker && marker.style, lineClass: line.className, bgClass: line.bgClassName};
1382 }
1676 }
1383
1677
1384 function stringWidth(str) {
1678 function stringWidth(str) {
@@ -1392,8 +1686,7 var CodeMirror = (function() {
1392 if (x <= 0) return 0;
1686 if (x <= 0) return 0;
1393 var lineObj = getLine(line), text = lineObj.text;
1687 var lineObj = getLine(line), text = lineObj.text;
1394 function getX(len) {
1688 function getX(len) {
1395 measure.innerHTML = "<pre><span>" + lineObj.getHTML(tabText, len) + "</span></pre>";
1689 return measureLine(lineObj, len).left;
1396 return measure.firstChild.firstChild.offsetWidth;
1397 }
1690 }
1398 var from = 0, fromX = 0, to = text.length, toX;
1691 var from = 0, fromX = 0, to = text.length, toX;
1399 // Guess a suitable upper bound for our search.
1692 // Guess a suitable upper bound for our search.
@@ -1416,19 +1709,13 var CodeMirror = (function() {
1416 }
1709 }
1417 }
1710 }
1418
1711
1419 var tempId = Math.floor(Math.random() * 0xffffff).toString(16);
1712 var tempId = "CodeMirror-temp-" + Math.floor(Math.random() * 0xffffff).toString(16);
1420 function measureLine(line, ch) {
1713 function measureLine(line, ch) {
1421 if (ch == 0) return {top: 0, left: 0};
1714 if (ch == 0) return {top: 0, left: 0};
1422 var extra = "";
1715 var wbr = options.lineWrapping && ch < line.text.length &&
1423 // Include extra text at the end to make sure the measured line is wrapped in the right way.
1716 spanAffectsWrapping.test(line.text.slice(ch - 1, ch + 1));
1424 if (options.lineWrapping) {
1717 measure.innerHTML = "<pre>" + line.getHTML(makeTab, ch, tempId, wbr) + "</pre>";
1425 var end = line.text.indexOf(" ", ch + 2);
1718 var elt = document.getElementById(tempId);
1426 extra = htmlEscape(line.text.slice(ch + 1, end < 0 ? line.text.length : end + (ie ? 5 : 0)));
1427 }
1428 measure.innerHTML = "<pre>" + line.getHTML(tabText, ch) +
1429 '<span id="CodeMirror-temp-' + tempId + '">' + htmlEscape(line.text.charAt(ch) || " ") + "</span>" +
1430 extra + "</pre>";
1431 var elt = document.getElementById("CodeMirror-temp-" + tempId);
1432 var top = elt.offsetTop, left = elt.offsetLeft;
1719 var top = elt.offsetTop, left = elt.offsetLeft;
1433 // Older IEs report zero offsets for spans directly after a wrap
1720 // Older IEs report zero offsets for spans directly after a wrap
1434 if (ie && top == 0 && left == 0) {
1721 if (ie && top == 0 && left == 0) {
@@ -1528,8 +1815,8 var CodeMirror = (function() {
1528 return coordsChar(x - offL.left, y - offL.top);
1815 return coordsChar(x - offL.left, y - offL.top);
1529 }
1816 }
1530 function onContextMenu(e) {
1817 function onContextMenu(e) {
1531 var pos = posFromMouse(e);
1818 var pos = posFromMouse(e), scrollPos = scrollbar.scrollTop;
1532 if (!pos || window.opera) return; // Opera is difficult.
1819 if (!pos || opera) return; // Opera is difficult.
1533 if (posEq(sel.from, sel.to) || posLess(pos, sel.from) || !posLess(pos, sel.to))
1820 if (posEq(sel.from, sel.to) || posLess(pos, sel.from) || !posLess(pos, sel.to))
1534 operation(setCursor)(pos.line, pos.ch);
1821 operation(setCursor)(pos.line, pos.ch);
1535
1822
@@ -1544,9 +1831,10 var CodeMirror = (function() {
1544 selectInput(input);
1831 selectInput(input);
1545 function rehide() {
1832 function rehide() {
1546 var newVal = splitLines(input.value).join("\n");
1833 var newVal = splitLines(input.value).join("\n");
1547 if (newVal != val) operation(replaceSelection)(newVal, "end");
1834 if (newVal != val && !options.readOnly) operation(replaceSelection)(newVal, "end");
1548 inputDiv.style.position = "relative";
1835 inputDiv.style.position = "relative";
1549 input.style.cssText = oldCSS;
1836 input.style.cssText = oldCSS;
1837 if (ie_lt9) scrollbar.scrollTop = scrollPos;
1550 leaveInputAlone = false;
1838 leaveInputAlone = false;
1551 resetInput(true);
1839 resetInput(true);
1552 slowPoll();
1840 slowPoll();
@@ -1558,8 +1846,7 var CodeMirror = (function() {
1558 mouseup();
1846 mouseup();
1559 setTimeout(rehide, 20);
1847 setTimeout(rehide, 20);
1560 }, true);
1848 }, true);
1561 }
1849 } else {
1562 else {
1563 setTimeout(rehide, 50);
1850 setTimeout(rehide, 50);
1564 }
1851 }
1565 }
1852 }
@@ -1589,7 +1876,7 var CodeMirror = (function() {
1589 var st = line.styles, pos = forward ? 0 : line.text.length - 1, cur;
1876 var st = line.styles, pos = forward ? 0 : line.text.length - 1, cur;
1590 for (var i = forward ? 0 : st.length - 2, e = forward ? st.length : -2; i != e; i += 2*d) {
1877 for (var i = forward ? 0 : st.length - 2, e = forward ? st.length : -2; i != e; i += 2*d) {
1591 var text = st[i];
1878 var text = st[i];
1592 if (st[i+1] != null && st[i+1] != style) {pos += d * text.length; continue;}
1879 if (st[i+1] != style) {pos += d * text.length; continue;}
1593 for (var j = forward ? 0 : text.length - 1, te = forward ? text.length : -1; j != te; j += d, pos+=d) {
1880 for (var j = forward ? 0 : text.length - 1, te = forward ? text.length : -1; j != te; j += d, pos+=d) {
1594 if (pos >= from && pos < to && re.test(cur = text.charAt(j))) {
1881 if (pos >= from && pos < to && re.test(cur = text.charAt(j))) {
1595 var match = matching[cur];
1882 var match = matching[cur];
@@ -1676,13 +1963,17 var CodeMirror = (function() {
1676 var changed = line.highlight(mode, state, options.tabSize);
1963 var changed = line.highlight(mode, state, options.tabSize);
1677 if (changed) realChange = true;
1964 if (changed) realChange = true;
1678 line.stateAfter = copyState(mode, state);
1965 line.stateAfter = copyState(mode, state);
1966 var done = null;
1679 if (compare) {
1967 if (compare) {
1680 if (hadState && compare(hadState, state)) return true;
1968 var same = hadState && compare(hadState, state);
1681 } else {
1969 if (same != Pass) done = !!same;
1970 }
1971 if (done == null) {
1682 if (changed !== false || !hadState) unchanged = 0;
1972 if (changed !== false || !hadState) unchanged = 0;
1683 else if (++unchanged > 3 && (!mode.indent || mode.indent(hadState, "") == mode.indent(state, "")))
1973 else if (++unchanged > 3 && (!mode.indent || mode.indent(hadState, "") == mode.indent(state, "")))
1684 return true;
1974 done = true;
1685 }
1975 }
1976 if (done) return true;
1686 ++i;
1977 ++i;
1687 });
1978 });
1688 if (bail) return;
1979 if (bail) return;
@@ -1705,14 +1996,24 var CodeMirror = (function() {
1705 changes = []; selectionChanged = false; callbacks = [];
1996 changes = []; selectionChanged = false; callbacks = [];
1706 }
1997 }
1707 function endOperation() {
1998 function endOperation() {
1708 var reScroll = false, updated;
1999 if (updateMaxLine) computeMaxLength();
1709 if (selectionChanged) reScroll = !scrollCursorIntoView();
2000 if (maxLineChanged && !options.lineWrapping) {
1710 if (changes.length) updated = updateDisplay(changes, true);
2001 var cursorWidth = widthForcer.offsetWidth, left = stringWidth(maxLine);
2002 widthForcer.style.left = left + "px";
2003 lineSpace.style.minWidth = (left + cursorWidth) + "px";
2004 maxLineChanged = false;
2005 }
2006 var newScrollPos, updated;
2007 if (selectionChanged) {
2008 var coords = calculateCursorCoords();
2009 newScrollPos = calculateScrollPos(coords.x, coords.y, coords.x, coords.yBot);
2010 }
2011 if (changes.length) updated = updateDisplay(changes, true, (newScrollPos ? newScrollPos.scrollTop : null));
1711 else {
2012 else {
1712 if (selectionChanged) updateSelection();
2013 if (selectionChanged) updateSelection();
1713 if (gutterDirty) updateGutter();
2014 if (gutterDirty) updateGutter();
1714 }
2015 }
1715 if (reScroll) scrollCursorIntoView();
2016 if (newScrollPos) scrollCursorIntoView();
1716 if (selectionChanged) {scrollEditorIntoView(); restartBlink();}
2017 if (selectionChanged) {scrollEditorIntoView(); restartBlink();}
1717
2018
1718 if (focused && !leaveInputAlone &&
2019 if (focused && !leaveInputAlone &&
@@ -1724,11 +2025,11 var CodeMirror = (function() {
1724 if (bracketHighlighted) {bracketHighlighted(); bracketHighlighted = null;}
2025 if (bracketHighlighted) {bracketHighlighted(); bracketHighlighted = null;}
1725 if (posEq(sel.from, sel.to)) matchBrackets(false);
2026 if (posEq(sel.from, sel.to)) matchBrackets(false);
1726 }), 20);
2027 }), 20);
1727 var tc = textChanged, cbs = callbacks; // these can be reset by callbacks
2028 var sc = selectionChanged, cbs = callbacks; // these can be reset by callbacks
1728 if (selectionChanged && options.onCursorActivity)
2029 if (textChanged && options.onChange && instance)
2030 options.onChange(instance, textChanged);
2031 if (sc && options.onCursorActivity)
1729 options.onCursorActivity(instance);
2032 options.onCursorActivity(instance);
1730 if (tc && options.onChange && instance)
1731 options.onChange(instance, tc);
1732 for (var i = 0; i < cbs.length; ++i) cbs[i](instance);
2033 for (var i = 0; i < cbs.length; ++i) cbs[i](instance);
1733 if (updated && options.onUpdate) options.onUpdate(instance);
2034 if (updated && options.onUpdate) options.onUpdate(instance);
1734 }
2035 }
@@ -1742,6 +2043,11 var CodeMirror = (function() {
1742 };
2043 };
1743 }
2044 }
1744
2045
2046 function compoundChange(f) {
2047 history.startCompound();
2048 try { return f(); } finally { history.endCompound(); }
2049 }
2050
1745 for (var ext in extensions)
2051 for (var ext in extensions)
1746 if (extensions.propertyIsEnumerable(ext) &&
2052 if (extensions.propertyIsEnumerable(ext) &&
1747 !instance.propertyIsEnumerable(ext))
2053 !instance.propertyIsEnumerable(ext))
@@ -1761,13 +2067,16 var CodeMirror = (function() {
1761 keyMap: "default",
2067 keyMap: "default",
1762 extraKeys: null,
2068 extraKeys: null,
1763 electricChars: true,
2069 electricChars: true,
2070 autoClearEmptyLines: false,
1764 onKeyEvent: null,
2071 onKeyEvent: null,
2072 onDragEvent: null,
1765 lineWrapping: false,
2073 lineWrapping: false,
1766 lineNumbers: false,
2074 lineNumbers: false,
1767 gutter: false,
2075 gutter: false,
1768 fixedGutter: false,
2076 fixedGutter: false,
1769 firstLineNumber: 1,
2077 firstLineNumber: 1,
1770 readOnly: false,
2078 readOnly: false,
2079 dragDrop: true,
1771 onChange: null,
2080 onChange: null,
1772 onCursorActivity: null,
2081 onCursorActivity: null,
1773 onGutterClick: null,
2082 onGutterClick: null,
@@ -1780,7 +2089,8 var CodeMirror = (function() {
1780 pollInterval: 100,
2089 pollInterval: 100,
1781 undoDepth: 40,
2090 undoDepth: 40,
1782 tabindex: null,
2091 tabindex: null,
1783 document: window.document
2092 autofocus: null,
2093 lineNumberFormatter: function(integer) { return integer; }
1784 };
2094 };
1785
2095
1786 var ios = /AppleWebKit/.test(navigator.userAgent) && /Mobile\/\w+/.test(navigator.userAgent);
2096 var ios = /AppleWebKit/.test(navigator.userAgent) && /Mobile\/\w+/.test(navigator.userAgent);
@@ -1788,27 +2098,31 var CodeMirror = (function() {
1788 var win = /Win/.test(navigator.platform);
2098 var win = /Win/.test(navigator.platform);
1789
2099
1790 // Known modes, by name and by MIME
2100 // Known modes, by name and by MIME
1791 var modes = {}, mimeModes = {};
2101 var modes = CodeMirror.modes = {}, mimeModes = CodeMirror.mimeModes = {};
1792 CodeMirror.defineMode = function(name, mode) {
2102 CodeMirror.defineMode = function(name, mode) {
1793 if (!CodeMirror.defaults.mode && name != "null") CodeMirror.defaults.mode = name;
2103 if (!CodeMirror.defaults.mode && name != "null") CodeMirror.defaults.mode = name;
2104 if (arguments.length > 2) {
2105 mode.dependencies = [];
2106 for (var i = 2; i < arguments.length; ++i) mode.dependencies.push(arguments[i]);
2107 }
1794 modes[name] = mode;
2108 modes[name] = mode;
1795 };
2109 };
1796 CodeMirror.defineMIME = function(mime, spec) {
2110 CodeMirror.defineMIME = function(mime, spec) {
1797 mimeModes[mime] = spec;
2111 mimeModes[mime] = spec;
1798 };
2112 };
1799 CodeMirror.getMode = function(options, spec) {
2113 CodeMirror.resolveMode = function(spec) {
1800 if (typeof spec == "string" && mimeModes.hasOwnProperty(spec))
2114 if (typeof spec == "string" && mimeModes.hasOwnProperty(spec))
1801 spec = mimeModes[spec];
2115 spec = mimeModes[spec];
1802 if (typeof spec == "string")
2116 else if (typeof spec == "string" && /^[\w\-]+\/[\w\-]+\+xml$/.test(spec))
1803 var mname = spec, config = {};
2117 return CodeMirror.resolveMode("application/xml");
1804 else if (spec != null)
2118 if (typeof spec == "string") return {name: spec};
1805 var mname = spec.name, config = spec;
2119 else return spec || {name: "null"};
1806 var mfactory = modes[mname];
2120 };
1807 if (!mfactory) {
2121 CodeMirror.getMode = function(options, spec) {
1808 if (window.console) console.warn("No mode " + mname + " found, falling back to plain text.");
2122 var spec = CodeMirror.resolveMode(spec);
1809 return CodeMirror.getMode(options, "text/plain");
2123 var mfactory = modes[spec.name];
1810 }
2124 if (!mfactory) return CodeMirror.getMode(options, "text/plain");
1811 return mfactory(options, config || {});
2125 return mfactory(options, spec);
1812 };
2126 };
1813 CodeMirror.listModes = function() {
2127 CodeMirror.listModes = function() {
1814 var list = [];
2128 var list = [];
@@ -1865,6 +2179,10 var CodeMirror = (function() {
1865 indentMore: function(cm) {cm.indentSelection("add");},
2179 indentMore: function(cm) {cm.indentSelection("add");},
1866 indentLess: function(cm) {cm.indentSelection("subtract");},
2180 indentLess: function(cm) {cm.indentSelection("subtract");},
1867 insertTab: function(cm) {cm.replaceSelection("\t", "end");},
2181 insertTab: function(cm) {cm.replaceSelection("\t", "end");},
2182 defaultTab: function(cm) {
2183 if (cm.somethingSelected()) cm.indentSelection("add");
2184 else cm.replaceSelection("\t", "end");
2185 },
1868 transposeChars: function(cm) {
2186 transposeChars: function(cm) {
1869 var cur = cm.getCursor(), line = cm.getLine(cur.line);
2187 var cur = cm.getCursor(), line = cm.getLine(cur.line);
1870 if (cur.ch > 0 && cur.ch < line.length - 1)
2188 if (cur.ch > 0 && cur.ch < line.length - 1)
@@ -1882,7 +2200,7 var CodeMirror = (function() {
1882 keyMap.basic = {
2200 keyMap.basic = {
1883 "Left": "goCharLeft", "Right": "goCharRight", "Up": "goLineUp", "Down": "goLineDown",
2201 "Left": "goCharLeft", "Right": "goCharRight", "Up": "goLineUp", "Down": "goLineDown",
1884 "End": "goLineEnd", "Home": "goLineStartSmart", "PageUp": "goPageUp", "PageDown": "goPageDown",
2202 "End": "goLineEnd", "Home": "goLineStartSmart", "PageUp": "goPageUp", "PageDown": "goPageDown",
1885 "Delete": "delCharRight", "Backspace": "delCharLeft", "Tab": "indentMore", "Shift-Tab": "indentLess",
2203 "Delete": "delCharRight", "Backspace": "delCharLeft", "Tab": "defaultTab", "Shift-Tab": "indentAuto",
1886 "Enter": "newlineAndIndent", "Insert": "toggleOverwrite"
2204 "Enter": "newlineAndIndent", "Insert": "toggleOverwrite"
1887 };
2205 };
1888 // Note that the save and find-related commands aren't defined by
2206 // Note that the save and find-related commands aren't defined by
@@ -1893,6 +2211,7 var CodeMirror = (function() {
1893 "Ctrl-Left": "goWordLeft", "Ctrl-Right": "goWordRight", "Alt-Left": "goLineStart", "Alt-Right": "goLineEnd",
2211 "Ctrl-Left": "goWordLeft", "Ctrl-Right": "goWordRight", "Alt-Left": "goLineStart", "Alt-Right": "goLineEnd",
1894 "Ctrl-Backspace": "delWordLeft", "Ctrl-Delete": "delWordRight", "Ctrl-S": "save", "Ctrl-F": "find",
2212 "Ctrl-Backspace": "delWordLeft", "Ctrl-Delete": "delWordRight", "Ctrl-S": "save", "Ctrl-F": "find",
1895 "Ctrl-G": "findNext", "Shift-Ctrl-G": "findPrev", "Shift-Ctrl-F": "replace", "Shift-Ctrl-R": "replaceAll",
2213 "Ctrl-G": "findNext", "Shift-Ctrl-G": "findPrev", "Shift-Ctrl-F": "replace", "Shift-Ctrl-R": "replaceAll",
2214 "Ctrl-[": "indentLess", "Ctrl-]": "indentMore",
1896 fallthrough: "basic"
2215 fallthrough: "basic"
1897 };
2216 };
1898 keyMap.macDefault = {
2217 keyMap.macDefault = {
@@ -1901,6 +2220,7 var CodeMirror = (function() {
1901 "Alt-Right": "goWordRight", "Cmd-Left": "goLineStart", "Cmd-Right": "goLineEnd", "Alt-Backspace": "delWordLeft",
2220 "Alt-Right": "goWordRight", "Cmd-Left": "goLineStart", "Cmd-Right": "goLineEnd", "Alt-Backspace": "delWordLeft",
1902 "Ctrl-Alt-Backspace": "delWordRight", "Alt-Delete": "delWordRight", "Cmd-S": "save", "Cmd-F": "find",
2221 "Ctrl-Alt-Backspace": "delWordRight", "Alt-Delete": "delWordRight", "Cmd-S": "save", "Cmd-F": "find",
1903 "Cmd-G": "findNext", "Shift-Cmd-G": "findPrev", "Cmd-Alt-F": "replace", "Shift-Cmd-Alt-F": "replaceAll",
2222 "Cmd-G": "findNext", "Shift-Cmd-G": "findPrev", "Cmd-Alt-F": "replace", "Shift-Cmd-Alt-F": "replaceAll",
2223 "Cmd-[": "indentLess", "Cmd-]": "indentMore",
1904 fallthrough: ["basic", "emacsy"]
2224 fallthrough: ["basic", "emacsy"]
1905 };
2225 };
1906 keyMap["default"] = mac ? keyMap.macDefault : keyMap.pcDefault;
2226 keyMap["default"] = mac ? keyMap.macDefault : keyMap.pcDefault;
@@ -1911,20 +2231,30 var CodeMirror = (function() {
1911 "Alt-D": "delWordRight", "Alt-Backspace": "delWordLeft", "Ctrl-K": "killLine", "Ctrl-T": "transposeChars"
2231 "Alt-D": "delWordRight", "Alt-Backspace": "delWordLeft", "Ctrl-K": "killLine", "Ctrl-T": "transposeChars"
1912 };
2232 };
1913
2233
1914 function lookupKey(name, extraMap, map) {
2234 function getKeyMap(val) {
1915 function lookup(name, map, ft) {
2235 if (typeof val == "string") return keyMap[val];
2236 else return val;
2237 }
2238 function lookupKey(name, extraMap, map, handle, stop) {
2239 function lookup(map) {
2240 map = getKeyMap(map);
1916 var found = map[name];
2241 var found = map[name];
1917 if (found != null) return found;
2242 if (found != null && handle(found)) return true;
1918 if (ft == null) ft = map.fallthrough;
2243 if (map.nofallthrough) {
1919 if (ft == null) return map.catchall;
2244 if (stop) stop();
1920 if (typeof ft == "string") return lookup(name, keyMap[ft]);
2245 return true;
1921 for (var i = 0, e = ft.length; i < e; ++i) {
1922 found = lookup(name, keyMap[ft[i]]);
1923 if (found != null) return found;
1924 }
2246 }
1925 return null;
2247 var fallthrough = map.fallthrough;
2248 if (fallthrough == null) return false;
2249 if (Object.prototype.toString.call(fallthrough) != "[object Array]")
2250 return lookup(fallthrough);
2251 for (var i = 0, e = fallthrough.length; i < e; ++i) {
2252 if (lookup(fallthrough[i])) return true;
2253 }
2254 return false;
1926 }
2255 }
1927 return extraMap ? lookup(name, extraMap, map) : lookup(name, keyMap[map]);
2256 if (extraMap && lookup(extraMap)) return true;
2257 return lookup(map);
1928 }
2258 }
1929 function isModifierKey(event) {
2259 function isModifierKey(event) {
1930 var name = keyNames[e_prop(event, "keyCode")];
2260 var name = keyNames[e_prop(event, "keyCode")];
@@ -1936,6 +2266,8 var CodeMirror = (function() {
1936 options.value = textarea.value;
2266 options.value = textarea.value;
1937 if (!options.tabindex && textarea.tabindex)
2267 if (!options.tabindex && textarea.tabindex)
1938 options.tabindex = textarea.tabindex;
2268 options.tabindex = textarea.tabindex;
2269 if (options.autofocus == null && textarea.getAttribute("autofocus") != null)
2270 options.autofocus = true;
1939
2271
1940 function save() {textarea.value = instance.getValue();}
2272 function save() {textarea.value = instance.getValue();}
1941 if (textarea.form) {
2273 if (textarea.form) {
@@ -2036,8 +2368,7 var CodeMirror = (function() {
2036 if (consume !== false) this.pos += pattern.length;
2368 if (consume !== false) this.pos += pattern.length;
2037 return true;
2369 return true;
2038 }
2370 }
2039 }
2371 } else {
2040 else {
2041 var match = this.string.slice(this.pos).match(pattern);
2372 var match = this.string.slice(this.pos).match(pattern);
2042 if (match && consume !== false) this.pos += match[0].length;
2373 if (match && consume !== false) this.pos += match[0].length;
2043 return match;
2374 return match;
@@ -2047,34 +2378,34 var CodeMirror = (function() {
2047 };
2378 };
2048 CodeMirror.StringStream = StringStream;
2379 CodeMirror.StringStream = StringStream;
2049
2380
2050 function MarkedText(from, to, className, set) {
2381 function MarkedText(from, to, className, marker) {
2051 this.from = from; this.to = to; this.style = className; this.set = set;
2382 this.from = from; this.to = to; this.style = className; this.marker = marker;
2052 }
2383 }
2053 MarkedText.prototype = {
2384 MarkedText.prototype = {
2054 attach: function(line) { this.set.push(line); },
2385 attach: function(line) { this.marker.set.push(line); },
2055 detach: function(line) {
2386 detach: function(line) {
2056 var ix = indexOf(this.set, line);
2387 var ix = indexOf(this.marker.set, line);
2057 if (ix > -1) this.set.splice(ix, 1);
2388 if (ix > -1) this.marker.set.splice(ix, 1);
2058 },
2389 },
2059 split: function(pos, lenBefore) {
2390 split: function(pos, lenBefore) {
2060 if (this.to <= pos && this.to != null) return null;
2391 if (this.to <= pos && this.to != null) return null;
2061 var from = this.from < pos || this.from == null ? null : this.from - pos + lenBefore;
2392 var from = this.from < pos || this.from == null ? null : this.from - pos + lenBefore;
2062 var to = this.to == null ? null : this.to - pos + lenBefore;
2393 var to = this.to == null ? null : this.to - pos + lenBefore;
2063 return new MarkedText(from, to, this.style, this.set);
2394 return new MarkedText(from, to, this.style, this.marker);
2064 },
2395 },
2065 dup: function() { return new MarkedText(null, null, this.style, this.set); },
2396 dup: function() { return new MarkedText(null, null, this.style, this.marker); },
2066 clipTo: function(fromOpen, from, toOpen, to, diff) {
2397 clipTo: function(fromOpen, from, toOpen, to, diff) {
2067 if (this.from != null && this.from >= from)
2068 this.from = Math.max(to, this.from) + diff;
2069 if (this.to != null && this.to > from)
2070 this.to = to < this.to ? this.to + diff : from;
2071 if (fromOpen && to > this.from && (to < this.to || this.to == null))
2398 if (fromOpen && to > this.from && (to < this.to || this.to == null))
2072 this.from = null;
2399 this.from = null;
2400 else if (this.from != null && this.from >= from)
2401 this.from = Math.max(to, this.from) + diff;
2073 if (toOpen && (from < this.to || this.to == null) && (from > this.from || this.from == null))
2402 if (toOpen && (from < this.to || this.to == null) && (from > this.from || this.from == null))
2074 this.to = null;
2403 this.to = null;
2404 else if (this.to != null && this.to > from)
2405 this.to = to < this.to ? this.to + diff : from;
2075 },
2406 },
2076 isDead: function() { return this.from != null && this.to != null && this.from >= this.to; },
2407 isDead: function() { return this.from != null && this.to != null && this.from >= this.to; },
2077 sameSet: function(x) { return this.set == x.set; }
2408 sameSet: function(x) { return this.marker == x.marker; }
2078 };
2409 };
2079
2410
2080 function Bookmark(pos) {
2411 function Bookmark(pos) {
@@ -2117,7 +2448,7 var CodeMirror = (function() {
2117 this.styles = styles || [text, null];
2448 this.styles = styles || [text, null];
2118 this.text = text;
2449 this.text = text;
2119 this.height = 1;
2450 this.height = 1;
2120 this.marked = this.gutterMarker = this.className = this.handlers = null;
2451 this.marked = this.gutterMarker = this.className = this.bgClassName = this.handlers = null;
2121 this.stateAfter = this.parent = this.hidden = null;
2452 this.stateAfter = this.parent = this.hidden = null;
2122 }
2453 }
2123 Line.inheritMarks = function(text, orig) {
2454 Line.inheritMarks = function(text, orig) {
@@ -2163,6 +2494,7 var CodeMirror = (function() {
2163 if (newmark) {
2494 if (newmark) {
2164 if (!taken.marked) taken.marked = [];
2495 if (!taken.marked) taken.marked = [];
2165 taken.marked.push(newmark); newmark.attach(taken);
2496 taken.marked.push(newmark); newmark.attach(taken);
2497 if (newmark == mark) mk.splice(i--, 1);
2166 }
2498 }
2167 }
2499 }
2168 }
2500 }
@@ -2203,11 +2535,20 var CodeMirror = (function() {
2203 fixMarkEnds: function(other) {
2535 fixMarkEnds: function(other) {
2204 var mk = this.marked, omk = other.marked;
2536 var mk = this.marked, omk = other.marked;
2205 if (!mk) return;
2537 if (!mk) return;
2206 for (var i = 0; i < mk.length; ++i) {
2538 outer: for (var i = 0; i < mk.length; ++i) {
2207 var mark = mk[i], close = mark.to == null;
2539 var mark = mk[i], close = mark.to == null;
2208 if (close && omk) {
2540 if (close && omk) {
2209 for (var j = 0; j < omk.length; ++j)
2541 for (var j = 0; j < omk.length; ++j) {
2210 if (omk[j].sameSet(mark)) {close = false; break;}
2542 var om = omk[j];
2543 if (!om.sameSet(mark) || om.from != null) continue
2544 if (mark.from == this.text.length && om.to == 0) {
2545 omk.splice(j, 1);
2546 mk.splice(i--, 1);
2547 continue outer;
2548 } else {
2549 close = false; break;
2550 }
2551 }
2211 }
2552 }
2212 if (close) mark.to = this.text.length;
2553 if (close) mark.to = this.text.length;
2213 }
2554 }
@@ -2272,34 +2613,87 var CodeMirror = (function() {
2272 indentation: function(tabSize) {return countColumn(this.text, null, tabSize);},
2613 indentation: function(tabSize) {return countColumn(this.text, null, tabSize);},
2273 // Produces an HTML fragment for the line, taking selection,
2614 // Produces an HTML fragment for the line, taking selection,
2274 // marking, and highlighting into account.
2615 // marking, and highlighting into account.
2275 getHTML: function(tabText, endAt) {
2616 getHTML: function(makeTab, wrapAt, wrapId, wrapWBR) {
2276 var html = [], first = true;
2617 var html = [], first = true, col = 0;
2277 function span(text, style) {
2618 function span_(text, style) {
2278 if (!text) return;
2619 if (!text) return;
2279 // Work around a bug where, in some compat modes, IE ignores leading spaces
2620 // Work around a bug where, in some compat modes, IE ignores leading spaces
2280 if (first && ie && text.charAt(0) == " ") text = "\u00a0" + text.slice(1);
2621 if (first && ie && text.charAt(0) == " ") text = "\u00a0" + text.slice(1);
2281 first = false;
2622 first = false;
2282 if (style) html.push('<span class="', style, '">', htmlEscape(text).replace(/\t/g, tabText), "</span>");
2623 if (text.indexOf("\t") == -1) {
2283 else html.push(htmlEscape(text).replace(/\t/g, tabText));
2624 col += text.length;
2625 var escaped = htmlEscape(text);
2626 } else {
2627 var escaped = "";
2628 for (var pos = 0;;) {
2629 var idx = text.indexOf("\t", pos);
2630 if (idx == -1) {
2631 escaped += htmlEscape(text.slice(pos));
2632 col += text.length - pos;
2633 break;
2634 } else {
2635 col += idx - pos;
2636 var tab = makeTab(col);
2637 escaped += htmlEscape(text.slice(pos, idx)) + tab.html;
2638 col += tab.width;
2639 pos = idx + 1;
2640 }
2641 }
2642 }
2643 if (style) html.push('<span class="', style, '">', escaped, "</span>");
2644 else html.push(escaped);
2645 }
2646 var span = span_;
2647 if (wrapAt != null) {
2648 var outPos = 0, open = "<span id=\"" + wrapId + "\">";
2649 span = function(text, style) {
2650 var l = text.length;
2651 if (wrapAt >= outPos && wrapAt < outPos + l) {
2652 if (wrapAt > outPos) {
2653 span_(text.slice(0, wrapAt - outPos), style);
2654 // See comment at the definition of spanAffectsWrapping
2655 if (wrapWBR) html.push("<wbr>");
2656 }
2657 html.push(open);
2658 var cut = wrapAt - outPos;
2659 span_(opera ? text.slice(cut, cut + 1) : text.slice(cut), style);
2660 html.push("</span>");
2661 if (opera) span_(text.slice(cut + 1), style);
2662 wrapAt--;
2663 outPos += l;
2664 } else {
2665 outPos += l;
2666 span_(text, style);
2667 // Output empty wrapper when at end of line
2668 // (Gecko and IE8+ do strange wrapping when adding a space
2669 // to the end of the line. Other browsers don't react well
2670 // to zero-width spaces. So we do hideous browser sniffing
2671 // to determine which to use.)
2672 if (outPos == wrapAt && outPos == len)
2673 html.push(open + (gecko || (ie && !ie_lt8) ? "&#x200b;" : " ") + "</span>");
2674 // Stop outputting HTML when gone sufficiently far beyond measure
2675 else if (outPos > wrapAt + 10 && /\s/.test(text)) span = function(){};
2676 }
2677 }
2284 }
2678 }
2679
2285 var st = this.styles, allText = this.text, marked = this.marked;
2680 var st = this.styles, allText = this.text, marked = this.marked;
2286 var len = allText.length;
2681 var len = allText.length;
2287 if (endAt != null) len = Math.min(endAt, len);
2288 function styleToClass(style) {
2682 function styleToClass(style) {
2289 if (!style) return null;
2683 if (!style) return null;
2290 return "cm-" + style.replace(/ +/g, " cm-");
2684 return "cm-" + style.replace(/ +/g, " cm-");
2291 }
2685 }
2292
2686
2293 if (!allText && endAt == null)
2687 if (!allText && wrapAt == null) {
2294 span(" ");
2688 span(" ");
2295 else if (!marked || !marked.length)
2689 } else if (!marked || !marked.length) {
2296 for (var i = 0, ch = 0; ch < len; i+=2) {
2690 for (var i = 0, ch = 0; ch < len; i+=2) {
2297 var str = st[i], style = st[i+1], l = str.length;
2691 var str = st[i], style = st[i+1], l = str.length;
2298 if (ch + l > len) str = str.slice(0, len - ch);
2692 if (ch + l > len) str = str.slice(0, len - ch);
2299 ch += l;
2693 ch += l;
2300 span(str, styleToClass(style));
2694 span(str, styleToClass(style));
2301 }
2695 }
2302 else {
2696 } else {
2303 var pos = 0, i = 0, text = "", style, sg = 0;
2697 var pos = 0, i = 0, text = "", style, sg = 0;
2304 var nextChange = marked[0].from || 0, marks = [], markpos = 0;
2698 var nextChange = marked[0].from || 0, marks = [], markpos = 0;
2305 function advanceMarks() {
2699 function advanceMarks() {
@@ -2311,7 +2705,8 var CodeMirror = (function() {
2311 }
2705 }
2312 nextChange = markpos < marked.length ? marked[markpos].from : Infinity;
2706 nextChange = markpos < marked.length ? marked[markpos].from : Infinity;
2313 for (var i = 0; i < marks.length; ++i) {
2707 for (var i = 0; i < marks.length; ++i) {
2314 var to = marks[i].to || Infinity;
2708 var to = marks[i].to;
2709 if (to == null) to = Infinity;
2315 if (to == pos) marks.splice(i--, 1);
2710 if (to == pos) marks.splice(i--, 1);
2316 else nextChange = Math.min(to, nextChange);
2711 else nextChange = Math.min(to, nextChange);
2317 }
2712 }
@@ -2349,8 +2744,7 var CodeMirror = (function() {
2349 if (state == 0) {
2744 if (state == 0) {
2350 if (end > from) dest.push(part.slice(from - pos, Math.min(part.length, to - pos)), source[i+1]);
2745 if (end > from) dest.push(part.slice(from - pos, Math.min(part.length, to - pos)), source[i+1]);
2351 if (end >= from) state = 1;
2746 if (end >= from) state = 1;
2352 }
2747 } else if (state == 1) {
2353 else if (state == 1) {
2354 if (end > to) dest.push(part.slice(0, to - pos), source[i+1]);
2748 if (end > to) dest.push(part.slice(0, to - pos), source[i+1]);
2355 else dest.push(part, source[i+1]);
2749 else dest.push(part, source[i+1]);
2356 }
2750 }
@@ -2385,7 +2779,7 var CodeMirror = (function() {
2385 },
2779 },
2386 insertHeight: function(at, lines, height) {
2780 insertHeight: function(at, lines, height) {
2387 this.height += height;
2781 this.height += height;
2388 this.lines.splice.apply(this.lines, [at, 0].concat(lines));
2782 this.lines = this.lines.slice(0, at).concat(lines).concat(this.lines.slice(at));
2389 for (var i = 0, e = lines.length; i < e; ++i) lines[i].parent = this;
2783 for (var i = 0, e = lines.length; i < e; ++i) lines[i].parent = this;
2390 },
2784 },
2391 iterN: function(at, n, op) {
2785 iterN: function(at, n, op) {
@@ -2551,33 +2945,36 var CodeMirror = (function() {
2551 function History() {
2945 function History() {
2552 this.time = 0;
2946 this.time = 0;
2553 this.done = []; this.undone = [];
2947 this.done = []; this.undone = [];
2948 this.compound = 0;
2949 this.closed = false;
2554 }
2950 }
2555 History.prototype = {
2951 History.prototype = {
2556 addChange: function(start, added, old) {
2952 addChange: function(start, added, old) {
2557 this.undone.length = 0;
2953 this.undone.length = 0;
2558 var time = +new Date, cur = this.done[this.done.length - 1], last = cur && cur[cur.length - 1];
2954 var time = +new Date, cur = this.done[this.done.length - 1], last = cur && cur[cur.length - 1];
2559 var dtime = time - this.time;
2955 var dtime = time - this.time;
2560 if (dtime > 400 || !last) {
2956
2561 this.done.push([{start: start, added: added, old: old}]);
2957 if (this.compound && cur && !this.closed) {
2562 } else if (last.start > start + added || last.start + last.added < start - last.added + last.old.length) {
2563 cur.push({start: start, added: added, old: old});
2958 cur.push({start: start, added: added, old: old});
2959 } else if (dtime > 400 || !last || this.closed ||
2960 last.start > start + old.length || last.start + last.added < start) {
2961 this.done.push([{start: start, added: added, old: old}]);
2962 this.closed = false;
2564 } else {
2963 } else {
2565 var oldoff = 0;
2964 var startBefore = Math.max(0, last.start - start),
2566 if (start < last.start) {
2965 endAfter = Math.max(0, (start + old.length) - (last.start + last.added));
2567 for (var i = last.start - start - 1; i >= 0; --i)
2966 for (var i = startBefore; i > 0; --i) last.old.unshift(old[i - 1]);
2568 last.old.unshift(old[i]);
2967 for (var i = endAfter; i > 0; --i) last.old.push(old[old.length - i]);
2569 last.added += last.start - start;
2968 if (startBefore) last.start = start;
2570 last.start = start;
2969 last.added += added - (old.length - startBefore - endAfter);
2571 }
2572 else if (last.start < start) {
2573 oldoff = start - last.start;
2574 added += oldoff;
2575 }
2576 for (var i = last.added - oldoff, e = old.length; i < e; ++i)
2577 last.old.push(old[i]);
2578 if (last.added < added) last.added = added;
2579 }
2970 }
2580 this.time = time;
2971 this.time = time;
2972 },
2973 startCompound: function() {
2974 if (!this.compound++) this.closed = true;
2975 },
2976 endCompound: function() {
2977 if (!--this.compound) this.closed = true;
2581 }
2978 }
2582 };
2979 };
2583
2980
@@ -2603,10 +3000,14 var CodeMirror = (function() {
2603
3000
2604 function e_target(e) {return e.target || e.srcElement;}
3001 function e_target(e) {return e.target || e.srcElement;}
2605 function e_button(e) {
3002 function e_button(e) {
2606 if (e.which) return e.which;
3003 var b = e.which;
2607 else if (e.button & 1) return 1;
3004 if (b == null) {
2608 else if (e.button & 2) return 3;
3005 if (e.button & 1) b = 1;
2609 else if (e.button & 4) return 2;
3006 else if (e.button & 2) b = 3;
3007 else if (e.button & 4) b = 2;
3008 }
3009 if (mac && e.ctrlKey && b == 1) b = 3;
3010 return b;
2610 }
3011 }
2611
3012
2612 // Allow 3rd-party code to override event properties by adding an override
3013 // Allow 3rd-party code to override event properties by adding an override
@@ -2622,8 +3023,7 var CodeMirror = (function() {
2622 if (typeof node.addEventListener == "function") {
3023 if (typeof node.addEventListener == "function") {
2623 node.addEventListener(type, handler, false);
3024 node.addEventListener(type, handler, false);
2624 if (disconnect) return function() {node.removeEventListener(type, handler, false);};
3025 if (disconnect) return function() {node.removeEventListener(type, handler, false);};
2625 }
3026 } else {
2626 else {
2627 var wrapHandler = function(event) {handler(event || window.event);};
3027 var wrapHandler = function(event) {handler(event || window.event);};
2628 node.attachEvent("on" + type, wrapHandler);
3028 node.attachEvent("on" + type, wrapHandler);
2629 if (disconnect) return function() {node.detachEvent("on" + type, wrapHandler);};
3029 if (disconnect) return function() {node.detachEvent("on" + type, wrapHandler);};
@@ -2634,26 +3034,48 var CodeMirror = (function() {
2634 function Delayed() {this.id = null;}
3034 function Delayed() {this.id = null;}
2635 Delayed.prototype = {set: function(ms, f) {clearTimeout(this.id); this.id = setTimeout(f, ms);}};
3035 Delayed.prototype = {set: function(ms, f) {clearTimeout(this.id); this.id = setTimeout(f, ms);}};
2636
3036
2637 // Detect drag-and-drop
3037 var Pass = CodeMirror.Pass = {toString: function(){return "CodeMirror.Pass";}};
2638 var dragAndDrop = function() {
2639 // IE8 has ondragstart and ondrop properties, but doesn't seem to
2640 // actually support ondragstart the way it's supposed to work.
2641 if (/MSIE [1-8]\b/.test(navigator.userAgent)) return false;
2642 var div = document.createElement('div');
2643 return "draggable" in div;
2644 }();
2645
3038
2646 var gecko = /gecko\/\d{7}/i.test(navigator.userAgent);
3039 var gecko = /gecko\/\d{7}/i.test(navigator.userAgent);
2647 var ie = /MSIE \d/.test(navigator.userAgent);
3040 var ie = /MSIE \d/.test(navigator.userAgent);
3041 var ie_lt8 = /MSIE [1-7]\b/.test(navigator.userAgent);
3042 var ie_lt9 = /MSIE [1-8]\b/.test(navigator.userAgent);
3043 var quirksMode = ie && document.documentMode == 5;
2648 var webkit = /WebKit\//.test(navigator.userAgent);
3044 var webkit = /WebKit\//.test(navigator.userAgent);
3045 var chrome = /Chrome\//.test(navigator.userAgent);
3046 var opera = /Opera\//.test(navigator.userAgent);
3047 var safari = /Apple Computer/.test(navigator.vendor);
3048 var khtml = /KHTML\//.test(navigator.userAgent);
3049 var mac_geLion = /Mac OS X 10\D([7-9]|\d\d)\D/.test(navigator.userAgent);
3050
3051 // Detect drag-and-drop
3052 var dragAndDrop = function() {
3053 // There is *some* kind of drag-and-drop support in IE6-8, but I
3054 // couldn't get it to work yet.
3055 if (ie_lt9) return false;
3056 var div = document.createElement('div');
3057 return "draggable" in div || "dragDrop" in div;
3058 }();
2649
3059
2650 var lineSep = "\n";
2651 // Feature-detect whether newlines in textareas are converted to \r\n
3060 // Feature-detect whether newlines in textareas are converted to \r\n
2652 (function () {
3061 var lineSep = function () {
2653 var te = document.createElement("textarea");
3062 var te = document.createElement("textarea");
2654 te.value = "foo\nbar";
3063 te.value = "foo\nbar";
2655 if (te.value.indexOf("\r") > -1) lineSep = "\r\n";
3064 if (te.value.indexOf("\r") > -1) return "\r\n";
2656 }());
3065 return "\n";
3066 }();
3067
3068 // For a reason I have yet to figure out, some browsers disallow
3069 // word wrapping between certain characters *only* if a new inline
3070 // element is started between them. This makes it hard to reliably
3071 // measure the position of things, since that requires inserting an
3072 // extra span. This terribly fragile set of regexps matches the
3073 // character combinations that suffer from this phenomenon on the
3074 // various browsers.
3075 var spanAffectsWrapping = /^$/; // Won't match any two-character string
3076 if (gecko) spanAffectsWrapping = /$'/;
3077 else if (safari) spanAffectsWrapping = /\-[^ \-?]|\?[^ !'\"\),.\-\/:;\?\]\}]/;
3078 else if (chrome) spanAffectsWrapping = /\-[^ \-\.?]|\?[^ \-\.?\]\}:;!'\"\),\/]|[\.!\"#&%\)*+,:;=>\]|\}~][\(\{\[<]|\$'/;
2657
3079
2658 // Counts the column offset in a string, taking tabs into account.
3080 // Counts the column offset in a string, taking tabs into account.
2659 // Used mostly to find indentation.
3081 // Used mostly to find indentation.
@@ -2674,26 +3096,7 var CodeMirror = (function() {
2674 return window.getComputedStyle(elt, null);
3096 return window.getComputedStyle(elt, null);
2675 }
3097 }
2676
3098
2677 // Find the position of an element by following the offsetParent chain.
2678 // If screen==true, it returns screen (rather than page) coordinates.
2679 function eltOffset(node, screen) {
3099 function eltOffset(node, screen) {
2680 var bod = node.ownerDocument.body;
2681 var x = 0, y = 0, skipBody = false;
2682 for (var n = node; n; n = n.offsetParent) {
2683 var ol = n.offsetLeft, ot = n.offsetTop;
2684 // Firefox reports weird inverted offsets when the body has a border.
2685 if (n == bod) { x += Math.abs(ol); y += Math.abs(ot); }
2686 else { x += ol, y += ot; }
2687 if (screen && computedStyle(n).position == "fixed")
2688 skipBody = true;
2689 }
2690 var e = screen && !skipBody ? null : bod;
2691 for (var n = node.parentNode; n != e; n = n.parentNode)
2692 if (n.scrollLeft != null) { x -= n.scrollLeft; y -= n.scrollTop;}
2693 return {left: x, top: y};
2694 }
2695 // Use the faster and saner getBoundingClientRect method when possible.
2696 if (document.documentElement.getBoundingClientRect != null) eltOffset = function(node, screen) {
2697 // Take the parts of bounding client rect that we are interested in so we are able to edit if need be,
3100 // Take the parts of bounding client rect that we are interested in so we are able to edit if need be,
2698 // since the returned value cannot be changed externally (they are kept in sync as the element moves within the page)
3101 // since the returned value cannot be changed externally (they are kept in sync as the element moves within the page)
2699 try { var box = node.getBoundingClientRect(); box = { top: box.top, left: box.left }; }
3102 try { var box = node.getBoundingClientRect(); box = { top: box.top, left: box.left }; }
@@ -2709,7 +3112,7 var CodeMirror = (function() {
2709 }
3112 }
2710 }
3113 }
2711 return box;
3114 return box;
2712 };
3115 }
2713
3116
2714 // Get a node's text content.
3117 // Get a node's text content.
2715 function eltText(node) {
3118 function eltText(node) {
@@ -2734,18 +3137,19 var CodeMirror = (function() {
2734 }
3137 }
2735 // Recent (late 2011) Opera betas insert bogus newlines at the start
3138 // Recent (late 2011) Opera betas insert bogus newlines at the start
2736 // of the textContent, so we strip those.
3139 // of the textContent, so we strip those.
2737 if (htmlEscape("a") == "\na")
3140 if (htmlEscape("a") == "\na") {
2738 htmlEscape = function(str) {
3141 htmlEscape = function(str) {
2739 escapeElement.textContent = str;
3142 escapeElement.textContent = str;
2740 return escapeElement.innerHTML.slice(1);
3143 return escapeElement.innerHTML.slice(1);
2741 };
3144 };
2742 // Some IEs don't preserve tabs through innerHTML
3145 // Some IEs don't preserve tabs through innerHTML
2743 else if (htmlEscape("\t") != "\t")
3146 } else if (htmlEscape("\t") != "\t") {
2744 htmlEscape = function(str) {
3147 htmlEscape = function(str) {
2745 escapeElement.innerHTML = "";
3148 escapeElement.innerHTML = "";
2746 escapeElement.appendChild(document.createTextNode(str));
3149 escapeElement.appendChild(document.createTextNode(str));
2747 return escapeElement.innerHTML;
3150 return escapeElement.innerHTML;
2748 };
3151 };
3152 }
2749 CodeMirror.htmlEscape = htmlEscape;
3153 CodeMirror.htmlEscape = htmlEscape;
2750
3154
2751 // Used to position the cursor after an undo/redo by finding the
3155 // Used to position the cursor after an undo/redo by finding the
@@ -2771,14 +3175,22 var CodeMirror = (function() {
2771 // See if "".split is the broken IE version, if so, provide an
3175 // See if "".split is the broken IE version, if so, provide an
2772 // alternative way to split lines.
3176 // alternative way to split lines.
2773 var splitLines = "\n\nb".split(/\n/).length != 3 ? function(string) {
3177 var splitLines = "\n\nb".split(/\n/).length != 3 ? function(string) {
2774 var pos = 0, nl, result = [];
3178 var pos = 0, result = [], l = string.length;
2775 while ((nl = string.indexOf("\n", pos)) > -1) {
3179 while (pos <= l) {
2776 result.push(string.slice(pos, string.charAt(nl-1) == "\r" ? nl - 1 : nl));
3180 var nl = string.indexOf("\n", pos);
2777 pos = nl + 1;
3181 if (nl == -1) nl = string.length;
3182 var line = string.slice(pos, string.charAt(nl - 1) == "\r" ? nl - 1 : nl);
3183 var rt = line.indexOf("\r");
3184 if (rt != -1) {
3185 result.push(line.slice(0, rt));
3186 pos += rt + 1;
3187 } else {
3188 result.push(line);
3189 pos = nl + 1;
3190 }
2778 }
3191 }
2779 result.push(string.slice(pos));
2780 return result;
3192 return result;
2781 } : function(string){return string.split(/\r?\n/);};
3193 } : function(string){return string.split(/\r\n?|\n/);};
2782 CodeMirror.splitLines = splitLines;
3194 CodeMirror.splitLines = splitLines;
2783
3195
2784 var hasSelection = window.getSelection ? function(te) {
3196 var hasSelection = window.getSelection ? function(te) {
@@ -2799,10 +3211,10 var CodeMirror = (function() {
2799 var keyNames = {3: "Enter", 8: "Backspace", 9: "Tab", 13: "Enter", 16: "Shift", 17: "Ctrl", 18: "Alt",
3211 var keyNames = {3: "Enter", 8: "Backspace", 9: "Tab", 13: "Enter", 16: "Shift", 17: "Ctrl", 18: "Alt",
2800 19: "Pause", 20: "CapsLock", 27: "Esc", 32: "Space", 33: "PageUp", 34: "PageDown", 35: "End",
3212 19: "Pause", 20: "CapsLock", 27: "Esc", 32: "Space", 33: "PageUp", 34: "PageDown", 35: "End",
2801 36: "Home", 37: "Left", 38: "Up", 39: "Right", 40: "Down", 44: "PrintScrn", 45: "Insert",
3213 36: "Home", 37: "Left", 38: "Up", 39: "Right", 40: "Down", 44: "PrintScrn", 45: "Insert",
2802 46: "Delete", 59: ";", 91: "Mod", 92: "Mod", 93: "Mod", 186: ";", 187: "=", 188: ",",
3214 46: "Delete", 59: ";", 91: "Mod", 92: "Mod", 93: "Mod", 109: "-", 107: "=", 127: "Delete",
2803 189: "-", 190: ".", 191: "/", 192: "`", 219: "[", 220: "\\", 221: "]", 222: "'", 63276: "PageUp",
3215 186: ";", 187: "=", 188: ",", 189: "-", 190: ".", 191: "/", 192: "`", 219: "[", 220: "\\",
2804 63277: "PageDown", 63275: "End", 63273: "Home", 63234: "Left", 63232: "Up", 63235: "Right",
3216 221: "]", 222: "'", 63276: "PageUp", 63277: "PageDown", 63275: "End", 63273: "Home",
2805 63233: "Down", 63302: "Insert", 63272: "Delete"};
3217 63234: "Left", 63232: "Up", 63235: "Right", 63233: "Down", 63302: "Insert", 63272: "Delete"};
2806 CodeMirror.keyNames = keyNames;
3218 CodeMirror.keyNames = keyNames;
2807 (function() {
3219 (function() {
2808 // Number keys
3220 // Number keys
@@ -21,3 +21,7
21 color: inherit;
21 color: inherit;
22 font-family: monospace;
22 font-family: monospace;
23 }
23 }
24
25 .CodeMirror-dialog button {
26 font-size: 70%;
27 } No newline at end of file
@@ -17,7 +17,7
17 closed = true;
17 closed = true;
18 dialog.parentNode.removeChild(dialog);
18 dialog.parentNode.removeChild(dialog);
19 }
19 }
20 var inp = dialog.getElementsByTagName("input")[0];
20 var inp = dialog.getElementsByTagName("input")[0], button;
21 if (inp) {
21 if (inp) {
22 CodeMirror.connect(inp, "keydown", function(e) {
22 CodeMirror.connect(inp, "keydown", function(e) {
23 if (e.keyCode == 13 || e.keyCode == 27) {
23 if (e.keyCode == 13 || e.keyCode == 27) {
@@ -29,6 +29,10
29 });
29 });
30 inp.focus();
30 inp.focus();
31 CodeMirror.connect(inp, "blur", close);
31 CodeMirror.connect(inp, "blur", close);
32 } else if (button = dialog.getElementsByTagName("button")[0]) {
33 CodeMirror.connect(button, "click", close);
34 button.focus();
35 CodeMirror.connect(button, "blur", close);
32 }
36 }
33 return close;
37 return close;
34 });
38 });
@@ -1,9 +1,9
1 // the tagRangeFinder function is
1 // the tagRangeFinder function is
2 // Copyright (C) 2011 by Daniel Glazman <daniel@glazman.org>
2 // Copyright (C) 2011 by Daniel Glazman <daniel@glazman.org>
3 // released under the MIT license (../../LICENSE) like the rest of CodeMirror
3 // released under the MIT license (../../LICENSE) like the rest of CodeMirror
4 CodeMirror.tagRangeFinder = function(cm, line) {
4 CodeMirror.tagRangeFinder = function(cm, line, hideEnd) {
5 var nameStartChar = "A-Z_a-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD";
5 var nameStartChar = "A-Z_a-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD";
6 var nameChar = nameStartChar + "\-\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040";
6 var nameChar = nameStartChar + "\-\:\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040";
7 var xmlNAMERegExp = new RegExp("^[" + nameStartChar + "][" + nameChar + "]*");
7 var xmlNAMERegExp = new RegExp("^[" + nameStartChar + "][" + nameChar + "]*");
8
8
9 var lineText = cm.getLine(line);
9 var lineText = cm.getLine(line);
@@ -36,8 +36,10 CodeMirror.tagRangeFinder = function(cm, line) {
36 var slash = lt.lastIndexOf("/", gt);
36 var slash = lt.lastIndexOf("/", gt);
37 if (-1 != slash && slash < gt) {
37 if (-1 != slash && slash < gt) {
38 var str = lineText.substr(slash, gt - slash + 1);
38 var str = lineText.substr(slash, gt - slash + 1);
39 if (!str.match( /\/\s*\>/ )) // yep, that's the end of empty tag
39 if (!str.match( /\/\s*\>/ )) { // yep, that's the end of empty tag
40 return l+1;
40 if (hideEnd === true) l++;
41 return l;
42 }
41 }
43 }
42 }
44 }
43 l++;
45 l++;
@@ -80,7 +82,7 CodeMirror.tagRangeFinder = function(cm, line) {
80 }
82 }
81
83
82 if (found) {
84 if (found) {
83 var startTag = "(\\<\\/" + tag + "\\>)|(\\<" + tag + "\\>)|(\\<" + tag + "\s)|(\\<" + tag + "$)";
85 var startTag = "(\\<\\/" + tag + "\\>)|(\\<" + tag + "\\>)|(\\<" + tag + "\\s)|(\\<" + tag + "$)";
84 var startTagRegExp = new RegExp(startTag, "g");
86 var startTagRegExp = new RegExp(startTag, "g");
85 var endTag = "</" + tag + ">";
87 var endTag = "</" + tag + ">";
86 var depth = 1;
88 var depth = 1;
@@ -95,8 +97,10 CodeMirror.tagRangeFinder = function(cm, line) {
95 depth--;
97 depth--;
96 else
98 else
97 depth++;
99 depth++;
98 if (!depth)
100 if (!depth) {
99 return l+1;
101 if (hideEnd === true) l++;
102 return l;
103 }
100 }
104 }
101 }
105 }
102 l++;
106 l++;
@@ -105,11 +109,16 CodeMirror.tagRangeFinder = function(cm, line) {
105 }
109 }
106 };
110 };
107
111
108 CodeMirror.braceRangeFinder = function(cm, line) {
112 CodeMirror.braceRangeFinder = function(cm, line, hideEnd) {
109 var lineText = cm.getLine(line);
113 var lineText = cm.getLine(line), at = lineText.length, startChar, tokenType;
110 var startChar = lineText.lastIndexOf("{");
114 for (;;) {
111 if (startChar < 0 || lineText.lastIndexOf("}") > startChar) return;
115 var found = lineText.lastIndexOf("{", at);
112 var tokenType = cm.getTokenAt({line: line, ch: startChar}).className;
116 if (found < 0) break;
117 tokenType = cm.getTokenAt({line: line, ch: found}).className;
118 if (!/^(comment|string)/.test(tokenType)) { startChar = found; break; }
119 at = found - 1;
120 }
121 if (startChar == null || lineText.lastIndexOf("}") > startChar) return;
113 var count = 1, lastLine = cm.lineCount(), end;
122 var count = 1, lastLine = cm.lineCount(), end;
114 outer: for (var i = line + 1; i < lastLine; ++i) {
123 outer: for (var i = line + 1; i < lastLine; ++i) {
115 var text = cm.getLine(i), pos = 0;
124 var text = cm.getLine(i), pos = 0;
@@ -127,11 +136,25 CodeMirror.braceRangeFinder = function(cm, line) {
127 }
136 }
128 }
137 }
129 if (end == null || end == line + 1) return;
138 if (end == null || end == line + 1) return;
139 if (hideEnd === true) end++;
130 return end;
140 return end;
131 };
141 };
132
142
143 CodeMirror.indentRangeFinder = function(cm, line) {
144 var tabSize = cm.getOption("tabSize");
145 var myIndent = cm.getLineHandle(line).indentation(tabSize), last;
146 for (var i = line + 1, end = cm.lineCount(); i < end; ++i) {
147 var handle = cm.getLineHandle(i);
148 if (!/^\s*$/.test(handle.text)) {
149 if (handle.indentation(tabSize) <= myIndent) break;
150 last = i;
151 }
152 }
153 if (!last) return null;
154 return last + 1;
155 };
133
156
134 CodeMirror.newFoldFunction = function(rangeFinder, markText) {
157 CodeMirror.newFoldFunction = function(rangeFinder, markText, hideEnd) {
135 var folded = [];
158 var folded = [];
136 if (markText == null) markText = '<div style="position: absolute; left: 2px; color:#600">&#x25bc;</div>%N%';
159 if (markText == null) markText = '<div style="position: absolute; left: 2px; color:#600">&#x25bc;</div>%N%';
137
160
@@ -156,7 +179,7 CodeMirror.newFoldFunction = function(rangeFinder, markText) {
156 folded.splice(known.pos, 1);
179 folded.splice(known.pos, 1);
157 expand(cm, known.region);
180 expand(cm, known.region);
158 } else {
181 } else {
159 var end = rangeFinder(cm, line);
182 var end = rangeFinder(cm, line, hideEnd);
160 if (end == null) return;
183 if (end == null) return;
161 var hidden = [];
184 var hidden = [];
162 for (var i = line + 1; i < end; ++i) {
185 for (var i = line + 1; i < end; ++i) {
@@ -1,10 +1,13
1 // ============== Formatting extensions ============================
1 // ============== Formatting extensions ============================
2 // A common storage for all mode-specific formatting features
2 // A common storage for all mode-specific formatting features
3 if (!CodeMirror.modeExtensions) CodeMirror.modeExtensions = {};
3 if (!CodeMirror.modeExtensions) CodeMirror.modeExtensions = {};
4
4
5 // Returns the extension of the editor's current mode
5 // Returns the extension of the editor's current mode
6 CodeMirror.defineExtension("getModeExt", function () {
6 CodeMirror.defineExtension("getModeExt", function () {
7 return CodeMirror.modeExtensions[this.getOption("mode")];
7 var mname = CodeMirror.resolveMode(this.getOption("mode")).name;
8 var ext = CodeMirror.modeExtensions[mname];
9 if (!ext) throw new Error("No extensions found for mode " + mname);
10 return ext;
8 });
11 });
9
12
10 // If the current mode is 'htmlmixed', returns the extension of a mode located at
13 // If the current mode is 'htmlmixed', returns the extension of a mode located at
@@ -81,7 +84,8 CodeMirror.modeExtensions["css"] = {
81 commentStart: "/*",
84 commentStart: "/*",
82 commentEnd: "*/",
85 commentEnd: "*/",
83 wordWrapChars: [";", "\\{", "\\}"],
86 wordWrapChars: [";", "\\{", "\\}"],
84 autoFormatLineBreaks: function (text) {
87 autoFormatLineBreaks: function (text, startPos, endPos) {
88 text = text.substring(startPos, endPos);
85 return text.replace(new RegExp("(;|\\{|\\})([^\r\n])", "g"), "$1\n$2");
89 return text.replace(new RegExp("(;|\\{|\\})([^\r\n])", "g"), "$1\n$2");
86 }
90 }
87 };
91 };
@@ -94,6 +98,8 CodeMirror.modeExtensions["javascript"] = {
94 getNonBreakableBlocks: function (text) {
98 getNonBreakableBlocks: function (text) {
95 var nonBreakableRegexes = [
99 var nonBreakableRegexes = [
96 new RegExp("for\\s*?\\(([\\s\\S]*?)\\)"),
100 new RegExp("for\\s*?\\(([\\s\\S]*?)\\)"),
101 new RegExp("\\\\\"([\\s\\S]*?)(\\\\\"|$)"),
102 new RegExp("\\\\\'([\\s\\S]*?)(\\\\\'|$)"),
97 new RegExp("'([\\s\\S]*?)('|$)"),
103 new RegExp("'([\\s\\S]*?)('|$)"),
98 new RegExp("\"([\\s\\S]*?)(\"|$)"),
104 new RegExp("\"([\\s\\S]*?)(\"|$)"),
99 new RegExp("//.*([\r\n]|$)")
105 new RegExp("//.*([\r\n]|$)")
@@ -122,7 +128,8 CodeMirror.modeExtensions["javascript"] = {
122 return nonBreakableBlocks;
128 return nonBreakableBlocks;
123 },
129 },
124
130
125 autoFormatLineBreaks: function (text) {
131 autoFormatLineBreaks: function (text, startPos, endPos) {
132 text = text.substring(startPos, endPos);
126 var curPos = 0;
133 var curPos = 0;
127 var reLinesSplitter = new RegExp("(;|\\{|\\})([^\r\n])", "g");
134 var reLinesSplitter = new RegExp("(;|\\{|\\})([^\r\n])", "g");
128 var nonBreakableBlocks = this.getNonBreakableBlocks(text);
135 var nonBreakableBlocks = this.getNonBreakableBlocks(text);
@@ -155,7 +162,8 CodeMirror.modeExtensions["xml"] = {
155 commentEnd: "-->",
162 commentEnd: "-->",
156 wordWrapChars: [">"],
163 wordWrapChars: [">"],
157
164
158 autoFormatLineBreaks: function (text) {
165 autoFormatLineBreaks: function (text, startPos, endPos) {
166 text = text.substring(startPos, endPos);
159 var lines = text.split("\n");
167 var lines = text.split("\n");
160 var reProcessedPortion = new RegExp("(^\\s*?<|^[^<]*?)(.+)(>\\s*?$|[^>]*?$)");
168 var reProcessedPortion = new RegExp("(^\\s*?<|^[^<]*?)(.+)(>\\s*?$|[^>]*?$)");
161 var reOpenBrackets = new RegExp("<", "g");
169 var reOpenBrackets = new RegExp("<", "g");
@@ -15,37 +15,81
15 }
15 }
16 return arr.indexOf(item) != -1;
16 return arr.indexOf(item) != -1;
17 }
17 }
18
18
19 CodeMirror.javascriptHint = function(editor) {
19 function scriptHint(editor, keywords, getToken) {
20 // Find the token at the cursor
20 // Find the token at the cursor
21 var cur = editor.getCursor(), token = editor.getTokenAt(cur), tprop = token;
21 var cur = editor.getCursor(), token = getToken(editor, cur), tprop = token;
22 // If it's not a 'word-style' token, ignore the token.
22 // If it's not a 'word-style' token, ignore the token.
23 if (!/^[\w$_]*$/.test(token.string)) {
23 if (!/^[\w$_]*$/.test(token.string)) {
24 token = tprop = {start: cur.ch, end: cur.ch, string: "", state: token.state,
24 token = tprop = {start: cur.ch, end: cur.ch, string: "", state: token.state,
25 className: token.string == "." ? "property" : null};
25 className: token.string == "." ? "property" : null};
26 }
26 }
27 // If it is a property, find out what it is a property of.
27 // If it is a property, find out what it is a property of.
28 while (tprop.className == "property") {
28 while (tprop.className == "property") {
29 tprop = editor.getTokenAt({line: cur.line, ch: tprop.start});
29 tprop = getToken(editor, {line: cur.line, ch: tprop.start});
30 if (tprop.string != ".") return;
30 if (tprop.string != ".") return;
31 tprop = editor.getTokenAt({line: cur.line, ch: tprop.start});
31 tprop = getToken(editor, {line: cur.line, ch: tprop.start});
32 if (tprop.string == ')') {
33 var level = 1;
34 do {
35 tprop = getToken(editor, {line: cur.line, ch: tprop.start});
36 switch (tprop.string) {
37 case ')': level++; break;
38 case '(': level--; break;
39 default: break;
40 }
41 } while (level > 0)
42 tprop = getToken(editor, {line: cur.line, ch: tprop.start});
43 if (tprop.className == 'variable')
44 tprop.className = 'function';
45 else return; // no clue
46 }
32 if (!context) var context = [];
47 if (!context) var context = [];
33 context.push(tprop);
48 context.push(tprop);
34 }
49 }
35 return {list: getCompletions(token, context),
50 return {list: getCompletions(token, context, keywords),
36 from: {line: cur.line, ch: token.start},
51 from: {line: cur.line, ch: token.start},
37 to: {line: cur.line, ch: token.end}};
52 to: {line: cur.line, ch: token.end}};
38 }
53 }
39
54
55 CodeMirror.javascriptHint = function(editor) {
56 return scriptHint(editor, javascriptKeywords,
57 function (e, cur) {return e.getTokenAt(cur);});
58 }
59
60 function getCoffeeScriptToken(editor, cur) {
61 // This getToken, it is for coffeescript, imitates the behavior of
62 // getTokenAt method in javascript.js, that is, returning "property"
63 // type and treat "." as indepenent token.
64 var token = editor.getTokenAt(cur);
65 if (cur.ch == token.start + 1 && token.string.charAt(0) == '.') {
66 token.end = token.start;
67 token.string = '.';
68 token.className = "property";
69 }
70 else if (/^\.[\w$_]*$/.test(token.string)) {
71 token.className = "property";
72 token.start++;
73 token.string = token.string.replace(/\./, '');
74 }
75 return token;
76 }
77
78 CodeMirror.coffeescriptHint = function(editor) {
79 return scriptHint(editor, coffeescriptKeywords, getCoffeeScriptToken);
80 }
81
40 var stringProps = ("charAt charCodeAt indexOf lastIndexOf substring substr slice trim trimLeft trimRight " +
82 var stringProps = ("charAt charCodeAt indexOf lastIndexOf substring substr slice trim trimLeft trimRight " +
41 "toUpperCase toLowerCase split concat match replace search").split(" ");
83 "toUpperCase toLowerCase split concat match replace search").split(" ");
42 var arrayProps = ("length concat join splice push pop shift unshift slice reverse sort indexOf " +
84 var arrayProps = ("length concat join splice push pop shift unshift slice reverse sort indexOf " +
43 "lastIndexOf every some filter forEach map reduce reduceRight ").split(" ");
85 "lastIndexOf every some filter forEach map reduce reduceRight ").split(" ");
44 var funcProps = "prototype apply call bind".split(" ");
86 var funcProps = "prototype apply call bind".split(" ");
45 var keywords = ("break case catch continue debugger default delete do else false finally for function " +
87 var javascriptKeywords = ("break case catch continue debugger default delete do else false finally for function " +
46 "if in instanceof new null return switch throw true try typeof var void while with").split(" ");
88 "if in instanceof new null return switch throw true try typeof var void while with").split(" ");
89 var coffeescriptKeywords = ("and break catch class continue delete do else extends false finally for " +
90 "if in instanceof isnt new no not null of off on or return switch then throw true try typeof until void while with yes").split(" ");
47
91
48 function getCompletions(token, context) {
92 function getCompletions(token, context, keywords) {
49 var found = [], start = token.string;
93 var found = [], start = token.string;
50 function maybeAdd(str) {
94 function maybeAdd(str) {
51 if (str.indexOf(start) == 0 && !arrayContains(found, str)) found.push(str);
95 if (str.indexOf(start) == 0 && !arrayContains(found, str)) found.push(str);
@@ -67,6 +111,13
67 base = "";
111 base = "";
68 else if (obj.className == "atom")
112 else if (obj.className == "atom")
69 base = 1;
113 base = 1;
114 else if (obj.className == "function") {
115 if (window.jQuery != null && (obj.string == '$' || obj.string == 'jQuery') &&
116 (typeof window.jQuery == 'function'))
117 base = window.jQuery();
118 else if (window._ != null && (obj.string == '_') && (typeof window._ == 'function'))
119 base = window._();
120 }
70 while (base != null && context.length)
121 while (base != null && context.length)
71 base = base[context.pop().string];
122 base = base[context.pop().string];
72 if (base != null) gatherCompletions(base);
123 if (base != null) gatherCompletions(base);
@@ -6,7 +6,8
6 // overlay wins, unless the combine argument was true, in which case
6 // overlay wins, unless the combine argument was true, in which case
7 // the styles are combined.
7 // the styles are combined.
8
8
9 CodeMirror.overlayParser = function(base, overlay, combine) {
9 // overlayParser is the old, deprecated name
10 CodeMirror.overlayMode = CodeMirror.overlayParser = function(base, overlay, combine) {
10 return {
11 return {
11 startState: function() {
12 startState: function() {
12 return {
13 return {
@@ -43,7 +44,7 CodeMirror.overlayParser = function(base, overlay, combine) {
43 else return state.overlayCur;
44 else return state.overlayCur;
44 },
45 },
45
46
46 indent: function(state, textAfter) {
47 indent: base.indent && function(state, textAfter) {
47 return base.indent(state.base, textAfter);
48 return base.indent(state.base, textAfter);
48 },
49 },
49 electricChars: base.electricChars
50 electricChars: base.electricChars
@@ -1,15 +1,37
1 CodeMirror.runMode = function(string, modespec, callback) {
1 CodeMirror.runMode = function(string, modespec, callback, options) {
2 var mode = CodeMirror.getMode({indentUnit: 2}, modespec);
2 var mode = CodeMirror.getMode(CodeMirror.defaults, modespec);
3 var isNode = callback.nodeType == 1;
3 var isNode = callback.nodeType == 1;
4 var tabSize = (options && options.tabSize) || CodeMirror.defaults.tabSize;
4 if (isNode) {
5 if (isNode) {
5 var node = callback, accum = [];
6 var node = callback, accum = [], col = 0;
6 callback = function(string, style) {
7 callback = function(text, style) {
7 if (string == "\n")
8 if (text == "\n") {
8 accum.push("<br>");
9 accum.push("<br>");
9 else if (style)
10 col = 0;
10 accum.push("<span class=\"cm-" + CodeMirror.htmlEscape(style) + "\">" + CodeMirror.htmlEscape(string) + "</span>");
11 return;
12 }
13 var escaped = "";
14 // HTML-escape and replace tabs
15 for (var pos = 0;;) {
16 var idx = text.indexOf("\t", pos);
17 if (idx == -1) {
18 escaped += CodeMirror.htmlEscape(text.slice(pos));
19 col += text.length - pos;
20 break;
21 } else {
22 col += idx - pos;
23 escaped += CodeMirror.htmlEscape(text.slice(pos, idx));
24 var size = tabSize - col % tabSize;
25 col += size;
26 for (var i = 0; i < size; ++i) escaped += " ";
27 pos = idx + 1;
28 }
29 }
30
31 if (style)
32 accum.push("<span class=\"cm-" + CodeMirror.htmlEscape(style) + "\">" + escaped + "</span>");
11 else
33 else
12 accum.push(CodeMirror.htmlEscape(string));
34 accum.push(escaped);
13 }
35 }
14 }
36 }
15 var lines = CodeMirror.splitLines(string), state = CodeMirror.startState(mode);
37 var lines = CodeMirror.splitLines(string), state = CodeMirror.startState(mode);
@@ -14,6 +14,10
14 function getSearchState(cm) {
14 function getSearchState(cm) {
15 return cm._searchState || (cm._searchState = new SearchState());
15 return cm._searchState || (cm._searchState = new SearchState());
16 }
16 }
17 function getSearchCursor(cm, query, pos) {
18 // Heuristic: if the query string is all lowercase, do a case insensitive search.
19 return cm.getSearchCursor(query, pos, typeof query == "string" && query == query.toLowerCase());
20 }
17 function dialog(cm, text, shortText, f) {
21 function dialog(cm, text, shortText, f) {
18 if (cm.openDialog) cm.openDialog(text, f);
22 if (cm.openDialog) cm.openDialog(text, f);
19 else f(prompt(shortText, ""));
23 else f(prompt(shortText, ""));
@@ -23,11 +27,11
23 else if (confirm(shortText)) fs[0]();
27 else if (confirm(shortText)) fs[0]();
24 }
28 }
25 function parseQuery(query) {
29 function parseQuery(query) {
26 var isRE = query.match(/^\/(.*)\/$/);
30 var isRE = query.match(/^\/(.*)\/([a-z]*)$/);
27 return isRE ? new RegExp(isRE[1]) : query;
31 return isRE ? new RegExp(isRE[1], isRE[2].indexOf("i") == -1 ? "" : "i") : query;
28 }
32 }
29 var queryDialog =
33 var queryDialog =
30 'Search: <input type="text" style="width: 10em"> <span style="color: #888">(Use /re/ syntax for regexp search)</span>';
34 'Search: <input type="text" style="width: 10em"/> <span style="color: #888">(Use /re/ syntax for regexp search)</span>';
31 function doSearch(cm, rev) {
35 function doSearch(cm, rev) {
32 var state = getSearchState(cm);
36 var state = getSearchState(cm);
33 if (state.query) return findNext(cm, rev);
37 if (state.query) return findNext(cm, rev);
@@ -36,7 +40,7
36 if (!query || state.query) return;
40 if (!query || state.query) return;
37 state.query = parseQuery(query);
41 state.query = parseQuery(query);
38 if (cm.lineCount() < 2000) { // This is too expensive on big documents.
42 if (cm.lineCount() < 2000) { // This is too expensive on big documents.
39 for (var cursor = cm.getSearchCursor(query); cursor.findNext();)
43 for (var cursor = getSearchCursor(cm, query); cursor.findNext();)
40 state.marked.push(cm.markText(cursor.from(), cursor.to(), "CodeMirror-searching"));
44 state.marked.push(cm.markText(cursor.from(), cursor.to(), "CodeMirror-searching"));
41 }
45 }
42 state.posFrom = state.posTo = cm.getCursor();
46 state.posFrom = state.posTo = cm.getCursor();
@@ -46,9 +50,9
46 }
50 }
47 function findNext(cm, rev) {cm.operation(function() {
51 function findNext(cm, rev) {cm.operation(function() {
48 var state = getSearchState(cm);
52 var state = getSearchState(cm);
49 var cursor = cm.getSearchCursor(state.query, rev ? state.posFrom : state.posTo);
53 var cursor = getSearchCursor(cm, state.query, rev ? state.posFrom : state.posTo);
50 if (!cursor.find(rev)) {
54 if (!cursor.find(rev)) {
51 cursor = cm.getSearchCursor(state.query, rev ? {line: cm.lineCount() - 1} : {line: 0, ch: 0});
55 cursor = getSearchCursor(cm, state.query, rev ? {line: cm.lineCount() - 1} : {line: 0, ch: 0});
52 if (!cursor.find(rev)) return;
56 if (!cursor.find(rev)) return;
53 }
57 }
54 cm.setSelection(cursor.from(), cursor.to());
58 cm.setSelection(cursor.from(), cursor.to());
@@ -63,8 +67,8
63 })}
67 })}
64
68
65 var replaceQueryDialog =
69 var replaceQueryDialog =
66 'Replace: <input type="text" style="width: 10em"> <span style="color: #888">(Use /re/ syntax for regexp search)</span>';
70 'Replace: <input type="text" style="width: 10em"/> <span style="color: #888">(Use /re/ syntax for regexp search)</span>';
67 var replacementQueryDialog = 'With: <input type="text" style="width: 10em">';
71 var replacementQueryDialog = 'With: <input type="text" style="width: 10em"/>';
68 var doReplaceConfirm = "Replace? <button>Yes</button> <button>No</button> <button>Stop</button>";
72 var doReplaceConfirm = "Replace? <button>Yes</button> <button>No</button> <button>Stop</button>";
69 function replace(cm, all) {
73 function replace(cm, all) {
70 dialog(cm, replaceQueryDialog, "Replace:", function(query) {
74 dialog(cm, replaceQueryDialog, "Replace:", function(query) {
@@ -72,23 +76,23
72 query = parseQuery(query);
76 query = parseQuery(query);
73 dialog(cm, replacementQueryDialog, "Replace with:", function(text) {
77 dialog(cm, replacementQueryDialog, "Replace with:", function(text) {
74 if (all) {
78 if (all) {
75 cm.operation(function() {
79 cm.compoundChange(function() { cm.operation(function() {
76 for (var cursor = cm.getSearchCursor(query); cursor.findNext();) {
80 for (var cursor = getSearchCursor(cm, query); cursor.findNext();) {
77 if (typeof query != "string") {
81 if (typeof query != "string") {
78 var match = cm.getRange(cursor.from(), cursor.to()).match(query);
82 var match = cm.getRange(cursor.from(), cursor.to()).match(query);
79 cursor.replace(text.replace(/\$(\d)/, function(w, i) {return match[i];}));
83 cursor.replace(text.replace(/\$(\d)/, function(w, i) {return match[i];}));
80 } else cursor.replace(text);
84 } else cursor.replace(text);
81 }
85 }
82 });
86 })});
83 } else {
87 } else {
84 clearSearch(cm);
88 clearSearch(cm);
85 var cursor = cm.getSearchCursor(query, cm.getCursor());
89 var cursor = getSearchCursor(cm, query, cm.getCursor());
86 function advance() {
90 function advance() {
87 var start = cursor.from(), match;
91 var start = cursor.from(), match;
88 if (!(match = cursor.findNext())) {
92 if (!(match = cursor.findNext())) {
89 cursor = cm.getSearchCursor(query);
93 cursor = getSearchCursor(cm, query);
90 if (!(match = cursor.findNext()) ||
94 if (!(match = cursor.findNext()) ||
91 (cursor.from().line == start.line && cursor.from().ch == start.ch)) return;
95 (start && cursor.from().line == start.line && cursor.from().ch == start.ch)) return;
92 }
96 }
93 cm.setSelection(cursor.from(), cursor.to());
97 cm.setSelection(cursor.from(), cursor.to());
94 confirmDialog(cm, doReplaceConfirm, "Replace?",
98 confirmDialog(cm, doReplaceConfirm, "Replace?",
@@ -1,7 +1,7
1 (function(){
1 (function(){
2 function SearchCursor(cm, query, pos, caseFold) {
2 function SearchCursor(cm, query, pos, caseFold) {
3 this.atOccurrence = false; this.cm = cm;
3 this.atOccurrence = false; this.cm = cm;
4 if (caseFold == null) caseFold = typeof query == "string" && query == query.toLowerCase();
4 if (caseFold == null && typeof query == "string") caseFold = false;
5
5
6 pos = pos ? cm.clipPos(pos) : {line: 0, ch: 0};
6 pos = pos ? cm.clipPos(pos) : {line: 0, ch: 0};
7 this.pos = {from: pos, to: pos};
7 this.pos = {from: pos, to: pos};
1 NO CONTENT: modified file chmod 100755 => 100644
NO CONTENT: modified file chmod 100755 => 100644
@@ -2,6 +2,10
2 CodeMirror.simpleHint = function(editor, getHints) {
2 CodeMirror.simpleHint = function(editor, getHints) {
3 // We want a single cursor position.
3 // We want a single cursor position.
4 if (editor.somethingSelected()) return;
4 if (editor.somethingSelected()) return;
5 //don't show completion if the token is empty
6 var tempToken = editor.getTokenAt(editor.getCursor());
7 if(!(/[\S]/gi.test(tempToken.string))) return;
8
5 var result = getHints(editor);
9 var result = getHints(editor);
6 if (!result || !result.list.length) return;
10 if (!result || !result.list.length) return;
7 var completions = result.list;
11 var completions = result.list;
@@ -29,6 +33,10
29 complete.style.left = pos.x + "px";
33 complete.style.left = pos.x + "px";
30 complete.style.top = pos.yBot + "px";
34 complete.style.top = pos.yBot + "px";
31 document.body.appendChild(complete);
35 document.body.appendChild(complete);
36 // If we're at the edge of the screen, then we want the menu to appear on the left of the cursor.
37 var winW = window.innerWidth || Math.max(document.body.offsetWidth, document.documentElement.offsetWidth);
38 if(winW - pos.x < sel.clientWidth)
39 complete.style.left = (pos.x - sel.clientWidth) + "px";
32 // Hack to hide the scrollbar.
40 // Hack to hide the scrollbar.
33 if (completions.length <= 10)
41 if (completions.length <= 10)
34 complete.style.width = (sel.clientWidth - 1) + "px";
42 complete.style.width = (sel.clientWidth - 1) + "px";
@@ -53,6 +61,8
53 else if (code == 27) {CodeMirror.e_stop(event); close(); editor.focus();}
61 else if (code == 27) {CodeMirror.e_stop(event); close(); editor.focus();}
54 else if (code != 38 && code != 40) {
62 else if (code != 38 && code != 40) {
55 close(); editor.focus();
63 close(); editor.focus();
64 // Pass the event to the CodeMirror instance so that it can handle things like backspace properly.
65 editor.triggerOnKeyDown(event);
56 setTimeout(function(){CodeMirror.simpleHint(editor, getHints);}, 50);
66 setTimeout(function(){CodeMirror.simpleHint(editor, getHints);}, 50);
57 }
67 }
58 });
68 });
@@ -92,7 +92,7 CodeMirror.defineMode("css", function(config) {
92 var style = state.tokenize(stream, state);
92 var style = state.tokenize(stream, state);
93
93
94 var context = state.stack[state.stack.length-1];
94 var context = state.stack[state.stack.length-1];
95 if (type == "hash" && context == "rule") style = "atom";
95 if (type == "hash" && context != "rule") style = "string-2";
96 else if (style == "variable") {
96 else if (style == "variable") {
97 if (context == "rule") style = "number";
97 if (context == "rule") style = "number";
98 else if (!context || context == "@media{") style = "tag";
98 else if (!context || context == "@media{") style = "tag";
1 NO CONTENT: modified file chmod 100755 => 100644
NO CONTENT: modified file chmod 100755 => 100644
@@ -28,7 +28,7 CodeMirror.defineMode("htmlmixed", function(config, parserConfig) {
28 function javascript(stream, state) {
28 function javascript(stream, state) {
29 if (stream.match(/^<\/\s*script\s*>/i, false)) {
29 if (stream.match(/^<\/\s*script\s*>/i, false)) {
30 state.token = html;
30 state.token = html;
31 state.curState = null;
31 state.localState = null;
32 state.mode = "html";
32 state.mode = "html";
33 return html(stream, state);
33 return html(stream, state);
34 }
34 }
@@ -73,11 +73,13 CodeMirror.defineMode("htmlmixed", function(config, parserConfig) {
73 },
73 },
74
74
75 compareStates: function(a, b) {
75 compareStates: function(a, b) {
76 if (a.mode != b.mode) return false;
77 if (a.localState) return CodeMirror.Pass;
76 return htmlMode.compareStates(a.htmlState, b.htmlState);
78 return htmlMode.compareStates(a.htmlState, b.htmlState);
77 },
79 },
78
80
79 electricChars: "/{}:"
81 electricChars: "/{}:"
80 }
82 }
81 });
83 }, "xml", "javascript", "css");
82
84
83 CodeMirror.defineMIME("text/html", "htmlmixed");
85 CodeMirror.defineMIME("text/html", "htmlmixed");
1 NO CONTENT: modified file chmod 100755 => 100644
NO CONTENT: modified file chmod 100755 => 100644
1 NO CONTENT: modified file chmod 100755 => 100644
NO CONTENT: modified file chmod 100755 => 100644
@@ -54,7 +54,7 CodeMirror.defineMode("javascript", function(config, parserConfig) {
54 stream.eatWhile(/[\da-f]/i);
54 stream.eatWhile(/[\da-f]/i);
55 return ret("number", "number");
55 return ret("number", "number");
56 }
56 }
57 else if (/\d/.test(ch)) {
57 else if (/\d/.test(ch) || ch == "-" && stream.eat(/\d/)) {
58 stream.match(/^\d*(?:\.\d*)?(?:[eE][+\-]?\d+)?/);
58 stream.match(/^\d*(?:\.\d*)?(?:[eE][+\-]?\d+)?/);
59 return ret("number", "number");
59 return ret("number", "number");
60 }
60 }
@@ -243,7 +243,7 CodeMirror.defineMode("javascript", function(config, parserConfig) {
243
243
244 function maybeoperator(type, value) {
244 function maybeoperator(type, value) {
245 if (type == "operator" && /\+\+|--/.test(value)) return cont(maybeoperator);
245 if (type == "operator" && /\+\+|--/.test(value)) return cont(maybeoperator);
246 if (type == "operator") return cont(expression);
246 if (type == "operator" || type == ":") return cont(expression);
247 if (type == ";") return;
247 if (type == ";") return;
248 if (type == "(") return cont(pushlex(")"), commasep(expression, ")"), poplex, maybeoperator);
248 if (type == "(") return cont(pushlex(")"), commasep(expression, ")"), poplex, maybeoperator);
249 if (type == ".") return cont(property, maybeoperator);
249 if (type == ".") return cont(property, maybeoperator);
@@ -319,8 +319,8 CodeMirror.defineMode("javascript", function(config, parserConfig) {
319 kwAllowed: true,
319 kwAllowed: true,
320 cc: [],
320 cc: [],
321 lexical: new JSLexical((basecolumn || 0) - indentUnit, 0, "block", false),
321 lexical: new JSLexical((basecolumn || 0) - indentUnit, 0, "block", false),
322 localVars: null,
322 localVars: parserConfig.localVars,
323 context: null,
323 context: parserConfig.localVars && {vars: parserConfig.localVars},
324 indented: 0
324 indented: 0
325 };
325 };
326 },
326 },
@@ -334,15 +334,16 CodeMirror.defineMode("javascript", function(config, parserConfig) {
334 if (stream.eatSpace()) return null;
334 if (stream.eatSpace()) return null;
335 var style = state.tokenize(stream, state);
335 var style = state.tokenize(stream, state);
336 if (type == "comment") return style;
336 if (type == "comment") return style;
337 state.reAllowed = type == "operator" || type == "keyword c" || type.match(/^[\[{}\(,;:]$/);
337 state.reAllowed = !!(type == "operator" || type == "keyword c" || type.match(/^[\[{}\(,;:]$/));
338 state.kwAllowed = type != '.';
338 state.kwAllowed = type != '.';
339 return parseJS(state, style, type, content, stream);
339 return parseJS(state, style, type, content, stream);
340 },
340 },
341
341
342 indent: function(state, textAfter) {
342 indent: function(state, textAfter) {
343 if (state.tokenize != jsTokenBase) return 0;
343 if (state.tokenize != jsTokenBase) return 0;
344 var firstChar = textAfter && textAfter.charAt(0), lexical = state.lexical,
344 var firstChar = textAfter && textAfter.charAt(0), lexical = state.lexical;
345 type = lexical.type, closing = firstChar == type;
345 if (lexical.type == "stat" && firstChar == "}") lexical = lexical.prev;
346 var type = lexical.type, closing = firstChar == type;
346 if (type == "vardef") return lexical.indented + 4;
347 if (type == "vardef") return lexical.indented + 4;
347 else if (type == "form" && firstChar == "{") return lexical.indented;
348 else if (type == "form" && firstChar == "{") return lexical.indented;
348 else if (type == "stat" || type == "form") return lexical.indented + indentUnit;
349 else if (type == "stat" || type == "form") return lexical.indented + indentUnit;
@@ -6,7 +6,6
6 <script src="../../lib/codemirror.js"></script>
6 <script src="../../lib/codemirror.js"></script>
7 <script src="../xml/xml.js"></script>
7 <script src="../xml/xml.js"></script>
8 <script src="markdown.js"></script>
8 <script src="markdown.js"></script>
9 <link rel="stylesheet" href="markdown.css">
10 <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
9 <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
11 <link rel="stylesheet" href="../../doc/docs.css">
10 <link rel="stylesheet" href="../../doc/docs.css">
12 </head>
11 </head>
@@ -333,6 +332,8 Output:
333 });
332 });
334 </script>
333 </script>
335
334
335 <p>Optionally depends on the XML mode for properly highlighted inline XML blocks.</p>
336
336 <p><strong>MIME types defined:</strong> <code>text/x-markdown</code>.</p>
337 <p><strong>MIME types defined:</strong> <code>text/x-markdown</code>.</p>
337
338
338 </body>
339 </body>
@@ -1,6 +1,7
1 CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
1 CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
2
2
3 var htmlMode = CodeMirror.getMode(cmCfg, { name: 'xml', htmlMode: true });
3 var htmlFound = CodeMirror.mimeModes.hasOwnProperty("text/html");
4 var htmlMode = CodeMirror.getMode(cmCfg, htmlFound ? "text/html" : "text/plain");
4
5
5 var header = 'header'
6 var header = 'header'
6 , code = 'comment'
7 , code = 'comment'
@@ -13,11 +14,10 CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
13 , strong = 'strong'
14 , strong = 'strong'
14 , emstrong = 'emstrong';
15 , emstrong = 'emstrong';
15
16
16 var hrRE = /^[*-=_]/
17 var hrRE = /^([*\-=_])(?:\s*\1){2,}\s*$/
17 , ulRE = /^[*-+]\s+/
18 , ulRE = /^[*\-+]\s+/
18 , olRE = /^[0-9]+\.\s+/
19 , olRE = /^[0-9]+\.\s+/
19 , headerRE = /^(?:\={3,}|-{3,})$/
20 , headerRE = /^(?:\={3,}|-{3,})$/
20 , codeRE = /^(k:\t|\s{4,})/
21 , textRE = /^[^\[*_\\<>`]+/;
21 , textRE = /^[^\[*_\\<>`]+/;
22
22
23 function switchInline(stream, state, f) {
23 function switchInline(stream, state, f) {
@@ -33,36 +33,36 CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
33
33
34 // Blocks
34 // Blocks
35
35
36 function blankLine(state) {
37 // Reset EM state
38 state.em = false;
39 // Reset STRONG state
40 state.strong = false;
41 if (!htmlFound && state.f == htmlBlock) {
42 state.f = inlineNormal;
43 state.block = blockNormal;
44 }
45 return null;
46 }
47
36 function blockNormal(stream, state) {
48 function blockNormal(stream, state) {
37 if (stream.match(codeRE)) {
49 var match;
50 if (state.indentationDiff >= 4) {
51 state.indentation -= state.indentationDiff;
38 stream.skipToEnd();
52 stream.skipToEnd();
39 return code;
53 return code;
40 }
54 } else if (stream.eatSpace()) {
41
42 if (stream.eatSpace()) {
43 return null;
55 return null;
44 }
56 } else if (stream.peek() === '#' || stream.match(headerRE)) {
45
57 state.header = true;
46 if (stream.peek() === '#' || stream.match(headerRE)) {
58 } else if (stream.eat('>')) {
47 stream.skipToEnd();
48 return header;
49 }
50 if (stream.eat('>')) {
51 state.indentation++;
59 state.indentation++;
52 return quote;
60 state.quote = true;
53 }
61 } else if (stream.peek() === '[') {
54 if (stream.peek() === '[') {
55 return switchInline(stream, state, footnoteLink);
62 return switchInline(stream, state, footnoteLink);
56 }
63 } else if (stream.match(hrRE, true)) {
57 if (hrRE.test(stream.peek())) {
64 return hr;
58 var re = new RegExp('(?:\s*['+stream.peek()+']){3,}$');
65 } else if (match = stream.match(ulRE, true) || stream.match(olRE, true)) {
59 if (stream.match(re, true)) {
60 return hr;
61 }
62 }
63
64 var match;
65 if (match = stream.match(ulRE, true) || stream.match(olRE, true)) {
66 state.indentation += match[0].length;
66 state.indentation += match[0].length;
67 return list;
67 return list;
68 }
68 }
@@ -72,18 +72,30 CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
72
72
73 function htmlBlock(stream, state) {
73 function htmlBlock(stream, state) {
74 var style = htmlMode.token(stream, state.htmlState);
74 var style = htmlMode.token(stream, state.htmlState);
75 if (style === 'tag' && state.htmlState.type !== 'openTag' && !state.htmlState.context) {
75 if (htmlFound && style === 'tag' && state.htmlState.type !== 'openTag' && !state.htmlState.context) {
76 state.f = inlineNormal;
76 state.f = inlineNormal;
77 state.block = blockNormal;
77 state.block = blockNormal;
78 }
78 }
79 if (state.md_inside && stream.current().indexOf(">")!=-1) {
80 state.f = inlineNormal;
81 state.block = blockNormal;
82 state.htmlState.context = undefined;
83 }
79 return style;
84 return style;
80 }
85 }
81
86
82
87
83 // Inline
88 // Inline
84 function getType(state) {
89 function getType(state) {
85 return state.strong ? (state.em ? emstrong : strong)
90 var styles = [];
86 : (state.em ? em : null);
91
92 if (state.strong) { styles.push(state.em ? emstrong : strong); }
93 else if (state.em) { styles.push(em); }
94
95 if (state.header) { styles.push(header); }
96 if (state.quote) { styles.push(quote); }
97
98 return styles.length ? styles.join(' ') : null;
87 }
99 }
88
100
89 function handleText(stream, state) {
101 function handleText(stream, state) {
@@ -111,10 +123,22 CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
111 return switchInline(stream, state, linkText);
123 return switchInline(stream, state, linkText);
112 }
124 }
113 if (ch === '<' && stream.match(/^\w/, false)) {
125 if (ch === '<' && stream.match(/^\w/, false)) {
126 var md_inside = false;
127 if (stream.string.indexOf(">")!=-1) {
128 var atts = stream.string.substring(1,stream.string.indexOf(">"));
129 if (/markdown\s*=\s*('|"){0,1}1('|"){0,1}/.test(atts)) {
130 state.md_inside = true;
131 }
132 }
114 stream.backUp(1);
133 stream.backUp(1);
115 return switchBlock(stream, state, htmlBlock);
134 return switchBlock(stream, state, htmlBlock);
116 }
135 }
117
136
137 if (ch === '<' && stream.match(/^\/\w*?>/)) {
138 state.md_inside = false;
139 return "tag";
140 }
141
118 var t = getType(state);
142 var t = getType(state);
119 if (ch === '*' || ch === '_') {
143 if (ch === '*' || ch === '_') {
120 if (stream.eat(ch)) {
144 if (stream.eat(ch)) {
@@ -186,13 +210,15 CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
186 f: blockNormal,
210 f: blockNormal,
187
211
188 block: blockNormal,
212 block: blockNormal,
189 htmlState: htmlMode.startState(),
213 htmlState: CodeMirror.startState(htmlMode),
190 indentation: 0,
214 indentation: 0,
191
215
192 inline: inlineNormal,
216 inline: inlineNormal,
193 text: handleText,
217 text: handleText,
194 em: false,
218 em: false,
195 strong: false
219 strong: false,
220 header: false,
221 quote: false
196 };
222 };
197 },
223 },
198
224
@@ -203,44 +229,40 CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
203 block: s.block,
229 block: s.block,
204 htmlState: CodeMirror.copyState(htmlMode, s.htmlState),
230 htmlState: CodeMirror.copyState(htmlMode, s.htmlState),
205 indentation: s.indentation,
231 indentation: s.indentation,
206
232
207 inline: s.inline,
233 inline: s.inline,
208 text: s.text,
234 text: s.text,
209 em: s.em,
235 em: s.em,
210 strong: s.strong
236 strong: s.strong,
237 header: s.header,
238 quote: s.quote,
239 md_inside: s.md_inside
211 };
240 };
212 },
241 },
213
242
214 token: function(stream, state) {
243 token: function(stream, state) {
215 if (stream.sol()) {
244 if (stream.sol()) {
216 // Reset EM state
245 if (stream.match(/^\s*$/, true)) { return blankLine(state); }
217 state.em = false;
246
218 // Reset STRONG state
247 // Reset state.header
219 state.strong = false;
248 state.header = false;
249 // Reset state.quote
250 state.quote = false;
251
220 state.f = state.block;
252 state.f = state.block;
221 var previousIndentation = state.indentation
253 var indentation = stream.match(/^\s*/, true)[0].replace(/\t/g, ' ').length;
222 , currentIndentation = 0;
254 state.indentationDiff = indentation - state.indentation;
223 while (previousIndentation > 0) {
255 state.indentation = indentation;
224 if (stream.eat(' ')) {
256 if (indentation > 0) { return null; }
225 previousIndentation--;
226 currentIndentation++;
227 } else if (previousIndentation >= 4 && stream.eat('\t')) {
228 previousIndentation -= 4;
229 currentIndentation += 4;
230 } else {
231 break;
232 }
233 }
234 state.indentation = currentIndentation;
235
236 if (currentIndentation > 0) return null;
237 }
257 }
238 return state.f(stream, state);
258 return state.f(stream, state);
239 },
259 },
240
260
261 blankLine: blankLine,
262
241 getType: getType
263 getType: getType
242 };
264 };
243
265
244 });
266 }, "xml");
245
267
246 CodeMirror.defineMIME("text/x-markdown", "markdown");
268 CodeMirror.defineMIME("text/x-markdown", "markdown");
1 NO CONTENT: modified file chmod 100755 => 100644
NO CONTENT: modified file chmod 100755 => 100644
1 NO CONTENT: modified file chmod 100755 => 100644
NO CONTENT: modified file chmod 100755 => 100644
@@ -5,7 +5,7 CodeMirror.defineMode("python", function(conf, parserConf) {
5 return new RegExp("^((" + words.join(")|(") + "))\\b");
5 return new RegExp("^((" + words.join(")|(") + "))\\b");
6 }
6 }
7
7
8 var singleOperators = new RegExp("^[\\+\\-\\*/%&|\\^~<>!\\?]");
8 var singleOperators = new RegExp("^[\\+\\-\\*/%&|\\^~<>!]");
9 var singleDelimiters = new RegExp('^[\\(\\)\\[\\]\\{\\}@,:`=;\\.]');
9 var singleDelimiters = new RegExp('^[\\(\\)\\[\\]\\{\\}@,:`=;\\.]');
10 var doubleOperators = new RegExp("^((==)|(!=)|(<=)|(>=)|(<>)|(<<)|(>>)|(//)|(\\*\\*))");
10 var doubleOperators = new RegExp("^((==)|(!=)|(<=)|(>=)|(<>)|(<<)|(>>)|(//)|(\\*\\*))");
11 var doubleDelimiters = new RegExp("^((\\+=)|(\\-=)|(\\*=)|(%=)|(/=)|(&=)|(\\|=)|(\\^=))");
11 var doubleDelimiters = new RegExp("^((\\+=)|(\\-=)|(\\*=)|(%=)|(/=)|(&=)|(\\|=)|(\\^=))");
@@ -249,32 +249,30 CodeMirror.defineMode("python", function(conf, parserConf) {
249
249
250 // Handle '.' connected identifiers
250 // Handle '.' connected identifiers
251 if (current === '.') {
251 if (current === '.') {
252 style = state.tokenize(stream, state);
252 style = stream.match(identifiers, false) ? null : ERRORCLASS;
253 current = stream.current();
253 if (style === null && state.lastToken === 'meta') {
254 if (style === 'variable' || style === 'builtin') {
254 // Apply 'meta' style to '.' connected identifiers when
255 return 'variable';
255 // appropriate.
256 } else {
256 style = 'meta';
257 return ERRORCLASS;
258 }
257 }
258 return style;
259 }
259 }
260
260
261 // Handle decorators
261 // Handle decorators
262 if (current === '@') {
262 if (current === '@') {
263 style = state.tokenize(stream, state);
263 return stream.match(identifiers, false) ? 'meta' : ERRORCLASS;
264 current = stream.current();
264 }
265 if (style === 'variable'
265
266 || current === '@staticmethod'
266 if ((style === 'variable' || style === 'builtin')
267 || current === '@classmethod') {
267 && state.lastToken === 'meta') {
268 return 'meta';
268 style = 'meta';
269 } else {
270 return ERRORCLASS;
271 }
272 }
269 }
273
270
274 // Handle scope changes.
271 // Handle scope changes.
275 if (current === 'pass' || current === 'return') {
272 if (current === 'pass' || current === 'return') {
276 state.dedent += 1;
273 state.dedent += 1;
277 }
274 }
275 if (current === 'lambda') state.lambda = true;
278 if ((current === ':' && !state.lambda && state.scopes[0].type == 'py')
276 if ((current === ':' && !state.lambda && state.scopes[0].type == 'py')
279 || indentInfo === 'indent') {
277 || indentInfo === 'indent') {
280 indent(stream, state);
278 indent(stream, state);
@@ -316,7 +314,7 CodeMirror.defineMode("python", function(conf, parserConf) {
316 token: function(stream, state) {
314 token: function(stream, state) {
317 var style = tokenLexer(stream, state);
315 var style = tokenLexer(stream, state);
318
316
319 state.lastToken = {style:style, content: stream.current()};
317 state.lastToken = style;
320
318
321 if (stream.eol() && stream.lambda) {
319 if (stream.eol() && stream.lambda) {
322 state.lambda = false;
320 state.lambda = false;
1 NO CONTENT: modified file chmod 100755 => 100644
NO CONTENT: modified file chmod 100755 => 100644
@@ -321,6 +321,6 CodeMirror.defineMode('rst', function(config, options) {
321 return token;
321 return token;
322 }
322 }
323 };
323 };
324 });
324 }, "python");
325
325
326 CodeMirror.defineMIME("text/x-rst", "rst");
326 CodeMirror.defineMIME("text/x-rst", "rst");
1 NO CONTENT: modified file chmod 100755 => 100644
NO CONTENT: modified file chmod 100755 => 100644
@@ -1,11 +1,44
1 CodeMirror.defineMode("xml", function(config, parserConfig) {
1 CodeMirror.defineMode("xml", function(config, parserConfig) {
2 var indentUnit = config.indentUnit;
2 var indentUnit = config.indentUnit;
3 var Kludges = parserConfig.htmlMode ? {
3 var Kludges = parserConfig.htmlMode ? {
4 autoSelfClosers: {"br": true, "img": true, "hr": true, "link": true, "input": true,
4 autoSelfClosers: {'area': true, 'base': true, 'br': true, 'col': true, 'command': true,
5 "meta": true, "col": true, "frame": true, "base": true, "area": true},
5 'embed': true, 'frame': true, 'hr': true, 'img': true, 'input': true,
6 'keygen': true, 'link': true, 'meta': true, 'param': true, 'source': true,
7 'track': true, 'wbr': true},
8 implicitlyClosed: {'dd': true, 'li': true, 'optgroup': true, 'option': true, 'p': true,
9 'rp': true, 'rt': true, 'tbody': true, 'td': true, 'tfoot': true,
10 'th': true, 'tr': true},
11 contextGrabbers: {
12 'dd': {'dd': true, 'dt': true},
13 'dt': {'dd': true, 'dt': true},
14 'li': {'li': true},
15 'option': {'option': true, 'optgroup': true},
16 'optgroup': {'optgroup': true},
17 'p': {'address': true, 'article': true, 'aside': true, 'blockquote': true, 'dir': true,
18 'div': true, 'dl': true, 'fieldset': true, 'footer': true, 'form': true,
19 'h1': true, 'h2': true, 'h3': true, 'h4': true, 'h5': true, 'h6': true,
20 'header': true, 'hgroup': true, 'hr': true, 'menu': true, 'nav': true, 'ol': true,
21 'p': true, 'pre': true, 'section': true, 'table': true, 'ul': true},
22 'rp': {'rp': true, 'rt': true},
23 'rt': {'rp': true, 'rt': true},
24 'tbody': {'tbody': true, 'tfoot': true},
25 'td': {'td': true, 'th': true},
26 'tfoot': {'tbody': true},
27 'th': {'td': true, 'th': true},
28 'thead': {'tbody': true, 'tfoot': true},
29 'tr': {'tr': true}
30 },
6 doNotIndent: {"pre": true},
31 doNotIndent: {"pre": true},
7 allowUnquoted: true
32 allowUnquoted: true,
8 } : {autoSelfClosers: {}, doNotIndent: {}, allowUnquoted: false};
33 allowMissing: false
34 } : {
35 autoSelfClosers: {},
36 implicitlyClosed: {},
37 contextGrabbers: {},
38 doNotIndent: {},
39 allowUnquoted: false,
40 allowMissing: false
41 };
9 var alignCDATA = parserConfig.alignCDATA;
42 var alignCDATA = parserConfig.alignCDATA;
10
43
11 // Return variables for tokenizers
44 // Return variables for tokenizers
@@ -55,7 +88,7 CodeMirror.defineMode("xml", function(config, parserConfig) {
55 ok = stream.eatWhile(/[\d]/) && stream.eat(";");
88 ok = stream.eatWhile(/[\d]/) && stream.eat(";");
56 }
89 }
57 } else {
90 } else {
58 ok = stream.eatWhile(/[\w]/) && stream.eat(";");
91 ok = stream.eatWhile(/[\w\.\-:]/) && stream.eat(";");
59 }
92 }
60 return ok ? "atom" : "error";
93 return ok ? "atom" : "error";
61 }
94 }
@@ -161,7 +194,12 CodeMirror.defineMode("xml", function(config, parserConfig) {
161 } else if (type == "closeTag") {
194 } else if (type == "closeTag") {
162 var err = false;
195 var err = false;
163 if (curState.context) {
196 if (curState.context) {
164 err = curState.context.tagName != tagName;
197 if (curState.context.tagName != tagName) {
198 if (Kludges.implicitlyClosed.hasOwnProperty(curState.context.tagName.toLowerCase())) {
199 popContext();
200 }
201 err = !curState.context || curState.context.tagName != tagName;
202 }
165 } else {
203 } else {
166 err = true;
204 err = true;
167 }
205 }
@@ -173,9 +211,15 CodeMirror.defineMode("xml", function(config, parserConfig) {
173 function endtag(startOfLine) {
211 function endtag(startOfLine) {
174 return function(type) {
212 return function(type) {
175 if (type == "selfcloseTag" ||
213 if (type == "selfcloseTag" ||
176 (type == "endTag" && Kludges.autoSelfClosers.hasOwnProperty(curState.tagName.toLowerCase())))
214 (type == "endTag" && Kludges.autoSelfClosers.hasOwnProperty(curState.tagName.toLowerCase()))) {
215 maybePopContext(curState.tagName.toLowerCase());
177 return cont();
216 return cont();
178 if (type == "endTag") {pushContext(curState.tagName, startOfLine); return cont();}
217 }
218 if (type == "endTag") {
219 maybePopContext(curState.tagName.toLowerCase());
220 pushContext(curState.tagName, startOfLine);
221 return cont();
222 }
179 return cont();
223 return cont();
180 };
224 };
181 }
225 }
@@ -187,17 +231,37 CodeMirror.defineMode("xml", function(config, parserConfig) {
187 return cont(arguments.callee);
231 return cont(arguments.callee);
188 }
232 }
189 }
233 }
234 function maybePopContext(nextTagName) {
235 var parentTagName;
236 while (true) {
237 if (!curState.context) {
238 return;
239 }
240 parentTagName = curState.context.tagName.toLowerCase();
241 if (!Kludges.contextGrabbers.hasOwnProperty(parentTagName) ||
242 !Kludges.contextGrabbers[parentTagName].hasOwnProperty(nextTagName)) {
243 return;
244 }
245 popContext();
246 }
247 }
190
248
191 function attributes(type) {
249 function attributes(type) {
192 if (type == "word") {setStyle = "attribute"; return cont(attributes);}
250 if (type == "word") {setStyle = "attribute"; return cont(attribute, attributes);}
251 if (type == "endTag" || type == "selfcloseTag") return pass();
252 setStyle = "error";
253 return cont(attributes);
254 }
255 function attribute(type) {
193 if (type == "equals") return cont(attvalue, attributes);
256 if (type == "equals") return cont(attvalue, attributes);
194 if (type == "string") {setStyle = "error"; return cont(attributes);}
257 if (!Kludges.allowMissing) setStyle = "error";
195 return pass();
258 return (type == "endTag" || type == "selfcloseTag") ? pass() : cont();
196 }
259 }
197 function attvalue(type) {
260 function attvalue(type) {
198 if (type == "word" && Kludges.allowUnquoted) {setStyle = "string"; return cont();}
199 if (type == "string") return cont(attvaluemaybe);
261 if (type == "string") return cont(attvaluemaybe);
200 return pass();
262 if (type == "word" && Kludges.allowUnquoted) {setStyle = "string"; return cont();}
263 setStyle = "error";
264 return (type == "endTag" || type == "selfCloseTag") ? pass() : cont();
201 }
265 }
202 function attvaluemaybe(type) {
266 function attvaluemaybe(type) {
203 if (type == "string") return cont(attvaluemaybe);
267 if (type == "string") return cont(attvaluemaybe);
@@ -248,7 +312,7 CodeMirror.defineMode("xml", function(config, parserConfig) {
248 if (a.indented != b.indented || a.tokenize != b.tokenize) return false;
312 if (a.indented != b.indented || a.tokenize != b.tokenize) return false;
249 for (var ca = a.context, cb = b.context; ; ca = ca.prev, cb = cb.prev) {
313 for (var ca = a.context, cb = b.context; ; ca = ca.prev, cb = cb.prev) {
250 if (!ca || !cb) return ca == cb;
314 if (!ca || !cb) return ca == cb;
251 if (ca.tagName != cb.tagName) return false;
315 if (ca.tagName != cb.tagName || ca.indent != cb.indent) return false;
252 }
316 }
253 },
317 },
254
318
@@ -256,5 +320,7 CodeMirror.defineMode("xml", function(config, parserConfig) {
256 };
320 };
257 });
321 });
258
322
323 CodeMirror.defineMIME("text/xml", "xml");
259 CodeMirror.defineMIME("application/xml", "xml");
324 CodeMirror.defineMIME("application/xml", "xml");
260 CodeMirror.defineMIME("text/html", {name: "xml", htmlMode: true});
325 if (!CodeMirror.mimeModes.hasOwnProperty("text/html"))
326 CodeMirror.defineMIME("text/html", {name: "xml", htmlMode: true});
1 NO CONTENT: modified file chmod 100755 => 100644
NO CONTENT: modified file chmod 100755 => 100644
@@ -1,5 +1,5
1 .cm-s-eclipse span.cm-meta {color: #FF1717;}
1 .cm-s-eclipse span.cm-meta {color: #FF1717;}
2 .cm-s-eclipse span.cm-keyword { font-weight: bold; color: #7F0055; }
2 .cm-s-eclipse span.cm-keyword { line-height: 1em; font-weight: bold; color: #7F0055; }
3 .cm-s-eclipse span.cm-atom {color: #219;}
3 .cm-s-eclipse span.cm-atom {color: #219;}
4 .cm-s-eclipse span.cm-number {color: #164;}
4 .cm-s-eclipse span.cm-number {color: #164;}
5 .cm-s-eclipse span.cm-def {color: #00f;}
5 .cm-s-eclipse span.cm-def {color: #00f;}
@@ -1,6 +1,6
1 .cm-s-elegant span.cm-number, .cm-s-elegant span.cm-string, .cm-s-elegant span.cm-atom {color: #762;}
1 .cm-s-elegant span.cm-number, .cm-s-elegant span.cm-string, .cm-s-elegant span.cm-atom {color: #762;}
2 .cm-s-elegant span.cm-comment {color: #262;font-style: italic;}
2 .cm-s-elegant span.cm-comment {color: #262; font-style: italic; line-height: 1em;}
3 .cm-s-elegant span.cm-meta {color: #555;font-style: italic;}
3 .cm-s-elegant span.cm-meta {color: #555; font-style: italic; line-height: 1em;}
4 .cm-s-elegant span.cm-variable {color: black;}
4 .cm-s-elegant span.cm-variable {color: black;}
5 .cm-s-elegant span.cm-variable-2 {color: #b11;}
5 .cm-s-elegant span.cm-variable-2 {color: #b11;}
6 .cm-s-elegant span.cm-qualifier {color: #555;}
6 .cm-s-elegant span.cm-qualifier {color: #555;}
1 NO CONTENT: modified file chmod 100755 => 100644
NO CONTENT: modified file chmod 100755 => 100644
@@ -1,8 +1,8
1 .cm-s-neat span.cm-comment { color: #a86; }
1 .cm-s-neat span.cm-comment { color: #a86; }
2 .cm-s-neat span.cm-keyword { font-weight: bold; color: blue; }
2 .cm-s-neat span.cm-keyword { line-height: 1em; font-weight: bold; color: blue; }
3 .cm-s-neat span.cm-string { color: #a22; }
3 .cm-s-neat span.cm-string { color: #a22; }
4 .cm-s-neat span.cm-builtin { font-weight: bold; color: #077; }
4 .cm-s-neat span.cm-builtin { line-height: 1em; font-weight: bold; color: #077; }
5 .cm-s-neat span.cm-special { font-weight: bold; color: #0aa; }
5 .cm-s-neat span.cm-special { line-height: 1em; font-weight: bold; color: #0aa; }
6 .cm-s-neat span.cm-variable { color: black; }
6 .cm-s-neat span.cm-variable { color: black; }
7 .cm-s-neat span.cm-number, .cm-s-neat span.cm-atom { color: #3a3; }
7 .cm-s-neat span.cm-number, .cm-s-neat span.cm-atom { color: #3a3; }
8 .cm-s-neat span.cm-meta {color: #555;}
8 .cm-s-neat span.cm-meta {color: #555;}
@@ -1,7 +1,7
1 /* Loosely based on the Midnight Textmate theme */
1 /* Loosely based on the Midnight Textmate theme */
2
2
3 .cm-s-night { background: #0a001f; color: #f8f8f8; }
3 .cm-s-night { background: #0a001f; color: #f8f8f8; }
4 .cm-s-night div.CodeMirror-selected { background: #a8f !important; }
4 .cm-s-night div.CodeMirror-selected { background: #447 !important; }
5 .cm-s-night .CodeMirror-gutter { background: #0a001f; border-right: 1px solid #aaa; }
5 .cm-s-night .CodeMirror-gutter { background: #0a001f; border-right: 1px solid #aaa; }
6 .cm-s-night .CodeMirror-gutter-text { color: #f8f8f8; }
6 .cm-s-night .CodeMirror-gutter-text { color: #f8f8f8; }
7 .cm-s-night .CodeMirror-cursor { border-left: 1px solid white !important; }
7 .cm-s-night .CodeMirror-cursor { border-left: 1px solid white !important; }
@@ -1,12 +1,12
1 .cm-s-rubyblue { font:13px/1.4em Trebuchet, Verdana, sans-serif; } /* - customized editor font - */
1 .cm-s-rubyblue { font:13px/1.4em Trebuchet, Verdana, sans-serif; } /* - customized editor font - */
2
2
3 .cm-s-rubyblue { background: #112435; color: white; }
3 .cm-s-rubyblue { background: #112435; color: white; }
4 .cm-s-rubyblue div.CodeMirror-selected { background: #0000FF !important; }
4 .cm-s-rubyblue div.CodeMirror-selected { background: #38566F !important; }
5 .cm-s-rubyblue .CodeMirror-gutter { background: #1F4661; border-right: 7px solid #3E7087; min-width:2.5em; }
5 .cm-s-rubyblue .CodeMirror-gutter { background: #1F4661; border-right: 7px solid #3E7087; min-width:2.5em; }
6 .cm-s-rubyblue .CodeMirror-gutter-text { color: white; }
6 .cm-s-rubyblue .CodeMirror-gutter-text { color: white; }
7 .cm-s-rubyblue .CodeMirror-cursor { border-left: 1px solid white !important; }
7 .cm-s-rubyblue .CodeMirror-cursor { border-left: 1px solid white !important; }
8
8
9 .cm-s-rubyblue span.cm-comment { color: #999; font-style:italic; }
9 .cm-s-rubyblue span.cm-comment { color: #999; font-style:italic; line-height: 1em; }
10 .cm-s-rubyblue span.cm-atom { color: #F4C20B; }
10 .cm-s-rubyblue span.cm-atom { color: #F4C20B; }
11 .cm-s-rubyblue span.cm-number, .cm-s-rubyblue span.cm-attribute { color: #82C6E0; }
11 .cm-s-rubyblue span.cm-number, .cm-s-rubyblue span.cm-attribute { color: #82C6E0; }
12 .cm-s-rubyblue span.cm-keyword { color: #F0F; }
12 .cm-s-rubyblue span.cm-keyword { color: #F0F; }
@@ -1,40 +0,0
1
2
3 .cm-s-ipython span.cm-keyword {color: #008000; font-weight: bold;}
4 .cm-s-ipython span.cm-number {color: #000080;}
5 .cm-s-ipython span.cm-operator {color: #AA22FF; font-weight: bold;}
6 .cm-s-ipython span.cm-meta {color: #AA22FF;}
7 .cm-s-ipython span.cm-comment {color: #408080; font-style: italic;}
8 .cm-s-ipython span.cm-string {color: #BA2121;}
9 .cm-s-ipython span.cm-error {color: #f00;}
10 .cm-s-ipython span.cm-builtin {color: #008000;}
11 .cm-s-ipython span.cm-variable {color: #000000;}
12
13 /* These classes are not currently used in the python.js mode */
14
15 /*.cm-s-ipython span.cm-atom {color: #219;}*/
16 /*.cm-s-ipython span.cm-def {color: #00f;}*/
17 /*.cm-s-ipython span.cm-variable-2 {color: #05a;}*/
18 /*.cm-s-ipython span.cm-variable-3 {color: #0a5;}*/
19 /*.cm-s-ipython span.cm-property {color: black;}*/
20 /*.cm-s-ipython span.cm-qualifier {color: #555;}*/
21 /*.cm-s-ipython span.cm-bracket {color: #cc7;}*/
22 /*.cm-s-ipython span.cm-tag {color: #170;}*/
23 /*.cm-s-ipython span.cm-attribute {color: #00c;}*/
24
25 /* These are the old styles for our pre-themed version */
26
27 /*span.py-delimiter {color: #666666;}*/
28 /*span.py-special {color: #666666;}*/
29 /*span.py-operator {color: #AA22FF; font-weight: bold;}*/
30 /*span.py-keyword {color: #008000; font-weight: bold;}*/
31 /*span.py-number {color: #666666;}*/
32 /*span.py-identifier {color: #000000;}*/
33 /*span.py-func {color: #000000;}*/
34 /*span.py-type {color: #008000;}*/
35 /*span.py-decorator {color: #AA22FF;}*/
36 /*span.py-comment {color: #408080; font-style: italic;}*/
37 /*span.py-string {color: #BA2121;}*/
38 /*span.py-bytes {color: #BA2121;}*/
39 /*span.py-raw {color: #BA2121;}*/
40 /*span.py-unicode {color: #BA2121;}*/
General Comments 0
You need to be logged in to leave comments. Login now