├── css ├── baboon.png └── docs.css ├── mode ├── diff │ ├── diff.css │ ├── diff.js │ └── index.html ├── python │ ├── LICENSE.txt │ └── index.html ├── coffeescript │ └── LICENSE ├── css │ ├── index.html │ └── css.js ├── sparql │ ├── index.html │ └── sparql.js ├── rst │ └── rst.css ├── r │ ├── LICENSE │ ├── index.html │ └── r.js ├── ruby │ ├── LICENSE │ ├── index.html │ └── ruby.js ├── php │ ├── index.html │ └── php.js ├── smalltalk │ ├── index.html │ └── smalltalk.js ├── xml │ ├── index.html │ └── xml.js ├── htmlmixed │ ├── index.html │ └── htmlmixed.js ├── plsql │ ├── index.html │ └── plsql.js ├── lua │ ├── index.html │ └── lua.js ├── haskell │ ├── index.html │ └── haskell.js ├── yaml │ ├── index.html │ └── yaml.js ├── scheme │ └── index.html ├── xmlpure │ └── index.html ├── javascript │ └── index.html ├── velocity │ ├── index.html │ └── velocity.js ├── clike │ ├── index.html │ └── clike.js └── stex │ ├── index.html │ └── stex.js ├── README.md ├── theme ├── neat.css ├── elegant.css ├── default.css ├── cobalt.css └── night.css ├── test ├── index.html └── test.js ├── lib ├── runmode.js ├── codemirror.css └── overlay.js ├── LICENSE ├── demo ├── resize.html ├── marker.html ├── changemode.html ├── theme.html ├── mustache.html ├── runmode.html ├── preview.html ├── complete.html ├── activeline.html ├── search.html ├── complete.js └── fullscreen.html ├── compress.html └── oldrelease.html /css/baboon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ttscoff/CodeMirror2/master/css/baboon.png -------------------------------------------------------------------------------- /mode/diff/diff.css: -------------------------------------------------------------------------------- 1 | .cm-s-default span.cm-rangeinfo {color: #a0b;} 2 | .cm-s-default span.cm-minus {color: #a22;} 3 | .cm-s-default span.cm-plus {color: #2b2;} 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CodeMirror 2 2 | 3 | CodeMirror 2 is a rewrite of [CodeMirror 4 | 1](http://github.com/marijnh/CodeMirror). The docs live 5 | [here](http://codemirror.net/manual.html), and the project page is 6 | [http://codemirror.net/](http://codemirror.net/). 7 | -------------------------------------------------------------------------------- /mode/diff/diff.js: -------------------------------------------------------------------------------- 1 | CodeMirror.defineMode("diff", function() { 2 | return { 3 | token: function(stream) { 4 | var ch = stream.next(); 5 | stream.skipToEnd(); 6 | if (ch == "+") return "plus"; 7 | if (ch == "-") return "minus"; 8 | if (ch == "@") return "rangeinfo"; 9 | } 10 | }; 11 | }); 12 | 13 | CodeMirror.defineMIME("text/x-diff", "diff"); 14 | -------------------------------------------------------------------------------- /theme/neat.css: -------------------------------------------------------------------------------- 1 | .cm-s-neat span.cm-comment { color: #a86; } 2 | .cm-s-neat span.cm-keyword { font-weight: bold; color: blue; } 3 | .cm-s-neat span.cm-string { color: #a22; } 4 | .cm-s-neat span.cm-builtin { font-weight: bold; color: #077; } 5 | .cm-s-neat span.cm-special { font-weight: bold; color: #0aa; } 6 | .cm-s-neat span.cm-variable { color: black; } 7 | .cm-s-neat span.cm-number, .cm-s-neat span.cm-atom { color: #3a3; } 8 | .cm-s-neat span.cm-meta {color: #555;} 9 | -------------------------------------------------------------------------------- /theme/elegant.css: -------------------------------------------------------------------------------- 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;} 3 | .cm-s-elegant span.cm-meta {color: #555;font-style: italic;} 4 | .cm-s-elegant span.cm-variable {color: black;} 5 | .cm-s-elegant span.cm-variable-2 {color: #b11;} 6 | .cm-s-elegant span.cm-qualifier {color: #555;} 7 | .cm-s-elegant span.cm-keyword {color: #730;} 8 | .cm-s-elegant span.cm-builtin {color: #30a;} 9 | .cm-s-elegant span.cm-error {background-color: #fdd;} 10 | -------------------------------------------------------------------------------- /test/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | CodeMirror 2: Test Suite 5 | 6 | 7 | 8 | 9 | 10 | 15 | 16 | 17 |

CodeMirror 2: Test Suite

18 | 19 |

A limited set of programmatic sanity tests for CodeMirror.

20 | 21 |

22 | 
23 |     
26 | 
27 |     
28 |   
29 | 
30 | 


--------------------------------------------------------------------------------
/theme/default.css:
--------------------------------------------------------------------------------
 1 | .cm-s-default span.cm-keyword {color: #708;}
 2 | .cm-s-default span.cm-atom {color: #219;}
 3 | .cm-s-default span.cm-number {color: #164;}
 4 | .cm-s-default span.cm-def {color: #00f;}
 5 | .cm-s-default span.cm-variable {color: black;}
 6 | .cm-s-default span.cm-variable-2 {color: #05a;}
 7 | .cm-s-default span.cm-variable-3 {color: #0a5;}
 8 | .cm-s-default span.cm-property {color: black;}
 9 | .cm-s-default span.cm-operator {color: black;}
10 | .cm-s-default span.cm-comment {color: #a50;}
11 | .cm-s-default span.cm-string {color: #a11;}
12 | .cm-s-default span.cm-string-2 {color: #f50;}
13 | .cm-s-default span.cm-meta {color: #555;}
14 | .cm-s-default span.cm-error {color: #f00;}
15 | .cm-s-default span.cm-qualifier {color: #555;}
16 | .cm-s-default span.cm-builtin {color: #30a;}
17 | .cm-s-default span.cm-bracket {color: #cc7;}
18 | .cm-s-default span.cm-tag {color: #170;}
19 | .cm-s-default span.cm-attribute {color: #00c;}
20 | 


--------------------------------------------------------------------------------
/theme/cobalt.css:
--------------------------------------------------------------------------------
 1 | .cm-s-cobalt { background: #002240; color: white; }
 2 | .cm-s-cobalt span.CodeMirror-selected { background: #b36539 !important; }
 3 | .cm-s-cobalt .CodeMirror-gutter { background: #002240; border-right: 1px solid #aaa; }
 4 | .cm-s-cobalt .CodeMirror-gutter-text { color: #d0d0d0; }
 5 | .cm-s-cobalt .CodeMirror-cursor { border-left: 1px solid white !important; }
 6 | 
 7 | .cm-s-cobalt span.cm-comment { color: #08f; }
 8 | .cm-s-cobalt span.cm-atom { color: #845dc4; }
 9 | .cm-s-cobalt span.cm-number, .cm-s-cobalt span.cm-attribute { color: #ff80e1; }
10 | .cm-s-cobalt span.cm-keyword { color: #ffee80; }
11 | .cm-s-cobalt span.cm-string { color: #3ad900; }
12 | .cm-s-cobalt span.cm-meta { color: #ff9d00; }
13 | .cm-s-cobalt span.cm-variable-2, .cm-s-cobalt span.cm-tag { color: #9effff; }
14 | .cm-s-cobalt span.cm-variable-3, .cm-s-cobalt span.cm-def { color: white; }
15 | .cm-s-cobalt span.cm-error { color: #9d1e15; }
16 | .cm-s-cobalt span.cm-bracket { color: #d8d8d8; }
17 | .cm-s-cobalt span.cm-builtin, .cm-s-cobalt span.cm-special { color: #ff9e59; }
18 | 


--------------------------------------------------------------------------------
/lib/runmode.js:
--------------------------------------------------------------------------------
 1 | CodeMirror.runMode = function(string, modespec, callback) {
 2 |   var mode = CodeMirror.getMode({indentUnit: 2}, modespec);
 3 |   var isNode = callback.nodeType == 1;
 4 |   if (isNode) {
 5 |     var node = callback, accum = [];
 6 |     callback = function(string, style) {
 7 |       if (string == "\n")
 8 |         accum.push("
"); 9 | else if (style) 10 | accum.push("" + CodeMirror.htmlEscape(string) + ""); 11 | else 12 | accum.push(CodeMirror.htmlEscape(string)); 13 | } 14 | } 15 | var lines = CodeMirror.splitLines(string), state = CodeMirror.startState(mode); 16 | for (var i = 0, e = lines.length; i < e; ++i) { 17 | if (i) callback("\n"); 18 | var stream = new CodeMirror.StringStream(lines[i]); 19 | while (!stream.eol()) { 20 | var style = mode.token(stream, state); 21 | callback(stream.current(), style); 22 | stream.start = stream.pos; 23 | } 24 | } 25 | if (isNode) 26 | node.innerHTML = accum.join(""); 27 | }; 28 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (C) 2011 by Marijn Haverbeke 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. 20 | -------------------------------------------------------------------------------- /theme/night.css: -------------------------------------------------------------------------------- 1 | /* Loosely based on the Midnight Textmate theme */ 2 | 3 | .cm-s-night { background: #0a001f; color: #f8f8f8; } 4 | .cm-s-night span.CodeMirror-selected { background: #a8f !important; } 5 | .cm-s-night .CodeMirror-gutter { background: #0a001f; border-right: 1px solid #aaa; } 6 | .cm-s-night .CodeMirror-gutter-text { color: #f8f8f8; } 7 | .cm-s-night .CodeMirror-cursor { border-left: 1px solid white !important; } 8 | 9 | .cm-s-night span.cm-comment { color: #6900a1; } 10 | .cm-s-night span.cm-atom { color: #845dc4; } 11 | .cm-s-night span.cm-number, .cm-s-night span.cm-attribute { color: #ffd500; } 12 | .cm-s-night span.cm-keyword { color: #599eff; } 13 | .cm-s-night span.cm-string { color: #37f14a; } 14 | .cm-s-night span.cm-meta { color: #7678e2; } 15 | .cm-s-night span.cm-variable-2, .cm-s-night span.cm-tag { color: #99b2ff; } 16 | .cm-s-night span.cm-variable-3, .cm-s-night span.cm-def { color: white; } 17 | .cm-s-night span.cm-error { color: #9d1e15; } 18 | .cm-s-night span.cm-bracket { color: #8da6ce; } 19 | .cm-s-night span.cm-comment { color: #6900a1; } 20 | .cm-s-night span.cm-builtin, .cm-s-night span.cm-special { color: #ff9e59; } 21 | -------------------------------------------------------------------------------- /mode/python/LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2010 Timothy Farrell 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. -------------------------------------------------------------------------------- /mode/coffeescript/LICENSE: -------------------------------------------------------------------------------- 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. -------------------------------------------------------------------------------- /demo/resize.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | CodeMirror 2: Autoresize Demo 5 | 6 | 7 | 8 | 9 | 10 | 11 | 22 | 23 | 24 |

CodeMirror 2: Autoresize demo

25 | 26 |
33 | 34 |

By setting a few CSS properties, CodeMirror can be made to 35 | automatically resize to fit its content.

36 | 37 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /mode/css/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | CodeMirror 2: CSS mode 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |

CodeMirror 2: CSS mode

14 |
49 | 52 | 53 |

MIME types defined: text/css.

54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /mode/sparql/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | CodeMirror 2: SPARQL mode 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |

CodeMirror 2: SPARQL mode

14 |
30 | 37 | 38 |

MIME types defined: application/x-sparql-query.

39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /mode/rst/rst.css: -------------------------------------------------------------------------------- 1 | .cm-s-default span.cm-emphasis { 2 | font-style: italic; 3 | } 4 | 5 | .cm-s-default span.cm-strong { 6 | font-weight: bold; 7 | } 8 | 9 | .cm-s-default span.cm-interpreted { 10 | color: #33cc66; 11 | } 12 | 13 | .cm-s-default span.cm-inline { 14 | color: #3399cc; 15 | } 16 | 17 | .cm-s-default span.cm-role { 18 | color: #666699; 19 | } 20 | 21 | .cm-s-default span.cm-list { 22 | color: #cc0099; 23 | font-weight: bold; 24 | } 25 | 26 | .cm-s-default span.cm-body { 27 | color: #6699cc; 28 | } 29 | 30 | .cm-s-default span.cm-verbatim { 31 | color: #3366ff; 32 | } 33 | 34 | .cm-s-default span.cm-comment { 35 | color: #aa7700; 36 | } 37 | 38 | .cm-s-default span.cm-directive { 39 | font-weight: bold; 40 | color: #3399ff; 41 | } 42 | 43 | .cm-s-default span.cm-hyperlink { 44 | font-weight: bold; 45 | color: #3366ff; 46 | } 47 | 48 | .cm-s-default span.cm-footnote { 49 | font-weight: bold; 50 | color: #3333ff; 51 | } 52 | 53 | .cm-s-default span.cm-citation { 54 | font-weight: bold; 55 | color: #3300ff; 56 | } 57 | 58 | .cm-s-default span.cm-replacement { 59 | color: #9933cc; 60 | } 61 | 62 | .cm-s-default span.cm-section { 63 | font-weight: bold; 64 | color: #cc0099; 65 | } 66 | 67 | .cm-s-default span.cm-directive-marker { 68 | font-weight: bold; 69 | color: #3399ff; 70 | } 71 | 72 | .cm-s-default span.cm-verbatim-marker { 73 | font-weight: bold; 74 | color: #9900ff; 75 | } 76 | -------------------------------------------------------------------------------- /mode/r/LICENSE: -------------------------------------------------------------------------------- 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. 25 | -------------------------------------------------------------------------------- /mode/ruby/LICENSE: -------------------------------------------------------------------------------- 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. 25 | -------------------------------------------------------------------------------- /demo/marker.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | CodeMirror 2: Breakpoint Demo 5 | 6 | 7 | 8 | 9 | 10 | 11 | 20 | 21 | 22 |

CodeMirror 2: Breakpoint demo

23 | 24 |
36 | 37 |

Click the line-number gutter to add or remove 'breakpoints'.

38 | 39 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /demo/changemode.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | CodeMirror 2: Mode-Changing Demo 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 15 | 16 | 17 |

CodeMirror 2: Mode-Changing demo

18 | 19 |
26 | 27 |

On changes to the content of the above editor, a (crude) script 28 | tries to auto-detect the language used, and switches the editor to 29 | either JavaScript or Scheme mode based on that.

30 | 31 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /lib/codemirror.css: -------------------------------------------------------------------------------- 1 | .CodeMirror { 2 | line-height: 1em; 3 | font-family: monospace; 4 | } 5 | 6 | .CodeMirror-scroll { 7 | overflow: auto; 8 | height: 300px; 9 | /* This is needed to prevent an IE[67] bug where the scrolled content 10 | is visible outside of the scrolling box. */ 11 | position: relative; 12 | } 13 | 14 | .CodeMirror-gutter { 15 | position: absolute; left: 0; top: 0; 16 | z-index: 10; 17 | background-color: #f7f7f7; 18 | border-right: 1px solid #eee; 19 | min-width: 2em; 20 | height: 100%; 21 | } 22 | .CodeMirror-gutter-text { 23 | color: #aaa; 24 | text-align: right; 25 | padding: .4em .2em .4em .4em; 26 | } 27 | .CodeMirror-lines { 28 | padding: .4em; 29 | } 30 | 31 | .CodeMirror pre { 32 | -moz-border-radius: 0; 33 | -webkit-border-radius: 0; 34 | -o-border-radius: 0; 35 | border-radius: 0; 36 | border-width: 0; margin: 0; padding: 0; background: transparent; 37 | font-family: inherit; 38 | font-size: inherit; 39 | padding: 0; margin: 0; 40 | white-space: pre; 41 | word-wrap: normal; 42 | } 43 | 44 | .CodeMirror textarea { 45 | font-family: inherit !important; 46 | font-size: inherit !important; 47 | } 48 | 49 | .CodeMirror-cursor { 50 | z-index: 10; 51 | position: absolute; 52 | visibility: hidden; 53 | border-left: 1px solid black !important; 54 | } 55 | .CodeMirror-focused .CodeMirror-cursor { 56 | visibility: visible; 57 | } 58 | 59 | span.CodeMirror-selected { 60 | background: #ccc !important; 61 | color: HighlightText !important; 62 | } 63 | .CodeMirror-focused span.CodeMirror-selected { 64 | background: Highlight !important; 65 | } 66 | 67 | .CodeMirror-matchingbracket {color: #0f0 !important;} 68 | .CodeMirror-nonmatchingbracket {color: #f22 !important;} 69 | -------------------------------------------------------------------------------- /mode/php/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | CodeMirror 2: PHP mode 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 |

CodeMirror 2: PHP mode

18 | 19 |
30 | 31 | 42 | 43 |

Simple HTML/PHP mode based on 44 | the C-like mode. Depends on XML, 45 | JavaScript, CSS, and C-like modes.

46 | 47 |

MIME types defined: application/x-httpd-php (HTML with PHP code), text/x-php (plain, non-wrapped PHP code).

48 | 49 | 50 | -------------------------------------------------------------------------------- /mode/smalltalk/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | CodeMirror 2: Smalltalk mode 5 | 6 | 7 | 8 | 9 | 10 | 15 | 16 | 17 |

CodeMirror 2: Smalltalk mode

18 | 19 |
42 | 43 | 51 | 52 |

Simple Smalltalk mode.

53 | 54 |

MIME types defined: text/x-stsrc.

55 | 56 | 57 | -------------------------------------------------------------------------------- /demo/theme.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | CodeMirror 2: Theme Demo 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 18 | 19 | 20 |

CodeMirror 2: Theme demo

21 | 22 |
35 | 36 |

Select a theme: 43 |

44 | 45 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /mode/xml/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | CodeMirror 2: XML mode 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |

CodeMirror 2: XML mode

14 |
26 | 29 |

The XML mode supports two configuration parameters:

30 |
31 |
htmlMode (boolean)
32 |
This switches the mode to parse HTML instead of XML. This 33 | means attributes do not have to be quoted, and some elements 34 | (such as br) do not require a closing tag.
35 |
alignCDATA (boolean)
36 |
Setting this to true will force the opening tag of CDATA 37 | blocks to not be indented.
38 |
39 | 40 |

MIME types defined: application/xml, text/html.

41 | 42 | 43 | -------------------------------------------------------------------------------- /mode/htmlmixed/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | CodeMirror 2: HTML mixed mode 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |

CodeMirror 2: HTML mixed mode

17 |
41 | 44 | 45 |

The HTML mixed mode depends on the XML, JavaScript, and CSS modes.

46 | 47 |

MIME types defined: text/html 48 | (redefined, only takes effect if you load this parser after the 49 | XML parser).

50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /mode/plsql/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | CodeMirror 2: Oracle PL/SQL mode 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |

CodeMirror 2: Oracle PL/SQL mode

14 | 15 |
47 | 48 | 56 | 57 |

58 | Simple mode that handles Oracle PL/SQL language (and Oracle SQL, of course). 59 |

60 | 61 |

MIME type defined: text/x-plsql 62 | (PLSQL code) 63 | 64 | -------------------------------------------------------------------------------- /mode/lua/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | CodeMirror 2: Lua mode 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |

CodeMirror 2: Lua mode

14 |
55 | 62 | 63 |

Loosely based on Franciszek 64 | Wawrzak's CodeMirror 65 | 1 mode. One configuration parameter is 66 | supported, specials, to which you can provide an 67 | array of strings to have those identifiers highlighted with 68 | the lua-special style.

69 |

MIME types defined: text/x-lua.

70 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /demo/mustache.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | CodeMirror 2: Overlay Parser Demo 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 16 | 17 | 18 |

CodeMirror 2: Overlay Parser Demo

19 | 20 |
31 | 32 | 49 | 50 |

Demonstration of a mode that parses HTML, highlighting 51 | the Mustache templating 52 | directives inside of it by using the code 53 | in overlay.js. View 54 | source to see the 15 lines of code needed to accomplish this.

55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /mode/haskell/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | CodeMirror 2: Haskell mode 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |

CodeMirror 2: Haskell mode

14 | 15 |
49 | 50 | 57 | 58 |

MIME types defined: text/x-haskell.

59 | 60 | 61 | -------------------------------------------------------------------------------- /lib/overlay.js: -------------------------------------------------------------------------------- 1 | // Utility function that allows modes to be combined. The mode given 2 | // as the base argument takes care of most of the normal mode 3 | // functionality, but a second (typically simple) mode is used, which 4 | // can override the style of text. Both modes get to parse all of the 5 | // text, but when both assign a non-null style to a piece of code, the 6 | // overlay wins, unless the combine argument was true, in which case 7 | // the styles are combined. 8 | 9 | CodeMirror.overlayParser = function(base, overlay, combine) { 10 | return { 11 | startState: function() { 12 | return { 13 | base: CodeMirror.startState(base), 14 | overlay: CodeMirror.startState(overlay), 15 | basePos: 0, baseCur: null, 16 | overlayPos: 0, overlayCur: null 17 | }; 18 | }, 19 | copyState: function(state) { 20 | return { 21 | base: CodeMirror.copyState(base, state.base), 22 | overlay: CodeMirror.copyState(overlay, state.overlay), 23 | basePos: state.basePos, baseCur: null, 24 | overlayPos: state.overlayPos, overlayCur: null 25 | }; 26 | }, 27 | 28 | token: function(stream, state) { 29 | if (stream.start == state.basePos) { 30 | state.baseCur = base.token(stream, state.base); 31 | state.basePos = stream.pos; 32 | } 33 | if (stream.start == state.overlayPos) { 34 | stream.pos = stream.start; 35 | state.overlayCur = overlay.token(stream, state.overlay); 36 | state.overlayPos = stream.pos; 37 | } 38 | stream.pos = Math.min(state.basePos, state.overlayPos); 39 | if (stream.eol()) state.basePos = state.overlayPos = 0; 40 | 41 | if (state.overlayCur == null) return state.baseCur; 42 | if (state.baseCur != null && combine) return state.baseCur + " " + state.overlayCur; 43 | else return state.overlayCur; 44 | }, 45 | 46 | indent: function(state, textAfter) { 47 | return base.indent(state.base, textAfter); 48 | }, 49 | electricChars: base.electricChars 50 | }; 51 | }; 52 | -------------------------------------------------------------------------------- /mode/yaml/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | CodeMirror 2: YAML mode 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |

CodeMirror 2: YAML mode

14 |
61 | 64 | 65 |

MIME types defined: text/x-yaml.

66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /demo/runmode.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | CodeMirror 2: Mode Runner Demo 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |

CodeMirror 2: Mode Runner Demo

14 | 15 |
21 | 22 |

23 | 
24 |     
30 | 
31 |     

Running a CodeMirror mode outside of the editor. 32 | The CodeMirror.runMode function, defined 33 | in lib/runmode.js takes the following arguments:

34 | 35 |
36 |
text (string)
37 |
The document to run through the highlighter.
38 |
mode (mode spec)
39 |
The mode to use (must be loaded as normal).
40 |
output (function or DOM node)
41 |
If this is a function, it will be called for each token with 42 | two arguments, the token's text and the token's style class (may 43 | be null for unstyled tokens). If it is a DOM node, 44 | the tokens will be converted to span elements as in 45 | an editor, and inserted into the node 46 | (through innerHTML).
47 |
48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /demo/preview.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | CodeMirror 2: HTML5 preview 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 28 | 29 | 30 |

CodeMirror 2: HTML5 preview

31 | 53 | 54 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /mode/scheme/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | CodeMirror 2: Scheme mode 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |

CodeMirror 2: Scheme mode

14 |
58 | 61 | 62 |

MIME types defined: text/x-scheme.

63 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /mode/r/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | CodeMirror 2: R mode 5 | 6 | 7 | 8 | 9 | 16 | 17 | 18 | 19 |

CodeMirror 2: R mode

20 |
63 | 66 | 67 |

MIME types defined: text/x-rsrc.

68 | 69 |

Development of the CodeMirror R mode was kindly sponsored 70 | by Ubalo, who hold 71 | the license.

72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /mode/xmlpure/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | CodeMirror 2: Pure XML mode 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |

CodeMirror 2: XML mode

14 |
31 | 34 | 35 |

This is my XML parser, based on the original:

36 | 44 | 45 |

What's missing:

46 | 51 | 52 |

MIME types defined: application/xml, text/xml.

53 | 54 |

@author: Dror BG (deebug dot dev at gmail dot com)
55 |

@date: August, 2011
56 |

@github: https://github.com/deebugger/CodeMirror2

57 | 58 |

MIME types defined: application/xml, text/xml.

59 | 60 | 61 | -------------------------------------------------------------------------------- /demo/complete.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | CodeMirror 2: Autocomplete Demo 5 | 6 | 7 | 8 | 9 | 10 | 11 | 32 | 33 | 34 |

CodeMirror 2: Autocomplete demo

35 | 36 |
73 | 74 |

Press ctrl-space to activate autocompletion. See 75 | the code to figure out how it works.

76 | 77 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /css/docs.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: Droid Sans, Arial, sans-serif; 3 | line-height: 1.5; 4 | max-width: 64.3em; 5 | margin: 3em auto; 6 | padding: 0 1em; 7 | } 8 | 9 | h1 { 10 | letter-spacing: -3px; 11 | font-size: 3.23em; 12 | font-weight: bold; 13 | margin: 0; 14 | } 15 | 16 | h2 { 17 | font-size: 1.23em; 18 | font-weight: bold; 19 | margin: .5em 0; 20 | letter-spacing: -1px; 21 | } 22 | 23 | h3 { 24 | font-size: 1em; 25 | font-weight: bold; 26 | margin: .4em 0; 27 | } 28 | 29 | pre { 30 | background-color: #eee; 31 | -moz-border-radius: 6px; 32 | -webkit-border-radius: 6px; 33 | border-radius: 6px; 34 | padding: 1em; 35 | } 36 | 37 | pre.code { 38 | margin: 0 1em; 39 | } 40 | 41 | .grey { 42 | font-size: 2.2em; 43 | padding: .5em 1em; 44 | line-height: 1.2em; 45 | margin-top: .5em; 46 | position: relative; 47 | } 48 | 49 | img.logo { 50 | position: absolute; 51 | right: -25px; 52 | bottom: 4px; 53 | } 54 | 55 | a:link, a:visited, .quasilink { 56 | color: #df0019; 57 | cursor: pointer; 58 | text-decoration: none; 59 | } 60 | 61 | a:hover, .quasilink:hover { 62 | color: #800004; 63 | } 64 | 65 | h1 a:link, h1 a:visited, h1 a:hover { 66 | color: black; 67 | } 68 | 69 | ul { 70 | margin: 0; 71 | padding-left: 1.2em; 72 | } 73 | 74 | a.download { 75 | color: white; 76 | background-color: #df0019; 77 | width: 100%; 78 | display: block; 79 | text-align: center; 80 | font-size: 1.23em; 81 | font-weight: bold; 82 | text-decoration: none; 83 | -moz-border-radius: 6px; 84 | -webkit-border-radius: 6px; 85 | border-radius: 6px; 86 | padding: .5em 0; 87 | margin-bottom: 1em; 88 | } 89 | 90 | a.download:hover { 91 | background-color: #bb0010; 92 | } 93 | 94 | .rel { 95 | margin-bottom: 0; 96 | } 97 | 98 | .rel-note { 99 | color: #777; 100 | font-size: .9em; 101 | margin-top: .1em; 102 | } 103 | 104 | .logo-braces { 105 | color: #df0019; 106 | position: relative; 107 | top: -4px; 108 | } 109 | 110 | .blk { 111 | float: left; 112 | } 113 | 114 | .left { 115 | width: 37em; 116 | padding-right: 6.53em; 117 | padding-bottom: 1em; 118 | } 119 | 120 | .left1 { 121 | width: 15.24em; 122 | padding-right: 6.45em; 123 | } 124 | 125 | .left2 { 126 | width: 15.24em; 127 | } 128 | 129 | .right { 130 | width: 20.68em; 131 | } 132 | 133 | .leftbig { 134 | width: 42.44em; 135 | padding-right: 6.53em; 136 | } 137 | 138 | .rightsmall { 139 | width: 15.24em; 140 | } 141 | 142 | .clear:after { 143 | visibility: hidden; 144 | display: block; 145 | font-size: 0; 146 | content: " "; 147 | clear: both; 148 | height: 0; 149 | } 150 | .clear { display: inline-block; } 151 | /* start commented backslash hack \*/ 152 | * html .clear { height: 1%; } 153 | .clear { display: block; } 154 | /* close commented backslash hack */ 155 | -------------------------------------------------------------------------------- /mode/javascript/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | CodeMirror 2: JavaScript mode 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |

CodeMirror 2: JavaScript mode

14 | 15 |
64 | 65 | 71 | 72 |

JavaScript mode supports a single configuration 73 | option, json, which will set the mode to expect JSON 74 | data rather than a JavaScript program.

75 | 76 |

MIME types defined: text/javascript, application/json.

77 | 78 | 79 | -------------------------------------------------------------------------------- /demo/activeline.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | CodeMirror 2: Active Line Demo 5 | 6 | 7 | 8 | 9 | 10 | 11 | 15 | 16 | 17 |

CodeMirror 2: Active Line Demo

18 | 19 |
56 | 57 | 68 | 69 |

Styling the current cursor line.

70 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /mode/htmlmixed/htmlmixed.js: -------------------------------------------------------------------------------- 1 | CodeMirror.defineMode("htmlmixed", function(config, parserConfig) { 2 | var htmlMode = CodeMirror.getMode(config, {name: "xml", htmlMode: true}); 3 | var jsMode = CodeMirror.getMode(config, "javascript"); 4 | var cssMode = CodeMirror.getMode(config, "css"); 5 | 6 | function html(stream, state) { 7 | var style = htmlMode.token(stream, state.htmlState); 8 | if (style == "tag" && stream.current() == ">" && state.htmlState.context) { 9 | if (/^script$/i.test(state.htmlState.context.tagName)) { 10 | state.token = javascript; 11 | state.localState = jsMode.startState(htmlMode.indent(state.htmlState, "")); 12 | state.mode = "javascript"; 13 | } 14 | else if (/^style$/i.test(state.htmlState.context.tagName)) { 15 | state.token = css; 16 | state.localState = cssMode.startState(htmlMode.indent(state.htmlState, "")); 17 | state.mode = "css"; 18 | } 19 | } 20 | return style; 21 | } 22 | function maybeBackup(stream, pat, style) { 23 | var cur = stream.current(); 24 | var close = cur.search(pat); 25 | if (close > -1) stream.backUp(cur.length - close); 26 | return style; 27 | } 28 | function javascript(stream, state) { 29 | if (stream.match(/^<\/\s*script\s*>/i, false)) { 30 | state.token = html; 31 | state.curState = null; 32 | state.mode = "html"; 33 | return html(stream, state); 34 | } 35 | return maybeBackup(stream, /<\/\s*script\s*>/, 36 | jsMode.token(stream, state.localState)); 37 | } 38 | function css(stream, state) { 39 | if (stream.match(/^<\/\s*style\s*>/i, false)) { 40 | state.token = html; 41 | state.localState = null; 42 | state.mode = "html"; 43 | return html(stream, state); 44 | } 45 | return maybeBackup(stream, /<\/\s*style\s*>/, 46 | cssMode.token(stream, state.localState)); 47 | } 48 | 49 | return { 50 | startState: function() { 51 | var state = htmlMode.startState(); 52 | return {token: html, localState: null, mode: "html", htmlState: state}; 53 | }, 54 | 55 | copyState: function(state) { 56 | if (state.localState) 57 | var local = CodeMirror.copyState(state.token == css ? cssMode : jsMode, state.localState); 58 | return {token: state.token, localState: local, mode: state.mode, 59 | htmlState: CodeMirror.copyState(htmlMode, state.htmlState)}; 60 | }, 61 | 62 | token: function(stream, state) { 63 | return state.token(stream, state); 64 | }, 65 | 66 | indent: function(state, textAfter) { 67 | if (state.token == html || /^\s*<\//.test(textAfter)) 68 | return htmlMode.indent(state.htmlState, textAfter); 69 | else if (state.token == javascript) 70 | return jsMode.indent(state.localState, textAfter); 71 | else 72 | return cssMode.indent(state.localState, textAfter); 73 | }, 74 | 75 | electricChars: "/{}:" 76 | } 77 | }); 78 | 79 | CodeMirror.defineMIME("text/html", "htmlmixed"); 80 | -------------------------------------------------------------------------------- /mode/yaml/yaml.js: -------------------------------------------------------------------------------- 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"); 96 | -------------------------------------------------------------------------------- /mode/velocity/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | CodeMirror 2: Velocity mode 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |

CodeMirror 2: Velocity mode

14 |
89 | 99 | 100 |

MIME types defined: text/velocity.

101 | 102 | 103 | 104 | -------------------------------------------------------------------------------- /mode/python/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | CodeMirror 2: Python mode 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |

CodeMirror 2: Python mode

14 | 15 |
104 | 115 |

Configuration Options:

116 | 120 | 121 |

MIME types defined: text/x-python.

122 | 123 | 124 | -------------------------------------------------------------------------------- /mode/clike/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | CodeMirror 2: C-like mode 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |

CodeMirror 2: C-like mode

14 | 15 |
82 | 83 | 90 | 91 |

Simple mode that tries to handle C-like languages as well as it 92 | can. Takes two configuration parameters: keywords, an 93 | object whose property names are the keywords in the language, 94 | and useCPP, which determines whether C preprocessor 95 | directives are recognized.

96 | 97 |

MIME types defined: text/x-csrc 98 | (C code), text/x-c++src (C++ 99 | code), text/x-java (Java 100 | code), text/x-groovy (Groovy code).

101 | 102 | 103 | -------------------------------------------------------------------------------- /mode/stex/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | CodeMirror 2: sTeX mode 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |

CodeMirror 2: sTeX mode

14 |
89 | 92 | 93 |

MIME types defined: text/stex.

94 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /mode/smalltalk/smalltalk.js: -------------------------------------------------------------------------------- 1 | CodeMirror.defineMode("smalltalk", function(config, parserConfig) { 2 | var keywords = {"true": 1, "false": 1, nil: 1, self: 1, "super": 1, thisContext: 1}; 3 | var indentUnit = config.indentUnit; 4 | 5 | function chain(stream, state, f) { 6 | state.tokenize = f; 7 | return f(stream, state); 8 | } 9 | 10 | var type; 11 | function ret(tp, style) { 12 | type = tp; 13 | return style; 14 | } 15 | 16 | function tokenBase(stream, state) { 17 | var ch = stream.next(); 18 | if (ch == '"') 19 | return chain(stream, state, tokenComment(ch)); 20 | else if (ch == "'") 21 | return chain(stream, state, tokenString(ch)); 22 | else if (ch == "#") { 23 | stream.eatWhile(/[\w\$_]/); 24 | return ret("string", "string"); 25 | } 26 | else if (/\d/.test(ch)) { 27 | stream.eatWhile(/[\w\.]/) 28 | return ret("number", "number"); 29 | } 30 | else if (/[\[\]()]/.test(ch)) { 31 | return ret(ch, null); 32 | } 33 | else { 34 | stream.eatWhile(/[\w\$_]/); 35 | if (keywords && keywords.propertyIsEnumerable(stream.current())) return ret("keyword", "keyword"); 36 | return ret("word", "variable"); 37 | } 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) {end = true; break;} 45 | escaped = !escaped && next == "\\"; 46 | } 47 | if (end || !(escaped)) 48 | state.tokenize = tokenBase; 49 | return ret("string", "string"); 50 | }; 51 | } 52 | 53 | function tokenComment(quote) { 54 | return function(stream, state) { 55 | var next, end = false; 56 | while ((next = stream.next()) != null) { 57 | if (next == quote) {end = true; break;} 58 | } 59 | if (end) 60 | state.tokenize = tokenBase; 61 | return ret("comment", "comment"); 62 | }; 63 | } 64 | 65 | function Context(indented, column, type, align, prev) { 66 | this.indented = indented; 67 | this.column = column; 68 | this.type = type; 69 | this.align = align; 70 | this.prev = prev; 71 | } 72 | 73 | function pushContext(state, col, type) { 74 | return state.context = new Context(state.indented, col, type, null, state.context); 75 | } 76 | function popContext(state) { 77 | return state.context = state.context.prev; 78 | } 79 | 80 | // Interface 81 | 82 | return { 83 | startState: function(basecolumn) { 84 | return { 85 | tokenize: tokenBase, 86 | context: new Context((basecolumn || 0) - indentUnit, 0, "top", false), 87 | indented: 0, 88 | startOfLine: true 89 | }; 90 | }, 91 | 92 | token: function(stream, state) { 93 | var ctx = state.context; 94 | if (stream.sol()) { 95 | if (ctx.align == null) ctx.align = false; 96 | state.indented = stream.indentation(); 97 | state.startOfLine = true; 98 | } 99 | if (stream.eatSpace()) return null; 100 | var style = state.tokenize(stream, state); 101 | if (type == "comment") return style; 102 | if (ctx.align == null) ctx.align = true; 103 | 104 | if (type == "[") pushContext(state, stream.column(), "]"); 105 | else if (type == "(") pushContext(state, stream.column(), ")"); 106 | else if (type == ctx.type) popContext(state); 107 | state.startOfLine = false; 108 | return style; 109 | }, 110 | 111 | indent: function(state, textAfter) { 112 | if (state.tokenize != tokenBase) return 0; 113 | var firstChar = textAfter && textAfter.charAt(0), ctx = state.context, closing = firstChar == ctx.type; 114 | if (ctx.align) return ctx.column + (closing ? 0 : 1); 115 | else return ctx.indented + (closing ? 0 : indentUnit); 116 | }, 117 | 118 | electricChars: "]" 119 | }; 120 | }); 121 | 122 | CodeMirror.defineMIME("text/x-stsrc", {name: "smalltalk"}); 123 | -------------------------------------------------------------------------------- /mode/css/css.js: -------------------------------------------------------------------------------- 1 | CodeMirror.defineMode("css", function(config) { 2 | var indentUnit = config.indentUnit, type; 3 | function ret(style, tp) {type = tp; return style;} 4 | 5 | function tokenBase(stream, state) { 6 | var ch = stream.next(); 7 | if (ch == "@") {stream.eatWhile(/\w/); return ret("meta", stream.current());} 8 | else if (ch == "/" && stream.eat("*")) { 9 | state.tokenize = tokenCComment; 10 | return tokenCComment(stream, state); 11 | } 12 | else if (ch == "<" && stream.eat("!")) { 13 | state.tokenize = tokenSGMLComment; 14 | return tokenSGMLComment(stream, state); 15 | } 16 | else if (ch == "=") ret(null, "compare"); 17 | else if ((ch == "~" || ch == "|") && stream.eat("=")) return ret(null, "compare"); 18 | else if (ch == "\"" || ch == "'") { 19 | state.tokenize = tokenString(ch); 20 | return state.tokenize(stream, state); 21 | } 22 | else if (ch == "#") { 23 | stream.eatWhile(/\w/); 24 | return ret("atom", "hash"); 25 | } 26 | else if (ch == "!") { 27 | stream.match(/^\s*\w*/); 28 | return ret("keyword", "important"); 29 | } 30 | else if (/\d/.test(ch)) { 31 | stream.eatWhile(/[\w.%]/); 32 | return ret("number", "unit"); 33 | } 34 | else if (/[,.+>*\/]/.test(ch)) { 35 | return ret(null, "select-op"); 36 | } 37 | else if (/[;{}:\[\]]/.test(ch)) { 38 | return ret(null, ch); 39 | } 40 | else { 41 | stream.eatWhile(/[\w\\\-_]/); 42 | return ret("variable", "variable"); 43 | } 44 | } 45 | 46 | function tokenCComment(stream, state) { 47 | var maybeEnd = false, ch; 48 | while ((ch = stream.next()) != null) { 49 | if (maybeEnd && ch == "/") { 50 | state.tokenize = tokenBase; 51 | break; 52 | } 53 | maybeEnd = (ch == "*"); 54 | } 55 | return ret("comment", "comment"); 56 | } 57 | 58 | function tokenSGMLComment(stream, state) { 59 | var dashes = 0, ch; 60 | while ((ch = stream.next()) != null) { 61 | if (dashes >= 2 && ch == ">") { 62 | state.tokenize = tokenBase; 63 | break; 64 | } 65 | dashes = (ch == "-") ? dashes + 1 : 0; 66 | } 67 | return ret("comment", "comment"); 68 | } 69 | 70 | function tokenString(quote) { 71 | return function(stream, state) { 72 | var escaped = false, ch; 73 | while ((ch = stream.next()) != null) { 74 | if (ch == quote && !escaped) 75 | break; 76 | escaped = !escaped && ch == "\\"; 77 | } 78 | if (!escaped) state.tokenize = tokenBase; 79 | return ret("string", "string"); 80 | }; 81 | } 82 | 83 | return { 84 | startState: function(base) { 85 | return {tokenize: tokenBase, 86 | baseIndent: base || 0, 87 | stack: []}; 88 | }, 89 | 90 | token: function(stream, state) { 91 | if (stream.eatSpace()) return null; 92 | var style = state.tokenize(stream, state); 93 | 94 | var context = state.stack[state.stack.length-1]; 95 | if (type == "hash" && context == "rule") style = "atom"; 96 | else if (style == "variable") { 97 | if (context == "rule") style = "number"; 98 | else if (!context || context == "@media{") style = "tag"; 99 | } 100 | 101 | if (context == "rule" && /^[\{\};]$/.test(type)) 102 | state.stack.pop(); 103 | if (type == "{") { 104 | if (context == "@media") state.stack[state.stack.length-1] = "@media{"; 105 | else state.stack.push("{"); 106 | } 107 | else if (type == "}") state.stack.pop(); 108 | else if (type == "@media") state.stack.push("@media"); 109 | else if (context == "{" && type != "comment") state.stack.push("rule"); 110 | return style; 111 | }, 112 | 113 | indent: function(state, textAfter) { 114 | var n = state.stack.length; 115 | if (/^\}/.test(textAfter)) 116 | n -= state.stack[state.stack.length-1] == "rule" ? 2 : 1; 117 | return state.baseIndent + n * indentUnit; 118 | }, 119 | 120 | electricChars: "}" 121 | }; 122 | }); 123 | 124 | CodeMirror.defineMIME("text/css", "css"); 125 | -------------------------------------------------------------------------------- /mode/diff/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | CodeMirror 2: Diff mode 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |

CodeMirror 2: Diff mode

14 |
92 | 95 | 96 |

MIME types defined: text/x-diff.

97 | 98 | 99 | 100 | -------------------------------------------------------------------------------- /demo/search.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | CodeMirror 2: Search/Replace Demo 5 | 6 | 7 | 8 | 9 | 10 | 11 | 15 | 16 | 17 |

CodeMirror 2: Search/Replace Demo

18 | 19 |
60 | 61 | or 62 | it by 63 | 64 | 65 | 101 | 102 |

Demonstration of search/replace functionality and marking 103 | text.

104 | 105 | 106 | 107 | -------------------------------------------------------------------------------- /mode/stex/stex.js: -------------------------------------------------------------------------------- 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-z]+/)) { 86 | var cmdName = source.current(); 87 | cmdName = cmdName.substr(1, cmdName.length-1); 88 | var plug = plugins[cmdName]; 89 | if (typeof(plug) == 'undefined') { 90 | plug = plugins["DEFAULT"]; 91 | } 92 | plug = new plug(); 93 | pushCommand(state, plug); 94 | setState(state, beginParams); 95 | return plug.style; 96 | } 97 | 98 | var ch = source.next(); 99 | if (ch == "%") { 100 | setState(state, inCComment); 101 | return "comment"; 102 | } 103 | else if (ch=='}' || ch==']') { 104 | plug = peekCommand(state); 105 | if (plug) { 106 | plug.closeBracket(ch); 107 | setState(state, beginParams); 108 | } else 109 | return "error"; 110 | return "bracket"; 111 | } else if (ch=='{' || ch=='[') { 112 | plug = plugins["DEFAULT"]; 113 | plug = new plug(); 114 | pushCommand(state, plug); 115 | return "bracket"; 116 | } 117 | else if (/\d/.test(ch)) { 118 | source.eatWhile(/[\w.%]/); 119 | return "atom"; 120 | } 121 | else { 122 | source.eatWhile(/[\w-_]/); 123 | return applyMostPowerful(state); 124 | } 125 | } 126 | 127 | function inCComment(source, state) { 128 | source.skipToEnd(); 129 | setState(state, normal); 130 | return "comment"; 131 | } 132 | 133 | function beginParams(source, state) { 134 | var ch = source.peek(); 135 | if (ch == '{' || ch == '[') { 136 | var lastPlug = peekCommand(state); 137 | var style = lastPlug.openBracket(ch); 138 | source.eat(ch); 139 | setState(state, normal); 140 | return "bracket"; 141 | } 142 | if (/[ \t\r]/.test(ch)) { 143 | source.eat(ch); 144 | return null; 145 | } 146 | setState(state, normal); 147 | lastPlug = peekCommand(state); 148 | if (lastPlug) { 149 | popCommand(state); 150 | } 151 | return normal(source, state); 152 | } 153 | 154 | return { 155 | startState: function() { return { f:normal, cmdState:[] }; }, 156 | copyState: function(s) { return { f: s.f, cmdState: s.cmdState.slice(0, s.cmdState.length) }; }, 157 | 158 | token: function(stream, state) { 159 | var t = state.f(stream, state); 160 | var w = stream.current(); 161 | return t; 162 | } 163 | }; 164 | }); 165 | 166 | 167 | CodeMirror.defineMIME("text/x-stex", "stex"); 168 | -------------------------------------------------------------------------------- /mode/php/php.js: -------------------------------------------------------------------------------- 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 cfunction class clone const continue declare " + 17 | "default do else elseif enddeclare endfor endforeach endif endswitch endwhile extends " + 18 | "final for foreach function global goto if implements interface instanceof namespace " + 19 | "new or private protected public static switch throw try use var while xor return"), 20 | blockKeywords: keywords("catch do else elseif for foreach if switch try while"), 21 | atoms: keywords("true false null"), 22 | multiLineStrings: true, 23 | hooks: { 24 | "$": function(stream, state) { 25 | stream.eatWhile(/[\w\$_]/); 26 | return "variable-2"; 27 | }, 28 | "<": function(stream, state) { 29 | if (stream.match(/</; 52 | state.mode = 'php'; 53 | } 54 | else if (style == "tag" && stream.current() == ">" && state.curState.context) { 55 | if (/^script$/i.test(state.curState.context.tagName)) { 56 | state.curMode = jsMode; 57 | state.curState = jsMode.startState(htmlMode.indent(state.curState, "")); 58 | state.curClose = /^<\/\s*script\s*>/i; 59 | state.mode = 'javascript'; 60 | } 61 | else if (/^style$/i.test(state.curState.context.tagName)) { 62 | state.curMode = cssMode; 63 | state.curState = cssMode.startState(htmlMode.indent(state.curState, "")); 64 | state.curClose = /^<\/\s*style\s*>/i; 65 | state.mode = 'css'; 66 | } 67 | } 68 | return style; 69 | } 70 | else if (stream.match(state.curClose, false)) { 71 | state.curMode = htmlMode; 72 | state.curState = state.html; 73 | state.curClose = null; 74 | state.mode = 'html'; 75 | return dispatch(stream, state); 76 | } 77 | else return state.curMode.token(stream, state.curState); 78 | } 79 | 80 | return { 81 | startState: function() { 82 | var html = htmlMode.startState(); 83 | return {html: html, 84 | php: phpMode.startState(), 85 | curMode: parserConfig.startOpen ? phpMode : htmlMode, 86 | curState: parserConfig.startOpen ? phpMode.startState() : html, 87 | curClose: parserConfig.startOpen ? /^\?>/ : null, 88 | mode: parserConfig.startOpen ? 'php' : 'html'} 89 | }, 90 | 91 | copyState: function(state) { 92 | var html = state.html, htmlNew = CodeMirror.copyState(htmlMode, html), 93 | php = state.php, phpNew = CodeMirror.copyState(phpMode, php), cur; 94 | if (state.curState == html) cur = htmlNew; 95 | else if (state.curState == php) cur = phpNew; 96 | else cur = CodeMirror.copyState(state.curMode, state.curState); 97 | return {html: htmlNew, php: phpNew, curMode: state.curMode, curState: cur, curClose: state.curClose}; 98 | }, 99 | 100 | token: dispatch, 101 | 102 | indent: function(state, textAfter) { 103 | if ((state.curMode != phpMode && /^\s*<\//.test(textAfter)) || 104 | (state.curMode == phpMode && /^\?>/.test(textAfter))) 105 | return htmlMode.indent(state.html, textAfter); 106 | return state.curMode.indent(state.curState, textAfter); 107 | }, 108 | 109 | electricChars: "/{}:" 110 | } 111 | }); 112 | CodeMirror.defineMIME("application/x-httpd-php", "php"); 113 | CodeMirror.defineMIME("application/x-httpd-php-open", {name: "php", startOpen: true}); 114 | CodeMirror.defineMIME("text/x-php", phpConfig); 115 | })(); 116 | -------------------------------------------------------------------------------- /mode/sparql/sparql.js: -------------------------------------------------------------------------------- 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"); 144 | -------------------------------------------------------------------------------- /mode/r/r.js: -------------------------------------------------------------------------------- 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"); 142 | -------------------------------------------------------------------------------- /mode/velocity/velocity.js: -------------------------------------------------------------------------------- 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"); 147 | -------------------------------------------------------------------------------- /compress.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | CodeMirror: Compression Helper 5 | 6 | 7 | 8 | 9 | 10 | 11 |

{ } CodeMirror

12 | 13 |
14 | /* Script compression
15 |    helper */
16 | 
17 | 18 |

To optimize loading CodeMirror, especially when including a 19 | bunch of different modes, it is recommended that you combine and 20 | minify (and preferably also gzip) the scripts. This page makes 21 | those first two steps very easy. Simply select the version and 22 | scripts you need in the form below, and 23 | click Compress to download the minified script 24 | file.

25 | 26 |
27 | 28 |

Version:

40 | 41 |

71 | 72 |

73 | with UglifyJS 74 |

75 | 76 |

Custom code to add to the compressed file:

77 |
78 | 79 | 94 | 95 | 96 | 97 | 98 | -------------------------------------------------------------------------------- /mode/lua/lua.js: -------------------------------------------------------------------------------- 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","for","while", "\\(", "{"]); 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 (indentTokens.test(word)) ++state.indentDepth; 127 | else if (dedentTokens.test(word)) --state.indentDepth; 128 | return style; 129 | }, 130 | 131 | indent: function(state, textAfter) { 132 | var closing = dedentPartial.test(textAfter); 133 | return state.basecol + indentUnit * (state.indentDepth - (closing ? 1 : 0)); 134 | } 135 | }; 136 | }); 137 | 138 | CodeMirror.defineMIME("text/x-lua", "lua"); 139 | -------------------------------------------------------------------------------- /mode/ruby/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | CodeMirror 2: Ruby mode 5 | 6 | 7 | 8 | 9 | 13 | 14 | 15 | 16 |

CodeMirror 2: Ruby mode

17 |
156 | 164 | 165 |

MIME types defined: text/x-ruby.

166 | 167 |

Development of the CodeMirror Ruby mode was kindly sponsored 168 | by Ubalo, who hold 169 | the license.

170 | 171 | 172 | 173 | -------------------------------------------------------------------------------- /demo/complete.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | // Minimal event-handling wrapper. 3 | function stopEvent() { 4 | if (this.preventDefault) {this.preventDefault(); this.stopPropagation();} 5 | else {this.returnValue = false; this.cancelBubble = true;} 6 | } 7 | function addStop(event) { 8 | if (!event.stop) event.stop = stopEvent; 9 | return event; 10 | } 11 | function connect(node, type, handler) { 12 | function wrapHandler(event) {handler(addStop(event || window.event));} 13 | if (typeof node.addEventListener == "function") 14 | node.addEventListener(type, wrapHandler, false); 15 | else 16 | node.attachEvent("on" + type, wrapHandler); 17 | } 18 | 19 | function forEach(arr, f) { 20 | for (var i = 0, e = arr.length; i < e; ++i) f(arr[i]); 21 | } 22 | 23 | var editor = CodeMirror.fromTextArea(document.getElementById("code"), { 24 | lineNumbers: true, 25 | theme: "night", 26 | onKeyEvent: function(i, e) { 27 | // Hook into ctrl-space 28 | if (e.keyCode == 32 && (e.ctrlKey || e.metaKey) && !e.altKey) { 29 | e.stop(); 30 | return startComplete(); 31 | } 32 | } 33 | }); 34 | 35 | function startComplete() { 36 | // We want a single cursor position. 37 | if (editor.somethingSelected()) return; 38 | // Find the token at the cursor 39 | var cur = editor.getCursor(false), token = editor.getTokenAt(cur), tprop = token; 40 | // If it's not a 'word-style' token, ignore the token. 41 | if (!/^[\w$_]*$/.test(token.string)) { 42 | token = tprop = {start: cur.ch, end: cur.ch, string: "", state: token.state, 43 | className: token.string == "." ? "js-property" : null}; 44 | } 45 | // If it is a property, find out what it is a property of. 46 | while (tprop.className == "js-property") { 47 | tprop = editor.getTokenAt({line: cur.line, ch: tprop.start}); 48 | if (tprop.string != ".") return; 49 | tprop = editor.getTokenAt({line: cur.line, ch: tprop.start}); 50 | if (!context) var context = []; 51 | context.push(tprop); 52 | } 53 | var completions = getCompletions(token, context); 54 | if (!completions.length) return; 55 | function insert(str) { 56 | editor.replaceRange(str, {line: cur.line, ch: token.start}, {line: cur.line, ch: token.end}); 57 | } 58 | // When there is only one completion, use it directly. 59 | if (completions.length == 1) {insert(completions[0]); return true;} 60 | 61 | // Build the select widget 62 | var complete = document.createElement("div"); 63 | complete.className = "completions"; 64 | var sel = complete.appendChild(document.createElement("select")); 65 | sel.multiple = true; 66 | for (var i = 0; i < completions.length; ++i) { 67 | var opt = sel.appendChild(document.createElement("option")); 68 | opt.appendChild(document.createTextNode(completions[i])); 69 | } 70 | sel.firstChild.selected = true; 71 | sel.size = Math.min(10, completions.length); 72 | var pos = editor.cursorCoords(); 73 | complete.style.left = pos.x + "px"; 74 | complete.style.top = pos.yBot + "px"; 75 | document.body.appendChild(complete); 76 | // Hack to hide the scrollbar. 77 | if (completions.length <= 10) 78 | complete.style.width = (sel.clientWidth - 1) + "px"; 79 | 80 | var done = false; 81 | function close() { 82 | if (done) return; 83 | done = true; 84 | complete.parentNode.removeChild(complete); 85 | } 86 | function pick() { 87 | insert(sel.options[sel.selectedIndex].value); 88 | close(); 89 | setTimeout(function(){editor.focus();}, 50); 90 | } 91 | connect(sel, "blur", close); 92 | connect(sel, "keydown", function(event) { 93 | var code = event.keyCode; 94 | // Enter and space 95 | if (code == 13 || code == 32) {event.stop(); pick();} 96 | // Escape 97 | else if (code == 27) {event.stop(); close(); editor.focus();} 98 | else if (code != 38 && code != 40) {close(); editor.focus(); setTimeout(startComplete, 50);} 99 | }); 100 | connect(sel, "dblclick", pick); 101 | 102 | sel.focus(); 103 | // Opera sometimes ignores focusing a freshly created node 104 | if (window.opera) setTimeout(function(){if (!done) sel.focus();}, 100); 105 | return true; 106 | } 107 | 108 | var stringProps = ("charAt charCodeAt indexOf lastIndexOf substring substr slice trim trimLeft trimRight " + 109 | "toUpperCase toLowerCase split concat match replace search").split(" "); 110 | var arrayProps = ("length concat join splice push pop shift unshift slice reverse sort indexOf " + 111 | "lastIndexOf every some filter forEach map reduce reduceRight ").split(" "); 112 | var funcProps = "prototype apply call bind".split(" "); 113 | var keywords = ("break case catch continue debugger default delete do else false finally for function " + 114 | "if in instanceof new null return switch throw true try typeof var void while with").split(" "); 115 | 116 | function getCompletions(token, context) { 117 | var found = [], start = token.string; 118 | function maybeAdd(str) { 119 | if (str.indexOf(start) == 0) found.push(str); 120 | } 121 | function gatherCompletions(obj) { 122 | if (typeof obj == "string") forEach(stringProps, maybeAdd); 123 | else if (obj instanceof Array) forEach(arrayProps, maybeAdd); 124 | else if (obj instanceof Function) forEach(funcProps, maybeAdd); 125 | for (var name in obj) maybeAdd(name); 126 | } 127 | 128 | if (context) { 129 | // If this is a property, see if it belongs to some object we can 130 | // find in the current environment. 131 | var obj = context.pop(), base; 132 | if (obj.className == "js-variable") 133 | base = window[obj.string]; 134 | else if (obj.className == "js-string") 135 | base = ""; 136 | else if (obj.className == "js-atom") 137 | base = 1; 138 | while (base != null && context.length) 139 | base = base[context.pop().string]; 140 | if (base != null) gatherCompletions(base); 141 | } 142 | else { 143 | // If not, just look in the window object and any local scope 144 | // (reading into JS mode internals to get at the local variables) 145 | for (var v = token.state.localVars; v; v = v.next) maybeAdd(v.name); 146 | gatherCompletions(window); 147 | forEach(keywords, maybeAdd); 148 | } 149 | return found; 150 | } 151 | })(); 152 | -------------------------------------------------------------------------------- /demo/fullscreen.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | CodeMirror 2: Full Screen Editing 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 29 | 30 | 31 |

CodeMirror 2: Full Screen Editing

32 | 33 |
114 | 150 | 151 |

Press F11 (or ESC in Safari on Mac OS X) when cursor is in the editor to toggle full screen editing.

152 | 153 |

Note: Does not currently work correctly in IE 154 | 6 and 7, where setting the height of something 155 | to 100% doesn't make it full-screen.

156 | 157 | 158 | 159 | -------------------------------------------------------------------------------- /mode/xml/xml.js: -------------------------------------------------------------------------------- 1 | CodeMirror.defineMode("xml", function(config, parserConfig) { 2 | var indentUnit = config.indentUnit; 3 | var Kludges = parserConfig.htmlMode ? { 4 | autoSelfClosers: {"br": true, "img": true, "hr": true, "link": true, "input": true, 5 | "meta": true, "col": true, "frame": true, "base": true, "area": true}, 6 | doNotIndent: {"pre": true, "!cdata": true}, 7 | allowUnquoted: true 8 | } : {autoSelfClosers: {}, doNotIndent: {"!cdata": true}, allowUnquoted: false}; 9 | var alignCDATA = parserConfig.alignCDATA; 10 | 11 | // Return variables for tokenizers 12 | var tagName, type; 13 | 14 | function inText(stream, state) { 15 | function chain(parser) { 16 | state.tokenize = parser; 17 | return parser(stream, state); 18 | } 19 | 20 | var ch = stream.next(); 21 | if (ch == "<") { 22 | if (stream.eat("!")) { 23 | if (stream.eat("[")) { 24 | if (stream.match("CDATA[")) return chain(inBlock("atom", "]]>")); 25 | else return null; 26 | } 27 | else if (stream.match("--")) return chain(inBlock("comment", "-->")); 28 | else if (stream.match("DOCTYPE", true, true)) { 29 | stream.eatWhile(/[\w\._\-]/); 30 | return chain(inBlock("meta", ">")); 31 | } 32 | else return null; 33 | } 34 | else if (stream.eat("?")) { 35 | stream.eatWhile(/[\w\._\-]/); 36 | state.tokenize = inBlock("meta", "?>"); 37 | return "meta"; 38 | } 39 | else { 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 = inTag; 46 | return "tag"; 47 | } 48 | } 49 | else if (ch == "&") { 50 | stream.eatWhile(/[^;]/); 51 | stream.eat(";"); 52 | return "atom"; 53 | } 54 | else { 55 | stream.eatWhile(/[^&<]/); 56 | return null; 57 | } 58 | } 59 | 60 | function inTag(stream, state) { 61 | var ch = stream.next(); 62 | if (ch == ">" || (ch == "/" && stream.eat(">"))) { 63 | state.tokenize = inText; 64 | type = ch == ">" ? "endTag" : "selfcloseTag"; 65 | return "tag"; 66 | } 67 | else if (ch == "=") { 68 | type = "equals"; 69 | return null; 70 | } 71 | else if (/[\'\"]/.test(ch)) { 72 | state.tokenize = inAttribute(ch); 73 | return state.tokenize(stream, state); 74 | } 75 | else { 76 | stream.eatWhile(/[^\s\u00a0=<>\"\'\/?]/); 77 | return "word"; 78 | } 79 | } 80 | 81 | function inAttribute(quote) { 82 | return function(stream, state) { 83 | while (!stream.eol()) { 84 | if (stream.next() == quote) { 85 | state.tokenize = inTag; 86 | break; 87 | } 88 | } 89 | return "string"; 90 | }; 91 | } 92 | 93 | function inBlock(style, terminator) { 94 | return function(stream, state) { 95 | while (!stream.eol()) { 96 | if (stream.match(terminator)) { 97 | state.tokenize = inText; 98 | break; 99 | } 100 | stream.next(); 101 | } 102 | return style; 103 | }; 104 | } 105 | 106 | var curState, setStyle; 107 | function pass() { 108 | for (var i = arguments.length - 1; i >= 0; i--) curState.cc.push(arguments[i]); 109 | } 110 | function cont() { 111 | pass.apply(null, arguments); 112 | return true; 113 | } 114 | 115 | function pushContext(tagName, startOfLine) { 116 | var noIndent = Kludges.doNotIndent.hasOwnProperty(tagName) || (curState.context && curState.context.noIndent); 117 | curState.context = { 118 | prev: curState.context, 119 | tagName: tagName, 120 | indent: curState.indented, 121 | startOfLine: startOfLine, 122 | noIndent: noIndent 123 | }; 124 | } 125 | function popContext() { 126 | if (curState.context) curState.context = curState.context.prev; 127 | } 128 | 129 | function element(type) { 130 | if (type == "openTag") {curState.tagName = tagName; return cont(attributes, endtag(curState.startOfLine));} 131 | else if (type == "closeTag") { 132 | var err = false; 133 | if (curState.context) { 134 | err = curState.context.tagName != tagName; 135 | } else { 136 | err = true; 137 | } 138 | if (err) setStyle = "error"; 139 | return cont(endclosetag(err)); 140 | } 141 | else if (type == "string") { 142 | if (!curState.context || curState.context.name != "!cdata") pushContext("!cdata"); 143 | if (curState.tokenize == inText) popContext(); 144 | return cont(); 145 | } 146 | else return cont(); 147 | } 148 | function endtag(startOfLine) { 149 | return function(type) { 150 | if (type == "selfcloseTag" || 151 | (type == "endTag" && Kludges.autoSelfClosers.hasOwnProperty(curState.tagName.toLowerCase()))) 152 | return cont(); 153 | if (type == "endTag") {pushContext(curState.tagName, startOfLine); return cont();} 154 | return cont(); 155 | }; 156 | } 157 | function endclosetag(err) { 158 | return function(type) { 159 | if (err) setStyle = "error"; 160 | if (type == "endTag") { popContext(); return cont(); } 161 | return pass(); 162 | } 163 | } 164 | 165 | function attributes(type) { 166 | if (type == "word") {setStyle = "attribute"; return cont(attributes);} 167 | if (type == "equals") return cont(attvalue, attributes); 168 | return pass(); 169 | } 170 | function attvalue(type) { 171 | if (type == "word" && Kludges.allowUnquoted) {setStyle = "string"; return cont();} 172 | if (type == "string") return cont(attvaluemaybe); 173 | return pass(); 174 | } 175 | function attvaluemaybe(type) { 176 | if (type == "string") return cont(attvaluemaybe); 177 | else return pass(); 178 | } 179 | 180 | return { 181 | startState: function() { 182 | return {tokenize: inText, cc: [], indented: 0, startOfLine: true, tagName: null, context: null}; 183 | }, 184 | 185 | token: function(stream, state) { 186 | if (stream.sol()) { 187 | state.startOfLine = true; 188 | state.indented = stream.indentation(); 189 | } 190 | if (stream.eatSpace()) return null; 191 | 192 | setStyle = type = tagName = null; 193 | var style = state.tokenize(stream, state); 194 | if ((style || type) && style != "comment") { 195 | curState = state; 196 | while (true) { 197 | var comb = state.cc.pop() || element; 198 | if (comb(type || style)) break; 199 | } 200 | } 201 | state.startOfLine = false; 202 | return setStyle || style; 203 | }, 204 | 205 | indent: function(state, textAfter) { 206 | var context = state.context; 207 | if (context && context.noIndent) return 0; 208 | if (alignCDATA && /")) { 92 | return "arrow"; 93 | } else if (/[=+\-\/*:\.^%<>~|]/.test(ch)) { 94 | stream.eatWhile(/[=+\-\/*:\.^%<>~|]/); 95 | return "operator"; 96 | } else { 97 | return null; 98 | } 99 | } 100 | 101 | function tokenBaseUntilBrace() { 102 | var depth = 1; 103 | return function(stream, state) { 104 | if (stream.peek() == "}") { 105 | depth--; 106 | if (depth == 0) { 107 | state.tokenize.pop(); 108 | return state.tokenize[state.tokenize.length-1](stream, state); 109 | } 110 | } else if (stream.peek() == "{") { 111 | depth++; 112 | } 113 | return tokenBase(stream, state); 114 | }; 115 | } 116 | function readQuoted(quote, style, embed, unescaped) { 117 | return function(stream, state) { 118 | var escaped = false, ch; 119 | while ((ch = stream.next()) != null) { 120 | if (ch == quote && (unescaped || !escaped)) { 121 | state.tokenize.pop(); 122 | break; 123 | } 124 | if (embed && ch == "#" && !escaped && stream.eat("{")) { 125 | state.tokenize.push(tokenBaseUntilBrace(arguments.callee)); 126 | break; 127 | } 128 | escaped = !escaped && ch == "\\"; 129 | } 130 | return style; 131 | }; 132 | } 133 | function readHereDoc(phrase) { 134 | return function(stream, state) { 135 | if (stream.match(phrase)) state.tokenize.pop(); 136 | else stream.skipToEnd(); 137 | return "string"; 138 | }; 139 | } 140 | function readBlockComment(stream, state) { 141 | if (stream.sol() && stream.match("=end") && stream.eol()) 142 | state.tokenize.pop(); 143 | stream.skipToEnd(); 144 | return "comment"; 145 | } 146 | 147 | return { 148 | startState: function() { 149 | return {tokenize: [tokenBase], 150 | indented: 0, 151 | context: {type: "top", indented: -config.indentUnit}, 152 | continuedLine: false, 153 | lastTok: null, 154 | varList: false}; 155 | }, 156 | 157 | token: function(stream, state) { 158 | if (stream.sol()) state.indented = stream.indentation(); 159 | var style = state.tokenize[state.tokenize.length-1](stream, state), kwtype; 160 | if (style == "ident") { 161 | var word = stream.current(); 162 | style = keywords.propertyIsEnumerable(stream.current()) ? "keyword" 163 | : /^[A-Z]/.test(word) ? "tag" 164 | : (state.lastTok == "def" || state.lastTok == "class" || state.varList) ? "def" 165 | : "variable"; 166 | if (indentWords.propertyIsEnumerable(word)) kwtype = "indent"; 167 | else if (dedentWords.propertyIsEnumerable(word)) kwtype = "dedent"; 168 | else if (word == "if" && stream.column() == stream.indentation()) kwtype = "indent"; 169 | } 170 | if (curPunc || (style && style != "comment")) state.lastTok = word || curPunc || style; 171 | if (curPunc == "|") state.varList = !state.varList; 172 | 173 | if (kwtype == "indent" || /[\(\[\{]/.test(curPunc)) 174 | state.context = {prev: state.context, type: curPunc || style, indented: state.indented}; 175 | else if ((kwtype == "dedent" || /[\)\]\}]/.test(curPunc)) && state.context.prev) 176 | state.context = state.context.prev; 177 | 178 | if (stream.eol()) 179 | state.continuedLine = (curPunc == "\\" || style == "operator"); 180 | return style; 181 | }, 182 | 183 | indent: function(state, textAfter) { 184 | if (state.tokenize[state.tokenize.length-1] != tokenBase) return 0; 185 | var firstChar = textAfter && textAfter.charAt(0); 186 | var ct = state.context; 187 | var closing = ct.type == matching[firstChar] || 188 | ct.type == "keyword" && /^(?:end|until|else|elsif|when)\b/.test(textAfter); 189 | return ct.indented + (closing ? 0 : config.indentUnit) + 190 | (state.continuedLine ? config.indentUnit : 0); 191 | } 192 | }; 193 | }); 194 | 195 | CodeMirror.defineMIME("text/x-ruby", "ruby"); 196 | -------------------------------------------------------------------------------- /mode/haskell/haskell.js: -------------------------------------------------------------------------------- 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"); 243 | -------------------------------------------------------------------------------- /test/test.js: -------------------------------------------------------------------------------- 1 | var tests = []; 2 | 3 | test("fromTextArea", function() { 4 | var te = document.getElementById("code"); 5 | te.value = "CONTENT"; 6 | var cm = CodeMirror.fromTextArea(te); 7 | is(!te.offsetHeight); 8 | eq(cm.getValue(), "CONTENT"); 9 | cm.setValue("foo\nbar"); 10 | eq(cm.getValue(), "foo\nbar"); 11 | cm.save(); 12 | is(/^foo\r?\nbar$/.test(te.value)); 13 | cm.setValue("xxx"); 14 | cm.toTextArea(); 15 | is(te.offsetHeight); 16 | eq(te.value, "xxx"); 17 | }); 18 | 19 | testCM("getRange", function(cm) { 20 | eq(cm.getLine(0), "1234"); 21 | eq(cm.getLine(1), "5678"); 22 | eq(cm.getLine(2), null); 23 | eq(cm.getLine(-1), null); 24 | eq(cm.getRange({line: 0, ch: 0}, {line: 0, ch: 3}), "123"); 25 | eq(cm.getRange({line: 0, ch: -1}, {line: 0, ch: 200}), "1234"); 26 | eq(cm.getRange({line: 0, ch: 2}, {line: 1, ch: 2}), "34\n56"); 27 | eq(cm.getRange({line: 1, ch: 2}, {line: 100, ch: 0}), "78"); 28 | }, {value: "1234\n5678"}); 29 | 30 | testCM("replaceRange", function(cm) { 31 | eq(cm.getValue(), ""); 32 | cm.replaceRange("foo\n", {line: 0, ch: 0}); 33 | eq(cm.getValue(), "foo\n"); 34 | cm.replaceRange("a\nb", {line: 0, ch: 1}); 35 | eq(cm.getValue(), "fa\nboo\n"); 36 | eq(cm.lineCount(), 3); 37 | cm.replaceRange("xyzzy", {line: 0, ch: 0}, {line: 1, ch: 1}); 38 | eq(cm.getValue(), "xyzzyoo\n"); 39 | cm.replaceRange("abc", {line: 0, ch: 0}, {line: 10, ch: 0}); 40 | eq(cm.getValue(), "abc"); 41 | eq(cm.lineCount(), 1); 42 | }); 43 | 44 | testCM("selection", function(cm) { 45 | cm.setSelection({line: 0, ch: 4}, {line: 2, ch: 2}); 46 | is(cm.somethingSelected()); 47 | eq(cm.getSelection(), "11\n222222\n33"); 48 | eqPos(cm.getCursor(false), {line: 2, ch: 2}); 49 | eqPos(cm.getCursor(true), {line: 0, ch: 4}); 50 | cm.setSelection({line: 1, ch: 0}); 51 | is(!cm.somethingSelected()); 52 | eq(cm.getSelection(), ""); 53 | eqPos(cm.getCursor(true), {line: 1, ch: 0}); 54 | cm.replaceSelection("abc"); 55 | eq(cm.getSelection(), "abc"); 56 | eq(cm.getValue(), "111111\nabc222222\n333333"); 57 | cm.replaceSelection("def", "end"); 58 | eq(cm.getSelection(), ""); 59 | eqPos(cm.getCursor(true), {line: 1, ch: 3}); 60 | cm.setCursor({line: 2, ch: 1}); 61 | eqPos(cm.getCursor(true), {line: 2, ch: 1}); 62 | cm.setCursor(1, 2); 63 | eqPos(cm.getCursor(true), {line: 1, ch: 2}); 64 | }, {value: "111111\n222222\n333333"}); 65 | 66 | testCM("lines", function(cm) { 67 | eq(cm.getLine(0), "111111"); 68 | eq(cm.getLine(1), "222222"); 69 | eq(cm.getLine(-1), null); 70 | cm.removeLine(1); 71 | cm.setLine(1, "abc"); 72 | eq(cm.getValue(), "111111\nabc"); 73 | }, {value: "111111\n222222\n333333"}); 74 | 75 | testCM("indent", function(cm) { 76 | cm.indentLine(1); 77 | eq(cm.getLine(1), " blah();"); 78 | cm.setOption("indentUnit", 8); 79 | cm.indentLine(1); 80 | eq(cm.getLine(1), "\tblah();"); 81 | }, {value: "if (x) {\nblah();\n}", indentUnit: 3, indentWithTabs: true}); 82 | 83 | test("defaults", function() { 84 | var olddefaults = CodeMirror.defaults, defs = CodeMirror.defaults = {}; 85 | for (var opt in olddefaults) defs[opt] = olddefaults[opt]; 86 | defs.indentUnit = 5; 87 | defs.value = "uu"; 88 | defs.enterMode = "keep"; 89 | defs.tabindex = 55; 90 | var place = document.getElementById("testground"), cm = CodeMirror(place); 91 | try { 92 | eq(cm.getOption("indentUnit"), 5); 93 | cm.setOption("indentUnit", 10); 94 | eq(defs.indentUnit, 5); 95 | eq(cm.getValue(), "uu"); 96 | eq(cm.getOption("enterMode"), "keep"); 97 | eq(cm.getInputField().tabindex, 55); 98 | } 99 | finally { 100 | CodeMirror.defaults = olddefaults; 101 | place.removeChild(cm.getWrapperElement()); 102 | } 103 | }); 104 | 105 | testCM("lineInfo", function(cm) { 106 | eq(cm.lineInfo(-1), null); 107 | var lh = cm.setMarker(1, "FOO", "bar"); 108 | var info = cm.lineInfo(1); 109 | eq(info.text, "222222"); 110 | eq(info.markerText, "FOO"); 111 | eq(info.markerClass, "bar"); 112 | eq(info.line, 1); 113 | eq(cm.lineInfo(2).markerText, null); 114 | cm.clearMarker(lh); 115 | eq(cm.lineInfo(1).markerText, null); 116 | }, {value: "111111\n222222\n333333"}); 117 | 118 | testCM("coords", function(cm) { 119 | var scroller = cm.getWrapperElement().getElementsByClassName("CodeMirror-scroll")[0]; 120 | scroller.style.height = "100px"; 121 | var content = []; 122 | for (var i = 0; i < 200; ++i) content.push("------------------------------" + i); 123 | cm.setValue(content.join("\n")); 124 | var top = cm.charCoords({line: 0, ch: 0}); 125 | var bot = cm.charCoords({line: 200, ch: 30}); 126 | is(top.x < bot.x); 127 | is(top.y < bot.y); 128 | is(top.y < top.yBot); 129 | scroller.scrollTop = 100; 130 | cm.refresh(); 131 | var top2 = cm.charCoords({line: 0, ch: 0}); 132 | is(top.y > top2.y); 133 | eq(top.x, top2.x); 134 | }); 135 | 136 | testCM("coordsChar", function(cm) { 137 | var content = []; 138 | for (var i = 0; i < 70; ++i) content.push("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"); 139 | cm.setValue(content.join("\n")); 140 | for (var x = 0; x < 35; x += 2) { 141 | for (var y = 0; y < 70; y += 5) { 142 | cm.setCursor(y, x); 143 | var pos = cm.coordsChar(cm.charCoords({line: y, ch: x})); 144 | eq(pos.line, y); 145 | eq(pos.ch, x); 146 | } 147 | } 148 | }); 149 | 150 | testCM("undo", function(cm) { 151 | cm.setLine(0, "def"); 152 | eq(cm.historySize().undo, 1); 153 | cm.undo(); 154 | eq(cm.getValue(), "abc"); 155 | eq(cm.historySize().undo, 0); 156 | eq(cm.historySize().redo, 1); 157 | cm.redo(); 158 | eq(cm.getValue(), "def"); 159 | eq(cm.historySize().undo, 1); 160 | eq(cm.historySize().redo, 0); 161 | cm.setValue("1\n\n\n2"); 162 | eq(cm.historySize().undo, 0); 163 | for (var i = 0; i < 20; ++i) { 164 | cm.replaceRange("a", {line: 0, ch: 0}); 165 | cm.replaceRange("b", {line: 3, ch: 0}); 166 | } 167 | eq(cm.historySize().undo, 40); 168 | for (var i = 0; i < 38; ++i) cm.undo(); 169 | eq(cm.historySize().undo, 2); 170 | eq(cm.historySize().redo, 38); 171 | eq(cm.getValue(), "a1\n\n\nb2"); 172 | cm.setOption("undoDepth", 10); 173 | for (var i = 0; i < 20; ++i) { 174 | cm.replaceRange("a", {line: 0, ch: 0}); 175 | cm.replaceRange("b", {line: 3, ch: 0}); 176 | } 177 | eq(cm.historySize().undo, 10); 178 | }, {value: "abc"}); 179 | 180 | testCM("undoMultiLine", function(cm) { 181 | cm.replaceRange("x", {line:0, ch: 0}); 182 | cm.replaceRange("y", {line:1, ch: 0}); 183 | cm.undo(); 184 | eq(cm.getValue(), "abc\ndef\nghi"); 185 | cm.replaceRange("y", {line:1, ch: 0}); 186 | cm.replaceRange("x", {line:0, ch: 0}); 187 | cm.undo(); 188 | eq(cm.getValue(), "abc\ndef\nghi"); 189 | cm.replaceRange("y", {line:2, ch: 0}); 190 | cm.replaceRange("x", {line:1, ch: 0}); 191 | cm.replaceRange("z", {line:2, ch: 0}); 192 | cm.undo(); 193 | eq(cm.getValue(), "abc\ndef\nghi"); 194 | }, {value: "abc\ndef\nghi"}); 195 | 196 | // Scaffolding 197 | 198 | function htmlEscape(str) { 199 | return str.replace(/[<&]/g, function(str) {return str == "&" ? "&" : "<";}); 200 | } 201 | function forEach(arr, f) { 202 | for (var i = 0, e = arr.length; i < e; ++i) f(arr[i]); 203 | } 204 | 205 | function Failure(why) {this.message = why;} 206 | 207 | function test(name, run) {tests.push({name: name, func: run});} 208 | function testCM(name, run, opts) { 209 | test(name, function() { 210 | var place = document.getElementById("testground"), cm = CodeMirror(place, opts); 211 | try {run(cm);} 212 | finally {place.removeChild(cm.getWrapperElement());} 213 | }); 214 | } 215 | 216 | function runTests() { 217 | var failures = [], run = 0; 218 | for (var i = 0; i < tests.length; ++i) { 219 | var test = tests[i]; 220 | try {test.func();} 221 | catch(e) { 222 | if (e instanceof Failure) 223 | failures.push({type: "failure", test: test.name, text: e.message}); 224 | else 225 | failures.push({type: "error", test: test.name, text: e.toString()}); 226 | } 227 | run++; 228 | } 229 | var html = [run + " tests run."]; 230 | if (failures.length) 231 | forEach(failures, function(fail) { 232 | html.push(fail.test + ': ' + htmlEscape(fail.text) + ""); 233 | }); 234 | else html.push('All passed.'); 235 | document.getElementById("output").innerHTML = html.join("\n"); 236 | } 237 | 238 | function eq(a, b, msg) { 239 | if (a != b) throw new Failure(a + " != " + b + (msg ? " (" + msg + ")" : "")); 240 | } 241 | function eqPos(a, b, msg) { 242 | eq(a.line, b.line, msg); 243 | eq(a.ch, b.ch, msg); 244 | } 245 | function is(a, msg) { 246 | if (!a) throw new Failure("assertion failed" + (msg ? " (" + msg + ")" : "")); 247 | } 248 | 249 | window.onload = runTests; 250 | -------------------------------------------------------------------------------- /mode/plsql/plsql.js: -------------------------------------------------------------------------------- 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 "word" 76 | return ret("word", "plsql-word"); 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 | }()); 218 | -------------------------------------------------------------------------------- /oldrelease.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | CodeMirror 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |

{ } CodeMirror

13 | 14 |
 15 | /* Old release history */
 16 | 
 17 | 
18 | 19 |

28-03-2011: Version 2.0:

20 |

CodeMirror 2 is a complete rewrite that's 21 | faster, smaller, simpler to use, and less dependent on browser 22 | quirks. See this 23 | and this 24 | for more information. 25 | 26 |

28-03-2011: Version 1.0:

27 | 32 | 33 |

22-02-2011: Version 2.0 beta 2:

34 |

Somewhate more mature API, lots of bugs shaken out. 35 | 36 |

17-02-2011: Version 0.94:

37 | 42 | 43 |

08-02-2011: Version 2.0 beta 1:

44 |

CodeMirror 2 is a complete rewrite of 45 | CodeMirror, no longer depending on an editable frame.

46 | 47 |

19-01-2011: Version 0.93:

48 | 57 | 58 |

17-12-2010: Version 0.92:

59 | 70 | 71 |

11-11-2010: Version 0.91:

73 | 81 | 82 |

02-10-2010: Version 0.9:

84 | 94 | 95 |

22-07-2010: Version 0.8:

97 | 117 | 118 |

27-04-2010: Version 120 | 0.67:

121 |

More consistent page-up/page-down behaviour 122 | across browsers. Fix some issues with hidden editors looping forever 123 | when line-numbers were enabled. Make PHP parser parse 124 | "\\" correctly. Have jumpToLine work on 125 | line handles, and add cursorLine function to fetch the 126 | line handle where the cursor currently is. Add new 127 | setStylesheet function to switch style-sheets in a 128 | running editor.

129 | 130 |

01-03-2010: Version 132 | 0.66:

133 |

Adds removeLine method to API. 134 | Introduces the PLSQL parser. 135 | Marks XML errors by adding (rather than replacing) a CSS class, so 136 | that they can be disabled by modifying their style. Fixes several 137 | selection bugs, and a number of small glitches.

138 | 139 |

12-11-2009: Version 141 | 0.65:

142 |

Add support for having both line-wrapping and 143 | line-numbers turned on, make paren-highlighting style customisable 144 | (markParen and unmarkParen config 145 | options), work around a selection bug that Opera 146 | reintroduced in version 10.

147 | 148 |

23-10-2009: Version 150 | 0.64:

151 |

Solves some issues introduced by the 152 | paste-handling changes from the previous release. Adds 153 | setSpellcheck, setTextWrapping, 154 | setIndentUnit, setUndoDepth, 155 | setTabMode, and setLineNumbers to 156 | customise a running editor. Introduces an SQL parser. Fixes a few small 158 | problems in the Python 159 | parser. And, as usual, add workarounds for various newly discovered 160 | browser incompatibilities.

161 | 162 |

31-08-2009: Version 164 | 0.63:

165 |

Overhaul of paste-handling (less fragile), fixes for several 166 | serious IE8 issues (cursor jumping, end-of-document bugs) and a number 167 | of small problems.

168 | 169 |

30-05-2009: Version 171 | 0.62:

172 |

Introduces Python 173 | and Lua parsers. Add 174 | setParser (on-the-fly mode changing) and 175 | clearHistory methods. Make parsing passes time-based 176 | instead of lines-based (see the passTime option).

177 | 178 | 179 | -------------------------------------------------------------------------------- /mode/clike/clike.js: -------------------------------------------------------------------------------- 1 | CodeMirror.defineMode("clike", 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 == '"' || 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 "word"; 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 | var cKeywords = "auto if break int case long char register continue return default short do sizeof " + 156 | "double static else struct entry switch extern typedef float union for unsigned " + 157 | "goto while enum void const signed volatile"; 158 | 159 | function cppHook(stream, state) { 160 | if (!state.startOfLine) return false; 161 | stream.skipToEnd(); 162 | return "meta"; 163 | } 164 | 165 | // C#-style strings where "" escapes a quote. 166 | function tokenAtString(stream, state) { 167 | var next; 168 | while ((next = stream.next()) != null) { 169 | if (next == '"' && !stream.eat('"')) { 170 | state.tokenize = null; 171 | break; 172 | } 173 | } 174 | return "string"; 175 | } 176 | 177 | CodeMirror.defineMIME("text/x-csrc", { 178 | name: "clike", 179 | keywords: words(cKeywords), 180 | blockKeywords: words("case do else for if switch while struct"), 181 | atoms: words("null"), 182 | hooks: {"#": cppHook} 183 | }); 184 | CodeMirror.defineMIME("text/x-c++src", { 185 | name: "clike", 186 | keywords: words(cKeywords + " asm dynamic_cast namespace reinterpret_cast try bool explicit new " + 187 | "static_cast typeid catch operator template typename class friend private " + 188 | "this using const_cast inline public throw virtual delete mutable protected " + 189 | "wchar_t"), 190 | blockKeywords: words("catch class do else finally for if struct switch try while"), 191 | atoms: words("true false null"), 192 | hooks: {"#": cppHook} 193 | }); 194 | CodeMirror.defineMIME("text/x-java", { 195 | name: "clike", 196 | keywords: words("abstract assert boolean break byte case catch char class const continue default " + 197 | "do double else enum extends final finally float for goto if implements import " + 198 | "instanceof int interface long native new package private protected public " + 199 | "return short static strictfp super switch synchronized this throw throws transient " + 200 | "try void volatile while"), 201 | blockKeywords: words("catch class do else finally for if switch try while"), 202 | atoms: words("true false null"), 203 | hooks: { 204 | "@": function(stream, state) { 205 | stream.eatWhile(/[\w\$_]/); 206 | return "meta"; 207 | } 208 | } 209 | }); 210 | CodeMirror.defineMIME("text/x-csharp", { 211 | name: "clike", 212 | keywords: words("abstract as base bool break byte case catch char checked class const continue decimal" + 213 | " default delegate do double else enum event explicit extern finally fixed float for" + 214 | " foreach goto if implicit in int interface internal is lock long namespace new object" + 215 | " operator out override params private protected public readonly ref return sbyte sealed short" + 216 | " sizeof stackalloc static string struct switch this throw try typeof uint ulong unchecked" + 217 | " unsafe ushort using virtual void volatile while add alias ascending descending dynamic from get" + 218 | " global group into join let orderby partial remove select set value var yield"), 219 | blockKeywords: words("catch class do else finally for foreach if struct switch try while"), 220 | atoms: words("true false null"), 221 | hooks: { 222 | "@": function(stream, state) { 223 | if (stream.eat('"')) { 224 | state.tokenize = tokenAtString; 225 | return tokenAtString(stream, state); 226 | } 227 | stream.eatWhile(/[\w\$_]/); 228 | return "meta"; 229 | } 230 | } 231 | }); 232 | CodeMirror.defineMIME("text/x-groovy", { 233 | name: "clike", 234 | keywords: words("abstract as assert boolean break byte case catch char class const continue def default " + 235 | "do double else enum extends final finally float for goto if implements import " + 236 | "in instanceof int interface long native new package property private protected public " + 237 | "return short static strictfp super switch synchronized this throw throws transient " + 238 | "try void volatile while"), 239 | atoms: words("true false null"), 240 | hooks: { 241 | "@": function(stream, state) { 242 | stream.eatWhile(/[\w\$_]/); 243 | return "meta"; 244 | } 245 | } 246 | }); 247 | }()); 248 | --------------------------------------------------------------------------------