Demonstration of CodeMirror's CSS
10 | highlighter.
11 |
12 |
13 |
48 |
49 |
50 |
58 |
59 |
60 |
61 |
--------------------------------------------------------------------------------
/contrib/xquery/css/xqcolors-dark.css:
--------------------------------------------------------------------------------
1 |
2 | .editbox {
3 | margin: .4em;
4 | padding: 0;
5 | font-family: monospace;
6 | font-size: 10pt;
7 | color: white;
8 | background-color: black;
9 | line-height: 16px;
10 | }
11 |
12 | span.word {
13 | color:white;
14 | }
15 |
16 | span.xqueryKeyword {
17 | color: #ffbd40;
18 | /* font-weight: bold; */
19 | }
20 |
21 | span.xqueryComment {
22 | color: #CDCDCD;
23 | font-style:italic;
24 | }
25 |
26 | span.xqueryModifier {
27 | color:#6c8cd5;
28 | font-weight: bold;
29 | }
30 |
31 | span.xqueryType {
32 | color:#6c8cd5;
33 | font-weight: bold;
34 | }
35 |
36 | span.xqueryAtom {
37 | color:#6c8cd5;
38 | font-weight: bold;
39 | }
40 |
41 | span.xqueryString {
42 | color: #9fee00;
43 | }
44 |
45 | span.xqueryRegexp {
46 | color: rgb(128,0,64);
47 | }
48 |
49 | span.xqueryNumber {
50 | color: rgb(255,0,0);
51 | }
52 |
53 | span.xqueryVariable {
54 |
55 | }
56 |
57 | span.xqueryFunction {
58 | color:#FFF700;
59 | }
60 |
61 | span.xqueryLocalvariable {
62 | color: white;
63 | }
64 |
65 | span.xqueryProperty
66 | {
67 | color: white;
68 | }
69 |
70 | span.xqueryOperator {
71 | color: orange;
72 | }
73 |
74 | span.xqueryPunctuation {
75 | color: white;
76 | }
77 |
78 | span.xquery-doc-directive {
79 | color: white;
80 | }
81 |
82 | span.xml-tagname {
83 | color: #ffbd40; ;
84 | }
85 |
86 | span.xml-attribute {
87 | color: #FFF700;
88 | }
89 |
90 | span.xml-attribute-value {
91 | color: #FFF700;
92 | font-style:italic;
93 | }
--------------------------------------------------------------------------------
/contrib/freemarker/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2010, Keybroker AB
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 Keybroker AB nor the
12 | names of its contributors may be used to endorse or promote products
13 | derived 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 Keybroker AB 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 |
--------------------------------------------------------------------------------
/contrib/lua/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2009, Franciszek Wawrzak
2 | All rights reserved.
3 |
4 | This software is provided for use in connection with the
5 | CodeMirror suite of modules and utilities, hosted and maintained
6 | at http://codemirror.net/.
7 |
8 | Redistribution and use of this software in source and binary forms,
9 | with or without modification, are permitted provided that the
10 | following conditions are met:
11 |
12 | * Redistributions of source code must retain the above
13 | copyright notice, this list of conditions and the
14 | following disclaimer.
15 |
16 | * Redistributions in binary form must reproduce the above
17 | copyright notice, this list of conditions and the
18 | following disclaimer in the documentation and/or other
19 | materials provided with the distribution.
20 |
21 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 | COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 | POSSIBILITY OF SUCH DAMAGE.
33 |
--------------------------------------------------------------------------------
/xhtmltest.xhtml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | CodeMirror: HTML/XML demonstration
5 |
6 |
19 |
20 |
21 |
22 |
This file runs CodeMirror inside an XHTML document.
23 |
24 |
25 |
37 |
38 |
39 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/contrib/python/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2009, Timothy Farrell
2 | All rights reserved.
3 |
4 | This software is provided for use in connection with the
5 | CodeMirror suite of modules and utilities, hosted and maintained
6 | at http://codemirror.net/.
7 |
8 | Redistribution and use of this software in source and binary forms,
9 | with or without modification, are permitted provided that the
10 | following conditions are met:
11 |
12 | * Redistributions of source code must retain the above
13 | copyright notice, this list of conditions and the
14 | following disclaimer.
15 |
16 | * Redistributions in binary form must reproduce the above
17 | copyright notice, this list of conditions and the
18 | following disclaimer in the documentation and/or other
19 | materials provided with the distribution.
20 |
21 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 | COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 | POSSIBILITY OF SUCH DAMAGE.
33 |
--------------------------------------------------------------------------------
/contrib/sql/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | CodeMirror: SQL demonstration
5 |
6 |
7 |
8 |
9 |
Demonstration of CodeMirror's SQL
10 | highlighter.
This is a simple demonstration of the HTML mixed-mode indentation
10 | module for CodeMirror. Script tags use the JS
11 | parser, style tags use the CSS parser.
This is a simple demonstration of the XML/HTML indentation module
23 | for CodeMirror. The javascript file contains some comments with
25 | more information.
26 |
27 |
43 |
44 |
54 |
55 |
56 |
--------------------------------------------------------------------------------
/js/unittests.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Test Harness for CodeMirror
3 | * JS-unit compatible tests here. The two available assertions are
4 | * assertEquals (strict equality) and assertEquivalent (looser equivalency).
5 | *
6 | * 'editor' is a global object for the CodeMirror editor shared between all
7 | * tests. After manipulating it in each test, try to restore it to
8 | * approximately its original state.
9 | */
10 |
11 | function testSetGet() {
12 | var code = 'It was the best of times.\nIt was the worst of times.';
13 | editor.setCode(code);
14 | assertEquals(code, editor.getCode());
15 | editor.setCode('');
16 | assertEquals('', editor.getCode());
17 | }
18 |
19 | function testSetStylesheet() {
20 | function cssStatus() {
21 | // Returns a list of tuples, for each CSS link return the filename and
22 | // whether it is enabled.
23 | links = editor.win.document.getElementsByTagName('link');
24 | css = [];
25 | for (var x = 0, link; link = links[x]; x++) {
26 | if (link.rel.indexOf("stylesheet") !== -1) {
27 | css.push([link.href.substring(link.href.lastIndexOf('/') + 1),
28 | !link.disabled])
29 | }
30 | }
31 | return css;
32 | }
33 | assertEquivalent([], cssStatus());
34 | editor.setStylesheet('css/jscolors.css');
35 | assertEquivalent([['jscolors.css', true]], cssStatus());
36 | editor.setStylesheet(['css/csscolors.css', 'css/xmlcolors.css']);
37 | assertEquivalent([['jscolors.css', false], ['csscolors.css', true], ['xmlcolors.css', true]], cssStatus());
38 | editor.setStylesheet([]);
39 | assertEquivalent([['jscolors.css', false], ['csscolors.css', false], ['xmlcolors.css', false]], cssStatus());
40 | }
41 |
42 | // Update this list of tests as new ones are added.
43 | var tests = ['testSetGet', 'testSetStylesheet'];
44 |
45 |
--------------------------------------------------------------------------------
/contrib/php/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2008-2009, Yahoo! Inc.
2 | All rights reserved.
3 |
4 | This software is provided for use in connection with the
5 | CodeMirror suite of modules and utilities, hosted and maintained
6 | at http://codemirror.net/.
7 |
8 | Redistribution and use of this software in source and binary forms,
9 | with or without modification, are permitted provided that the
10 | following conditions are met:
11 |
12 | * Redistributions of source code must retain the above
13 | copyright notice, this list of conditions and the
14 | following disclaimer.
15 |
16 | * Redistributions in binary form must reproduce the above
17 | copyright notice, this list of conditions and the
18 | following disclaimer in the documentation and/or other
19 | materials provided with the distribution.
20 |
21 | * Neither the name of Yahoo! Inc. nor the names of its
22 | contributors may be used to endorse or promote products
23 | derived from this software without specific prior
24 | written permission of Yahoo! Inc.
25 |
26 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
29 | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
30 | COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
31 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
32 | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
33 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
34 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
36 | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37 | POSSIBILITY OF SUCH DAMAGE.
38 |
--------------------------------------------------------------------------------
/jstest.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CodeMirror: JavaScript demonstration
6 |
7 |
8 |
9 |
10 |
This page demonstrates CodeMirror's
11 | JavaScript parser. Note that the ugly buttons at the top are not are
12 | not part of CodeMirror proper -- they demonstrate the way it can be
13 | embedded in a web-application.
Q: Can I use CodeMirror in my such-and-such project?
20 |
21 |
A: Yes. The license is short, simple, and
22 | permissive.
23 |
24 |
Q: You said you fixed this-and-this issue, but I'm
25 | still seeing it.
26 |
27 |
A: One possibility is that I screwed up, but a very real
28 | alternative is that you're looking at a cached version of the
29 | CodeMirror scripts. Because the scripts are loaded into an iframe,
30 | the ctrl-f5 you issued on the outer page doesn't always cause them
31 | to be reloaded (IE, Opera, and Firefox are the worst offenders
32 | here). Clear your cache and re-try.
33 |
34 |
Q: I can't put content containing
35 | </textarea> into CodeMirror!
36 |
37 |
A: [Web-programming 101] The first </textarea>
38 | following a <textarea> tag will close the
39 | textarea. This has nothing to do with CodeMirror. Sit down, and
40 | spend ten minutes thinking about why HTML-escaping was
41 | invented.
42 |
43 |
Q: I have this huge chunk of code that does not
44 | work, can you debug it for me?
45 |
46 |
A: Nope. If you can't be bothered isolate your problem in 20
47 | lines of code or less, I can't be bothered to think about it.
48 |
49 |
Q: How do I submit patches for CodeMirror?
50 |
51 |
A: Preferred way is to create a fork on github, add your
53 | patch, and send me a pull request. Diffs (against the latest
54 | version!) by mail are also cool.
Adapted from the official Javascript parser by Eric KEDJI
13 | <eric.kedji@gmail.com>.
14 |
15 |
16 |
53 |
54 |
55 |
75 |
76 |
77 |
78 |
--------------------------------------------------------------------------------
/js/util.js:
--------------------------------------------------------------------------------
1 | /* A few useful utility functions. */
2 |
3 | // Capture a method on an object.
4 | function method(obj, name) {
5 | return function() {obj[name].apply(obj, arguments);};
6 | }
7 |
8 | // The value used to signal the end of a sequence in iterators.
9 | var StopIteration = {toString: function() {return "StopIteration"}};
10 |
11 | // Apply a function to each element in a sequence.
12 | function forEach(iter, f) {
13 | if (iter.next) {
14 | try {while (true) f(iter.next());}
15 | catch (e) {if (e != StopIteration) throw e;}
16 | }
17 | else {
18 | for (var i = 0; i < iter.length; i++)
19 | f(iter[i]);
20 | }
21 | }
22 |
23 | // Map a function over a sequence, producing an array of results.
24 | function map(iter, f) {
25 | var accum = [];
26 | forEach(iter, function(val) {accum.push(f(val));});
27 | return accum;
28 | }
29 |
30 | // Create a predicate function that tests a string againsts a given
31 | // regular expression. No longer used but might be used by 3rd party
32 | // parsers.
33 | function matcher(regexp){
34 | return function(value){return regexp.test(value);};
35 | }
36 |
37 | // Test whether a DOM node has a certain CSS class.
38 | function hasClass(element, className) {
39 | var classes = element.className;
40 | return classes && new RegExp("(^| )" + className + "($| )").test(classes);
41 | }
42 | function removeClass(element, className) {
43 | element.className = element.className.replace(new RegExp(" " + className + "\\b", "g"), "");
44 | return element;
45 | }
46 |
47 | // Insert a DOM node after another node.
48 | function insertAfter(newNode, oldNode) {
49 | var parent = oldNode.parentNode;
50 | parent.insertBefore(newNode, oldNode.nextSibling);
51 | return newNode;
52 | }
53 |
54 | function removeElement(node) {
55 | if (node.parentNode)
56 | node.parentNode.removeChild(node);
57 | }
58 |
59 | function clearElement(node) {
60 | while (node.firstChild)
61 | node.removeChild(node.firstChild);
62 | }
63 |
64 | // Check whether a node is contained in another one.
65 | function isAncestor(node, child) {
66 | while (child = child.parentNode) {
67 | if (node == child)
68 | return true;
69 | }
70 | return false;
71 | }
72 |
73 | // The non-breaking space character.
74 | var nbsp = "\u00a0";
75 | var matching = {"{": "}", "[": "]", "(": ")",
76 | "}": "{", "]": "[", ")": "("};
77 |
78 | // Standardize a few unportable event properties.
79 | function normalizeEvent(event) {
80 | if (!event.stopPropagation) {
81 | event.stopPropagation = function() {this.cancelBubble = true;};
82 | event.preventDefault = function() {this.returnValue = false;};
83 | }
84 | if (!event.stop) {
85 | event.stop = function() {
86 | this.stopPropagation();
87 | this.preventDefault();
88 | };
89 | }
90 |
91 | if (event.type == "keypress") {
92 | event.code = (event.charCode == null) ? event.keyCode : event.charCode;
93 | event.character = String.fromCharCode(event.code);
94 | }
95 | return event;
96 | }
97 |
98 | // Portably register event handlers.
99 | function addEventHandler(node, type, handler, removeFunc) {
100 | function wrapHandler(event) {
101 | handler(normalizeEvent(event || window.event));
102 | }
103 | if (typeof node.addEventListener == "function") {
104 | node.addEventListener(type, wrapHandler, false);
105 | if (removeFunc) return function() {node.removeEventListener(type, wrapHandler, false);};
106 | }
107 | else {
108 | node.attachEvent("on" + type, wrapHandler);
109 | if (removeFunc) return function() {node.detachEvent("on" + type, wrapHandler);};
110 | }
111 | }
112 |
113 | function nodeText(node) {
114 | return node.textContent || node.innerText || node.nodeValue || "";
115 | }
116 |
117 | function nodeTop(node) {
118 | var top = 0;
119 | while (node.offsetParent) {
120 | top += node.offsetTop;
121 | node = node.offsetParent;
122 | }
123 | return top;
124 | }
125 |
126 | function isBR(node) {
127 | var nn = node.nodeName;
128 | return nn == "BR" || nn == "br";
129 | }
130 | function isSpan(node) {
131 | var nn = node.nodeName;
132 | return nn == "SPAN" || nn == "span";
133 | }
134 |
--------------------------------------------------------------------------------
/contrib/python/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | CodeMirror: Python demonstration
5 |
18 |
19 |
20 |
21 | This is a simple demonstration of the Python syntax highlighting module
22 | for CodeMirror.
23 |
24 |
25 | Features of this parser include:
26 |
27 |
28 |
Token-based syntax highlighting - currently very little lexical analysis happens. Few lexical errors will be detected.
29 |
Use the normal indentation mode to enforce regular indentation, otherwise the "shift" indentation mode will give you more flexibility.
30 |
Parser Options:
31 |
32 |
pythonVersion (Integer) - 2 or 3 to indicate which version of Python to parse. Default = 2
33 |
strictErrors (Bool) - true to highlight errors that may not be Python errors but cause confusion for this parser. Default = true
34 |
35 |
36 |
37 |
Written by Timothy Farrell (license). Special
38 | thanks to Adam Brand and Marijn Haverbeke for their help in debugging
39 | and providing for this parser.
115 |
116 |
123 |
124 |
125 |
126 |
--------------------------------------------------------------------------------
/contrib/php/js/parsephphtmlmixed.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2008-2009 Yahoo! Inc. All rights reserved.
3 | The copyrights embodied in the content of this file are licensed by
4 | Yahoo! Inc. under the BSD (revised) open source license
5 |
6 | @author Dan Vlad Dascalescu
7 |
8 | Based on parsehtmlmixed.js by Marijn Haverbeke.
9 | */
10 |
11 | var PHPHTMLMixedParser = Editor.Parser = (function() {
12 | var processingInstructions = ["");
36 | break;
37 | }
38 | }
39 | else if (token.style == "xml-attribute" && token.content == "\"php\"" && inTag == "script" && lastAtt == "language")
40 | inTag = "script/php";
41 | // "xml-processing" tokens are ignored, because they should be handled by a specific local parser
42 | else if (token.content == ">") {
43 | if (inTag == "script/php")
44 | iter.next = local(PHPParser, "");
45 | else if (inTag == "script")
46 | iter.next = local(JSParser, "
2 |
3 |
4 | CodeMirror Regex Highlighting
5 |
6 |
90 |
91 |
92 |
93 |
94 |
CodeMirror Regex Code Editor Demonstration
95 |
The Regex parser for CodeMirror allows syntax coloring on regular expressions with some beginning customizability by
96 | Regex flavor/language. For integrating styling of regular expression literals into JavaScript syntax highlighting, see this
97 | JavaScript+Regex Demo.
98 |
Styling ability is fine-grained, so any token should be distinctly stylable if so desired. Parenthetical groups can
99 | be styled with the same styles for inner content, and the script also enables styling by nesting depth and sequence,
100 | including by imposing a limit such that styles will alternate.
101 |
Information can also be passed on (especially when the parseregex-unicode.js file is included) for use in CodeMirror's
102 | activeTokens argument such as demonstrated below by tooltips which show which characters are present in a given
103 | range or Unicode class.
104 |
Note that this editor does not support free-spacing mode, so it is not recommended to use multiple lines for input, but
105 | for demonstration purposes, multiple lines are shown.
This demonstrates a parser in the regex folder which wraps the regular CodeMirror JavaScript editor and adds syntax coloring to
100 | regular expression literals in JavaScript.
101 |
105 |
106 |
While the above styles by depth or sequence no matter the grouping type, this parser also allows styling distinctly by grouping type (capturing, named, non-capturing), while also still allowing alternating of colors within a type.
107 |
111 |
One may also simply turn off the styling of content inside groups, allowing only individual tokens to be styled per the stylesheet (though the parentheses tokens themselves can still indicate depth or sequence):
112 |
116 |
117 |
118 |
119 |
--------------------------------------------------------------------------------
/js/stringstream.js:
--------------------------------------------------------------------------------
1 | /* String streams are the things fed to parsers (which can feed them
2 | * to a tokenizer if they want). They provide peek and next methods
3 | * for looking at the current character (next 'consumes' this
4 | * character, peek does not), and a get method for retrieving all the
5 | * text that was consumed since the last time get was called.
6 | *
7 | * An easy mistake to make is to let a StopIteration exception finish
8 | * the token stream while there are still characters pending in the
9 | * string stream (hitting the end of the buffer while parsing a
10 | * token). To make it easier to detect such errors, the stringstreams
11 | * throw an exception when this happens.
12 | */
13 |
14 | // Make a stringstream stream out of an iterator that returns strings.
15 | // This is applied to the result of traverseDOM (see codemirror.js),
16 | // and the resulting stream is fed to the parser.
17 | var stringStream = function(source){
18 | // String that's currently being iterated over.
19 | var current = "";
20 | // Position in that string.
21 | var pos = 0;
22 | // Accumulator for strings that have been iterated over but not
23 | // get()-ed yet.
24 | var accum = "";
25 | // Make sure there are more characters ready, or throw
26 | // StopIteration.
27 | function ensureChars() {
28 | while (pos == current.length) {
29 | accum += current;
30 | current = ""; // In case source.next() throws
31 | pos = 0;
32 | try {current = source.next();}
33 | catch (e) {
34 | if (e != StopIteration) throw e;
35 | else return false;
36 | }
37 | }
38 | return true;
39 | }
40 |
41 | return {
42 | // peek: -> character
43 | // Return the next character in the stream.
44 | peek: function() {
45 | if (!ensureChars()) return null;
46 | return current.charAt(pos);
47 | },
48 | // next: -> character
49 | // Get the next character, throw StopIteration if at end, check
50 | // for unused content.
51 | next: function() {
52 | if (!ensureChars()) {
53 | if (accum.length > 0)
54 | throw "End of stringstream reached without emptying buffer ('" + accum + "').";
55 | else
56 | throw StopIteration;
57 | }
58 | return current.charAt(pos++);
59 | },
60 | // get(): -> string
61 | // Return the characters iterated over since the last call to
62 | // .get().
63 | get: function() {
64 | var temp = accum;
65 | accum = "";
66 | if (pos > 0){
67 | temp += current.slice(0, pos);
68 | current = current.slice(pos);
69 | pos = 0;
70 | }
71 | return temp;
72 | },
73 | // Push a string back into the stream.
74 | push: function(str) {
75 | current = current.slice(0, pos) + str + current.slice(pos);
76 | },
77 | lookAhead: function(str, consume, skipSpaces, caseInsensitive) {
78 | function cased(str) {return caseInsensitive ? str.toLowerCase() : str;}
79 | str = cased(str);
80 | var found = false;
81 |
82 | var _accum = accum, _pos = pos;
83 | if (skipSpaces) this.nextWhileMatches(/[\s\u00a0]/);
84 |
85 | while (true) {
86 | var end = pos + str.length, left = current.length - pos;
87 | if (end <= current.length) {
88 | found = str == cased(current.slice(pos, end));
89 | pos = end;
90 | break;
91 | }
92 | else if (str.slice(0, left) == cased(current.slice(pos))) {
93 | accum += current; current = "";
94 | try {current = source.next();}
95 | catch (e) {if (e != StopIteration) throw e; break;}
96 | pos = 0;
97 | str = str.slice(left);
98 | }
99 | else {
100 | break;
101 | }
102 | }
103 |
104 | if (!(found && consume)) {
105 | current = accum.slice(_accum.length) + current;
106 | pos = _pos;
107 | accum = _accum;
108 | }
109 |
110 | return found;
111 | },
112 | // Wont't match past end of line.
113 | lookAheadRegex: function(regex, consume) {
114 | if (regex.source.charAt(0) != "^")
115 | throw new Error("Regexps passed to lookAheadRegex must start with ^");
116 |
117 | // Fetch the rest of the line
118 | while (current.indexOf("\n", pos) == -1) {
119 | try {current += source.next();}
120 | catch (e) {if (e != StopIteration) throw e; break;}
121 | }
122 | var matched = current.slice(pos).match(regex);
123 | if (matched && consume) pos += matched[0].length;
124 | return matched;
125 | },
126 |
127 | // Utils built on top of the above
128 | // more: -> boolean
129 | // Produce true if the stream isn't empty.
130 | more: function() {
131 | return this.peek() !== null;
132 | },
133 | applies: function(test) {
134 | var next = this.peek();
135 | return (next !== null && test(next));
136 | },
137 | nextWhile: function(test) {
138 | var next;
139 | while ((next = this.peek()) !== null && test(next))
140 | this.next();
141 | },
142 | matches: function(re) {
143 | var next = this.peek();
144 | return (next !== null && re.test(next));
145 | },
146 | nextWhileMatches: function(re) {
147 | var next;
148 | while ((next = this.peek()) !== null && re.test(next))
149 | this.next();
150 | },
151 | equals: function(ch) {
152 | return ch === this.peek();
153 | },
154 | endOfLine: function() {
155 | var next = this.peek();
156 | return next == null || next == "\n";
157 | }
158 | };
159 | };
160 |
--------------------------------------------------------------------------------
/contrib/regex/css/regexcolors.css:
--------------------------------------------------------------------------------
1 | /*///////////////////////////////*/
2 | html {
3 | cursor: text;
4 | }
5 | .editbox {
6 | margin: .4em;
7 | padding: 0;
8 | font-family: monospace;
9 | font-size: 10pt;
10 | color: black;
11 | }
12 | .editbox p {
13 | margin: 0;
14 | }
15 |
16 | html, body {
17 | background: #555555 !important;
18 | }
19 |
20 | /*///////////////////////////////*/
21 | /* Inside character classes */
22 | span.regex-class-special-escape {
23 | color: Coral;
24 | }
25 | span.regex-class-begin, span.regex-class-end {
26 | color: YellowGreen;
27 | }
28 | span.regex-class-negator {
29 | color: Wheat;
30 | }
31 | span.regex-class-range-hyphen {
32 | color: Turquoise;
33 | }
34 | span.regex-class-final-hyphen {
35 | color: Violet;
36 | }
37 |
38 | /*///////////////////////////////*/
39 | /* Inside character classes (suffixable by -begin-range or -end-range if beginning or ending a range) */
40 | span.regex-unicode-class-inside {
41 | color: Tomato;
42 | }
43 | span.regex-class-initial-hyphen {
44 | color: Teal;
45 | }
46 | span.regex-class-character {
47 | color: Tan;
48 | }
49 | span.regex-class-octal {
50 | color: SteelBlue;
51 | }
52 | span.regex-class-hex {
53 | color: SpringGreen;
54 | }
55 | span.regex-class-unicode-escape {
56 | color: LightGray;
57 | }
58 | span.regex-class-ascii-control {
59 | color: SlateBlue;
60 | }
61 | span.regex-class-extra-escaped {
62 | color: SkyBlue;
63 | }
64 | span.regex-class-escaped-special {
65 | color: CornflowerBlue;
66 | }
67 |
68 | /*///////////////////////////////*/
69 | span.class-special-escape-begin-range, span.class-special-escape-end-range {
70 | color: Brown;
71 | }
72 | span.regex-unicode-class-inside-begin-range, span.regex-unicode-class-inside-end-range {
73 | color: Silver;
74 | }
75 | span.regex-class-initial-hyphen-begin-range, span.regex-class-initial-hyphen-end-range {
76 | color: SeaGreen;
77 | }
78 | span.regex-class-character-begin-range, span.regex-class-character-end-range {
79 | color: SandyBrown;
80 | }
81 | span.regex-class-octal-begin-range, span.regex-class-octal-end-range {
82 | color: Salmon;
83 | }
84 | span.regex-class-hex-begin-range, span.regex-class-hex-end-range {
85 | color: Tan;
86 | }
87 | span.regex-class-unicode-escape-begin-range, span.regex-class-unicode-escape-end-range {
88 | color: LightBlue;
89 | }
90 | span.regex-class-ascii-control-begin-range, span.regex-class-ascii-control-end-range {
91 | color: RosyBrown;
92 | }
93 | span.regex-class-extra-escaped-begin-range, span.regex-class-extra-escaped-end-range {
94 | color: Orange;
95 | }
96 | span.regex-class-escaped-special-begin-range, span.regex-class-escaped-special-end-range {
97 | color: DarkKhaki;
98 | }
99 |
100 |
101 | /*///////////////////////////////*/
102 | /* Outside character classes */
103 | span.regex-special-escape {
104 | color: Chocolate;
105 | }
106 | span.regex-escaped-special {
107 | color: Orange;
108 | }
109 | span.regex-alternator {
110 | color: BurlyWood;
111 | }
112 | span.regex-unicode-class-outside {
113 | color: Gold;
114 | }
115 | span.regex-octal {
116 | color: MediumVioletRed;
117 | }
118 | span.regex-ascii {
119 | color: MediumTurquoise;
120 | }
121 | span.regex-hex {
122 | color: MediumSpringGreen;
123 | }
124 | span.regex-unicode-escape {
125 | color:pink;
126 | }
127 | span.regex-ascii-control {
128 | color: MediumSlateBlue;
129 | }
130 | span.regex-extra-escaped {
131 | color: MediumSeaGreen;
132 | }
133 | span.regex-quantifier-escape {
134 | color: Azure;
135 | }
136 | span.regex-quantifiers {
137 | color: MediumPurple;
138 | }
139 | span.regex-repetition {
140 | color: MediumOrchid;
141 | }
142 | span.regex-literal-begin, span.regex-literal-end {
143 | color: MediumBlue;
144 | }
145 | span.regex-character {
146 | color: #FFFFAA;
147 | }
148 |
149 | /*///////////////////////////////*/
150 | /* Literals/Surrounding characters */
151 | span.regex-flags {
152 | color: LimeGreen;
153 | }
154 |
155 | /*///////////////////////////////*/
156 | /* Optional outside character class features*/
157 | span.regex-empty-class {
158 | color: Lime;
159 | }
160 | span.regex-named-backreference {
161 | color: LightSlateGray;
162 | }
163 | span.regex-free-spacing-mode {
164 | background-color: LightSeaGreen;
165 | }
166 | span.regex-mode-modifier {
167 | color: LightSalmon;
168 | }
169 | span.regex-comment-pattern {
170 | color: LightGreen;
171 | }
172 | span.regex-capturing-group, span.regex-ending-capturing-group {
173 | color: LightGray;
174 | }
175 | span.regex-named-capturing-group, span.regex-ending-named-capturing-group {
176 | color: LightCoral;
177 | }
178 | span.regex-group, span.regex-ending-group {
179 | color: LawnGreen;
180 | }
181 |
182 |
183 | span.regex-capturing-group1-1, span.regex-ending-capturing-group1-1 {
184 | background-color: red;
185 | }
186 | span.regex-capturing-group1-2, span.regex-ending-capturing-group1-2 {
187 | background-color: orange;
188 | }
189 | span.regex-capturing-group2-1, span.regex-ending-capturing-group2-1 {
190 | background-color: yellow;
191 | }
192 | span.regex-capturing-group2-2, span.regex-ending-capturing-group2-2 {
193 | background-color: green;
194 | }
195 |
196 | /*///////////////////////////////*/
197 | /* Closing parentheses without opening, etc. */
198 | span.regex-bad-character, span.regex-bad-sequence {
199 | color: red;
200 | }
201 |
202 | /* Used if "uniform" inner_group_mode is used */
203 | span.regex-group-1-1 {
204 | color: lightblue;
205 | }
206 | span.regex-group-1-2 {
207 | color: lightgreen;
208 | }
209 | span.regex-group-2-1 {
210 | color: pink;
211 | }
212 | span.regex-group-2-2 {
213 | color: yellow;
214 | }
215 |
--------------------------------------------------------------------------------
/contrib/regex/css/js-regexcolors.css:
--------------------------------------------------------------------------------
1 | /*///////////////////////////////*/
2 | html {
3 | cursor: text;
4 | }
5 | .editbox {
6 | margin: .4em;
7 | padding: 0;
8 | font-family: monospace;
9 | font-size: 10pt;
10 | color: black;
11 | }
12 | .editbox p {
13 | margin: 0;
14 | }
15 |
16 | html, body {
17 | background: #cccccc !important;
18 | }
19 |
20 | /*///////////////////////////////*/
21 | /* Inside character classes */
22 | span.regex-class-special-escape {
23 | color: Coral;
24 | }
25 | span.regex-class-begin, span.regex-class-end {
26 | color: YellowGreen;
27 | }
28 | span.regex-class-negator {
29 | color: Wheat;
30 | }
31 | span.regex-class-range-hyphen {
32 | color: Turquoise;
33 | }
34 | span.regex-class-final-hyphen {
35 | color: Violet;
36 | }
37 |
38 | /*///////////////////////////////*/
39 | /* Inside character classes (suffixable by -begin-range or -end-range if beginning or ending a range) */
40 | span.regex-unicode-class-inside {
41 | color: Tomato;
42 | }
43 | span.regex-class-initial-hyphen {
44 | color: Teal;
45 | }
46 | span.regex-class-character {
47 | color: Tan;
48 | }
49 | span.regex-class-octal {
50 | color: SteelBlue;
51 | }
52 | span.regex-class-hex {
53 | color: SpringGreen;
54 | }
55 | span.regex-class-unicode-escape {
56 | color: SlateGray;
57 | }
58 | span.regex-class-ascii-control {
59 | color: SlateBlue;
60 | }
61 | span.regex-class-extra-escaped {
62 | color: SkyBlue;
63 | }
64 | span.regex-class-escaped-special {
65 | color: CornflowerBlue;
66 | }
67 |
68 | /*///////////////////////////////*/
69 | span.class-special-escape-begin-range, span.class-special-escape-end-range {
70 | color: Brown;
71 | }
72 | span.regex-unicode-class-inside-begin-range, span.regex-unicode-class-inside-end-range {
73 | color: Silver;
74 | }
75 | span.regex-class-initial-hyphen-begin-range, span.regex-class-initial-hyphen-end-range {
76 | color: SeaGreen;
77 | }
78 | span.regex-class-character-begin-range, span.regex-class-character-end-range {
79 | color: SandyBrown;
80 | }
81 | span.regex-class-octal-begin-range, span.regex-class-octal-end-range {
82 | color: Salmon;
83 | }
84 | span.regex-class-hex-begin-range, span.regex-class-hex-end-range {
85 | color: SaddleBrown;
86 | }
87 | span.regex-class-unicode-escape-begin-range, span.regex-class-unicode-escape-end-range {
88 | color: RoyalBlue;
89 | }
90 | span.regex-class-ascii-control-begin-range, span.regex-class-ascii-control-end-range {
91 | color: RosyBrown;
92 | }
93 | span.regex-class-extra-escaped-begin-range, span.regex-class-extra-escaped-end-range {
94 | color: Orange;
95 | }
96 | span.regex-class-escaped-special-begin-range, span.regex-class-escaped-special-end-range {
97 | color: DarkKhaki;
98 | }
99 |
100 |
101 | /*///////////////////////////////*/
102 | /* Outside character classes */
103 | span.regex-special-escape {
104 | color: Chocolate;
105 | }
106 | span.regex-escaped-special {
107 | color: Orange;
108 | }
109 | span.regex-alternator {
110 | color: darkpink;
111 | }
112 | span.regex-unicode-class-outside {
113 | color: Green;
114 | }
115 | span.regex-octal {
116 | color: MediumVioletRed;
117 | }
118 | span.regex-ascii {
119 | color: MediumTurquoise;
120 | }
121 | span.regex-hex {
122 | color: MediumSpringGreen;
123 | }
124 | span.regex-unicode-escape {
125 | color:pink;
126 | }
127 | span.regex-ascii-control {
128 | color: MediumSlateBlue;
129 | }
130 | span.regex-extra-escaped {
131 | color: MediumSeaGreen;
132 | }
133 | span.regex-quantifier-escape {
134 | color: Azure;
135 | }
136 | span.regex-quantifiers {
137 | color: MediumPurple;
138 | }
139 | span.regex-repetition {
140 | color: MediumOrchid;
141 | }
142 | span.regex-literal-begin, span.regex-literal-end {
143 | color: MediumBlue;
144 | }
145 | span.regex-character {
146 | color: Navy;
147 | }
148 |
149 | /*///////////////////////////////*/
150 | /* Literals/Surrounding characters */
151 | span.regex-flags {
152 | color: Green;
153 | }
154 |
155 | /*///////////////////////////////*/
156 | /* Optional outside character class features*/
157 | span.regex-empty-class {
158 | color: Lime;
159 | }
160 | span.regex-named-backreference {
161 | color: LightSlateGray;
162 | }
163 | span.regex-free-spacing-mode {
164 | background-color: LightSeaGreen;
165 | }
166 | span.regex-mode-modifier {
167 | color: LightSalmon;
168 | }
169 | span.regex-comment-pattern {
170 | color: LightGreen;
171 | }
172 | span.regex-capturing-group, span.regex-ending-capturing-group {
173 | color: LightGray;
174 | }
175 | span.regex-named-capturing-group, span.regex-ending-named-capturing-group {
176 | color: LightCoral;
177 | }
178 | span.regex-group, span.regex-ending-group {
179 | color: LawnGreen;
180 | }
181 |
182 |
183 | span.regex-capturing-group1-1, span.regex-ending-capturing-group1-1 {
184 | background-color: red;
185 | }
186 | span.regex-capturing-group1-2, span.regex-ending-capturing-group1-2 {
187 | background-color: orange;
188 | }
189 | span.regex-capturing-group2-1, span.regex-ending-capturing-group2-1 {
190 | background-color: yellow;
191 | }
192 | span.regex-capturing-group2-2, span.regex-ending-capturing-group2-2 {
193 | background-color: green;
194 | }
195 |
196 | /*///////////////////////////////*/
197 | /* Closing parentheses without opening, etc. */
198 | span.regex-bad-character, span.regex-bad-sequence {
199 | color: red;
200 | }
201 |
202 | /* Used if "uniform" inner_group_mode is used */
203 | span.regex-group-1-1 {
204 | background-color: blue;
205 | }
206 | span.regex-group-1-2 {
207 | background-color: green;
208 | }
209 | span.regex-group-2-1 {
210 | background-color: pink;
211 | }
212 | span.regex-group-2-2 {
213 | background-color: yellow;
214 | }
215 |
--------------------------------------------------------------------------------
/js/parsesparql.js:
--------------------------------------------------------------------------------
1 | var SparqlParser = Editor.Parser = (function() {
2 | function wordRegexp(words) {
3 | return new RegExp("^(?:" + words.join("|") + ")$", "i");
4 | }
5 | var ops = wordRegexp(["str", "lang", "langmatches", "datatype", "bound", "sameterm", "isiri", "isuri",
6 | "isblank", "isliteral", "union", "a"]);
7 | var keywords = wordRegexp(["base", "prefix", "select", "distinct", "reduced", "construct", "describe",
8 | "ask", "from", "named", "where", "order", "limit", "offset", "filter", "optional",
9 | "graph", "by", "asc", "desc"]);
10 | var operatorChars = /[*+\-<>=&|]/;
11 |
12 | var tokenizeSparql = (function() {
13 | function normal(source, setState) {
14 | var ch = source.next();
15 | if (ch == "$" || ch == "?") {
16 | source.nextWhileMatches(/[\w\d]/);
17 | return "sp-var";
18 | }
19 | else if (ch == "<" && !source.matches(/[\s\u00a0=]/)) {
20 | source.nextWhileMatches(/[^\s\u00a0>]/);
21 | if (source.equals(">")) source.next();
22 | return "sp-uri";
23 | }
24 | else if (ch == "\"" || ch == "'") {
25 | setState(inLiteral(ch));
26 | return null;
27 | }
28 | else if (/[{}\(\),\.;\[\]]/.test(ch)) {
29 | return "sp-punc";
30 | }
31 | else if (ch == "#") {
32 | while (!source.endOfLine()) source.next();
33 | return "sp-comment";
34 | }
35 | else if (operatorChars.test(ch)) {
36 | source.nextWhileMatches(operatorChars);
37 | return "sp-operator";
38 | }
39 | else if (ch == ":") {
40 | source.nextWhileMatches(/[\w\d\._\-]/);
41 | return "sp-prefixed";
42 | }
43 | else {
44 | source.nextWhileMatches(/[_\w\d]/);
45 | if (source.equals(":")) {
46 | source.next();
47 | source.nextWhileMatches(/[\w\d_\-]/);
48 | return "sp-prefixed";
49 | }
50 | var word = source.get(), type;
51 | if (ops.test(word))
52 | type = "sp-operator";
53 | else if (keywords.test(word))
54 | type = "sp-keyword";
55 | else
56 | type = "sp-word";
57 | return {style: type, content: word};
58 | }
59 | }
60 |
61 | function inLiteral(quote) {
62 | return function(source, setState) {
63 | var escaped = false;
64 | while (!source.endOfLine()) {
65 | var ch = source.next();
66 | if (ch == quote && !escaped) {
67 | setState(normal);
68 | break;
69 | }
70 | escaped = !escaped && ch == "\\";
71 | }
72 | return "sp-literal";
73 | };
74 | }
75 |
76 | return function(source, startState) {
77 | return tokenizer(source, startState || normal);
78 | };
79 | })();
80 |
81 | function indentSparql(context) {
82 | return function(nextChars) {
83 | var firstChar = nextChars && nextChars.charAt(0);
84 | if (/[\]\}]/.test(firstChar))
85 | while (context && context.type == "pattern") context = context.prev;
86 |
87 | var closing = context && firstChar == matching[context.type];
88 | if (!context)
89 | return 0;
90 | else if (context.type == "pattern")
91 | return context.col;
92 | else if (context.align)
93 | return context.col - (closing ? context.width : 0);
94 | else
95 | return context.indent + (closing ? 0 : indentUnit);
96 | }
97 | }
98 |
99 | function parseSparql(source) {
100 | var tokens = tokenizeSparql(source);
101 | var context = null, indent = 0, col = 0;
102 | function pushContext(type, width) {
103 | context = {prev: context, indent: indent, col: col, type: type, width: width};
104 | }
105 | function popContext() {
106 | context = context.prev;
107 | }
108 |
109 | var iter = {
110 | next: function() {
111 | var token = tokens.next(), type = token.style, content = token.content, width = token.value.length;
112 |
113 | if (content == "\n") {
114 | token.indentation = indentSparql(context);
115 | indent = col = 0;
116 | if (context && context.align == null) context.align = false;
117 | }
118 | else if (type == "whitespace" && col == 0) {
119 | indent = width;
120 | }
121 | else if (type != "sp-comment" && context && context.align == null) {
122 | context.align = true;
123 | }
124 |
125 | if (content != "\n") col += width;
126 |
127 | if (/[\[\{\(]/.test(content)) {
128 | pushContext(content, width);
129 | }
130 | else if (/[\]\}\)]/.test(content)) {
131 | while (context && context.type == "pattern")
132 | popContext();
133 | if (context && content == matching[context.type])
134 | popContext();
135 | }
136 | else if (content == "." && context && context.type == "pattern") {
137 | popContext();
138 | }
139 | else if ((type == "sp-word" || type == "sp-prefixed" || type == "sp-uri" || type == "sp-var" || type == "sp-literal") &&
140 | context && /[\{\[]/.test(context.type)) {
141 | pushContext("pattern", width);
142 | }
143 |
144 | return token;
145 | },
146 |
147 | copy: function() {
148 | var _context = context, _indent = indent, _col = col, _tokenState = tokens.state;
149 | return function(source) {
150 | tokens = tokenizeSparql(source, _tokenState);
151 | context = _context;
152 | indent = _indent;
153 | col = _col;
154 | return iter;
155 | };
156 | }
157 | };
158 | return iter;
159 | }
160 |
161 | return {make: parseSparql, electricChars: "}]"};
162 | })();
163 |
--------------------------------------------------------------------------------
/contrib/scheme/js/tokenizescheme.js:
--------------------------------------------------------------------------------
1 | /* Tokenizer for Scheme code */
2 |
3 |
4 |
5 |
6 | /**
7 | TODO: follow the definitions in:
8 |
9 | http://docs.racket-lang.org/reference/reader.html
10 |
11 | to the letter; at the moment, we've just done something quick-and-dirty.
12 |
13 | */
14 |
15 |
16 | var tokenizeScheme = (function() {
17 | var isWhiteSpace = function(ch) {
18 | // The messy regexp is because IE's regexp matcher is of the
19 | // opinion that non-breaking spaces are no whitespace.
20 | return ch != "\n" && /^[\s\u00a0]*$/.test(ch);
21 | };
22 |
23 |
24 | // scanUntilUnescaped: string-stream char -> boolean
25 | // Advances the stream until the given character (not preceded by a
26 | // backslash) is encountered.
27 | // Returns true if we hit end of line without closing.
28 | // Returns false otherwise.
29 | var scanUntilUnescaped = function(source, end) {
30 | var escaped = false;
31 | while (true) {
32 | if (source.endOfLine()) {
33 | return true;
34 | }
35 | var next = source.next();
36 | if (next == end && !escaped)
37 | return false;
38 | escaped = !escaped && next == "\\";
39 | }
40 | return false;
41 | }
42 |
43 |
44 | // Advance the stream until endline.
45 | var scanUntilEndline = function(source, end) {
46 | while (!source.endOfLine()) {
47 | source.next();
48 | }
49 | }
50 |
51 |
52 | // Some helper regexps
53 | var isHexDigit = /[0-9A-Fa-f]/;
54 |
55 |
56 | var whitespaceChar = new RegExp("[\\s\\u00a0]");
57 |
58 | var isDelimiterChar =
59 | new RegExp("[\\s\\\(\\\)\\\[\\\]\\\{\\\}\\\"\\\,\\\'\\\`\\\;]");
60 |
61 | var isNotDelimiterChar =
62 | new RegExp("[^\\s\\\(\\\)\\\[\\\]\\\{\\\}\\\"\\\,\\\'\\\`\\\;]");
63 |
64 |
65 | var numberHeader = ("(?:(?:\\d+\\/\\d+)|"+
66 | ( "(?:(?:\\d+\\.\\d+|\\d+\\.|\\.\\d+)(?:[eE][+\\-]?\\d+)?)|")+
67 | ( "(?:\\d+(?:[eE][+\\-]?\\d+)?))"));
68 | var numberPatterns = [
69 | // complex numbers
70 | new RegExp("^((?:(?:\\#[ei])?[+\\-]?" + numberHeader +")?"
71 | + "(?:[+\\-]" + numberHeader + ")i$)"),
72 | /^((?:\#[ei])?[+-]inf.0)$/,
73 | /^((?:\#[ei])?[+-]nan.0)$/,
74 | new RegExp("^((?:\\#[ei])?[+\\-]?" + numberHeader + "$)"),
75 | new RegExp("^0[xX][0-9A-Fa-f]+$")];
76 |
77 |
78 | // looksLikeNumber: string -> boolean
79 | // Returns true if string s looks like a number.
80 | var looksLikeNumber = function(s) {
81 | for (var i = 0; i < numberPatterns.length; i++) {
82 | if (numberPatterns[i].test(s)) {
83 | return true;
84 | }
85 | }
86 | return false;
87 | };
88 |
89 |
90 |
91 | var UNCLOSED_STRING = function(source, setState) {
92 | var readNewline = function() {
93 | var content = source.get();
94 | return { type:'whitespace', style:'whitespace', content: content };
95 | };
96 |
97 | var ch = source.peek();
98 | if (ch === '\n') {
99 | source.next();
100 | return readNewline();
101 | } else {
102 | var isUnclosedString = scanUntilUnescaped(source, '"');
103 | if (isUnclosedString) {
104 | setState(UNCLOSED_STRING);
105 | } else {
106 | setState(START);
107 | }
108 | var content = source.get();
109 | return {type: "string", style: "scheme-string", content: content,
110 | isUnclosed: isUnclosedString};
111 | }
112 | };
113 |
114 |
115 |
116 | var START = function(source, setState) {
117 | // Read a word, look it up in keywords. If not found, it is a
118 | // variable, otherwise it is a keyword of the type found.
119 | var readWordOrNumber = function() {
120 | source.nextWhileMatches(isNotDelimiterChar);
121 | var word = source.get();
122 | if (looksLikeNumber(word)) {
123 | return {type: "number", style: "scheme-number", content: word};
124 | } else {
125 | return {type: "variable", style: "scheme-symbol", content: word};
126 | }
127 | };
128 |
129 |
130 | var readString = function(quote) {
131 | var isUnclosedString = scanUntilUnescaped(source, quote);
132 | if (isUnclosedString) {
133 | setState(UNCLOSED_STRING);
134 | }
135 | var word = source.get();
136 | return {type: "string", style: "scheme-string", content: word,
137 | isUnclosed: isUnclosedString};
138 | };
139 |
140 |
141 | var readPound = function() {
142 | var text;
143 | // FIXME: handle special things here
144 | if (source.equals(";")) {
145 | source.next();
146 | text = source.get();
147 | return {type: text,
148 | style:"scheme-symbol",
149 | content: text};
150 | } else {
151 | text = source.get();
152 |
153 | return {type : "symbol",
154 | style: "scheme-symbol",
155 | content: text};
156 | }
157 |
158 | };
159 |
160 | var readLineComment = function() {
161 | scanUntilEndline(source);
162 | var text = source.get();
163 | return { type: "comment", style: "scheme-comment", content: text};
164 | };
165 |
166 |
167 | var readWhitespace = function() {
168 | source.nextWhile(isWhiteSpace);
169 | var content = source.get();
170 | return { type: 'whitespace', style:'whitespace', content: content };
171 | };
172 |
173 | var readNewline = function() {
174 | var content = source.get();
175 | return { type:'whitespace', style:'whitespace', content: content };
176 | };
177 |
178 |
179 | // Fetch the next token. Dispatches on first character in the
180 | // stream, or first two characters when the first is a slash.
181 | var ch = source.next();
182 | if (ch === '\n') {
183 | return readNewline();
184 | } else if (whitespaceChar.test(ch)) {
185 | return readWhitespace();
186 | } else if (ch === "#") {
187 | return readPound();
188 | } else if (ch ===';') {
189 | return readLineComment();
190 | } else if (ch === "\"") {
191 | return readString(ch);
192 | } else if (isDelimiterChar.test(ch)) {
193 | return {type: ch, style: "scheme-punctuation"};
194 | } else {
195 | return readWordOrNumber();
196 | }
197 | }
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 | var makeTokenizer = function(source, state) {
206 | // Newlines are always a separate token.
207 |
208 | var tokenizer = {
209 | state: state,
210 |
211 | take: function(type) {
212 | if (typeof(type) == "string")
213 | type = {style: type, type: type};
214 |
215 | type.content = (type.content || "") + source.get();
216 | type.value = type.content;
217 | return type;
218 | },
219 |
220 | next: function () {
221 | if (!source.more()) throw StopIteration;
222 |
223 | var type;
224 | while (!type) {
225 | type = tokenizer.state(source, function(s) {
226 | tokenizer.state = s;
227 | });
228 | }
229 | var result = this.take(type);
230 | return result;
231 | }
232 | };
233 | return tokenizer;
234 | };
235 |
236 |
237 | // The external interface to the tokenizer.
238 | return function(source, startState) {
239 | return makeTokenizer(source, startState || START);
240 | };
241 | })();
242 |
--------------------------------------------------------------------------------
/js/tokenizejavascript.js:
--------------------------------------------------------------------------------
1 | /* Tokenizer for JavaScript code */
2 |
3 | var tokenizeJavaScript = (function() {
4 | // Advance the stream until the given character (not preceded by a
5 | // backslash) is encountered, or the end of the line is reached.
6 | function nextUntilUnescaped(source, end) {
7 | var escaped = false;
8 | while (!source.endOfLine()) {
9 | var next = source.next();
10 | if (next == end && !escaped)
11 | return false;
12 | escaped = !escaped && next == "\\";
13 | }
14 | return escaped;
15 | }
16 |
17 | // A map of JavaScript's keywords. The a/b/c keyword distinction is
18 | // very rough, but it gives the parser enough information to parse
19 | // correct code correctly (we don't care that much how we parse
20 | // incorrect code). The style information included in these objects
21 | // is used by the highlighter to pick the correct CSS style for a
22 | // token.
23 | var keywords = function(){
24 | function result(type, style){
25 | return {type: type, style: "js-" + style};
26 | }
27 | // keywords that take a parenthised expression, and then a
28 | // statement (if)
29 | var keywordA = result("keyword a", "keyword");
30 | // keywords that take just a statement (else)
31 | var keywordB = result("keyword b", "keyword");
32 | // keywords that optionally take an expression, and form a
33 | // statement (return)
34 | var keywordC = result("keyword c", "keyword");
35 | var operator = result("operator", "keyword");
36 | var atom = result("atom", "atom");
37 | return {
38 | "if": keywordA, "while": keywordA, "with": keywordA,
39 | "else": keywordB, "do": keywordB, "try": keywordB, "finally": keywordB,
40 | "return": keywordC, "break": keywordC, "continue": keywordC, "new": keywordC, "delete": keywordC, "throw": keywordC,
41 | "in": operator, "typeof": operator, "instanceof": operator,
42 | "var": result("var", "keyword"), "function": result("function", "keyword"), "catch": result("catch", "keyword"),
43 | "for": result("for", "keyword"), "switch": result("switch", "keyword"),
44 | "case": result("case", "keyword"), "default": result("default", "keyword"),
45 | "true": atom, "false": atom, "null": atom, "undefined": atom, "NaN": atom, "Infinity": atom
46 | };
47 | }();
48 |
49 | // Some helper regexps
50 | var isOperatorChar = /[+\-*&%=<>!?|]/;
51 | var isHexDigit = /[0-9A-Fa-f]/;
52 | var isWordChar = /[\w\$_]/;
53 |
54 | // Wrapper around jsToken that helps maintain parser state (whether
55 | // we are inside of a multi-line comment and whether the next token
56 | // could be a regular expression).
57 | function jsTokenState(inside, regexp) {
58 | return function(source, setState) {
59 | var newInside = inside;
60 | var type = jsToken(inside, regexp, source, function(c) {newInside = c;});
61 | var newRegexp = type.type == "operator" || type.type == "keyword c" || type.type.match(/^[\[{}\(,;:]$/);
62 | if (newRegexp != regexp || newInside != inside)
63 | setState(jsTokenState(newInside, newRegexp));
64 | return type;
65 | };
66 | }
67 |
68 | // The token reader, intended to be used by the tokenizer from
69 | // tokenize.js (through jsTokenState). Advances the source stream
70 | // over a token, and returns an object containing the type and style
71 | // of that token.
72 | function jsToken(inside, regexp, source, setInside) {
73 | function readHexNumber(){
74 | source.next(); // skip the 'x'
75 | source.nextWhileMatches(isHexDigit);
76 | return {type: "number", style: "js-atom"};
77 | }
78 |
79 | function readNumber() {
80 | source.nextWhileMatches(/[0-9]/);
81 | if (source.equals(".")){
82 | source.next();
83 | source.nextWhileMatches(/[0-9]/);
84 | }
85 | if (source.equals("e") || source.equals("E")){
86 | source.next();
87 | if (source.equals("-"))
88 | source.next();
89 | source.nextWhileMatches(/[0-9]/);
90 | }
91 | return {type: "number", style: "js-atom"};
92 | }
93 | // Read a word, look it up in keywords. If not found, it is a
94 | // variable, otherwise it is a keyword of the type found.
95 | function readWord() {
96 | source.nextWhileMatches(isWordChar);
97 | var word = source.get();
98 | var known = keywords.hasOwnProperty(word) && keywords.propertyIsEnumerable(word) && keywords[word];
99 | return known ? {type: known.type, style: known.style, content: word} :
100 | {type: "variable", style: "js-variable", content: word};
101 | }
102 | function readRegexp() {
103 | nextUntilUnescaped(source, "/");
104 | source.nextWhileMatches(/[gimy]/); // 'y' is "sticky" option in Mozilla
105 | return {type: "regexp", style: "js-string"};
106 | }
107 | // Mutli-line comments are tricky. We want to return the newlines
108 | // embedded in them as regular newline tokens, and then continue
109 | // returning a comment token for every line of the comment. So
110 | // some state has to be saved (inside) to indicate whether we are
111 | // inside a /* */ sequence.
112 | function readMultilineComment(start){
113 | var newInside = "/*";
114 | var maybeEnd = (start == "*");
115 | while (true) {
116 | if (source.endOfLine())
117 | break;
118 | var next = source.next();
119 | if (next == "/" && maybeEnd){
120 | newInside = null;
121 | break;
122 | }
123 | maybeEnd = (next == "*");
124 | }
125 | setInside(newInside);
126 | return {type: "comment", style: "js-comment"};
127 | }
128 | function readOperator() {
129 | source.nextWhileMatches(isOperatorChar);
130 | return {type: "operator", style: "js-operator"};
131 | }
132 | function readString(quote) {
133 | var endBackSlash = nextUntilUnescaped(source, quote);
134 | setInside(endBackSlash ? quote : null);
135 | return {type: "string", style: "js-string"};
136 | }
137 |
138 | // Fetch the next token. Dispatches on first character in the
139 | // stream, or first two characters when the first is a slash.
140 | if (inside == "\"" || inside == "'")
141 | return readString(inside);
142 | var ch = source.next();
143 | if (inside == "/*")
144 | return readMultilineComment(ch);
145 | else if (ch == "\"" || ch == "'")
146 | return readString(ch);
147 | // with punctuation, the type of the token is the symbol itself
148 | else if (/[\[\]{}\(\),;\:\.]/.test(ch))
149 | return {type: ch, style: "js-punctuation"};
150 | else if (ch == "0" && (source.equals("x") || source.equals("X")))
151 | return readHexNumber();
152 | else if (/[0-9]/.test(ch))
153 | return readNumber();
154 | else if (ch == "/"){
155 | if (source.equals("*"))
156 | { source.next(); return readMultilineComment(ch); }
157 | else if (source.equals("/"))
158 | { nextUntilUnescaped(source, null); return {type: "comment", style: "js-comment"};}
159 | else if (regexp)
160 | return readRegexp();
161 | else
162 | return readOperator();
163 | }
164 | else if (isOperatorChar.test(ch))
165 | return readOperator();
166 | else
167 | return readWord();
168 | }
169 |
170 | // The external interface to the tokenizer.
171 | return function(source, startState) {
172 | return tokenizer(source, startState || jsTokenState(false, true));
173 | };
174 | })();
175 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | CodeMirror
5 |
6 |
7 |
8 |
9 |
10 |
11 |
CodeMirror is a JavaScript library that can be used to create a
21 | relatively pleasant editor interface for code-like content ―
22 | computer programs, HTML markup, and similar. If a parser has been
23 | written for the language you are editing (see below for a list of
24 | supported languages), the code will be coloured, and the editor will
25 | help you with indentation.
The following browsers are able to run CodeMirror:
82 |
83 |
84 |
Firefox 1.5 or higher
85 |
Internet Explorer 6 or higher
86 |
Safari 3 or higher
87 |
Opera 9.52 or higher
88 |
Chrome
89 |
90 |
91 |
I am not actively testing against every new browser release, and
92 | vendors have a habit of introducing bugs all the time, so I am
93 | relying on the community to tell me when something breaks. See below for information on how to contact me.
CodeMirror can also be found on GitHub: http://github.com/marijnh/CodeMirror.
113 | If you plan to hack on the code and contribute patches, the best way
114 | to do it is to create a GitHub fork, and send pull requests.
115 |
116 |
Documentation
117 |
118 |
The manual is your first stop for
119 | learning how to use this library. It starts with a quick explanation
120 | of how to use the editor, and then describes all of the (many)
121 | options and methods that CodeMirror exposes.
122 |
123 |
For those who want to learn more about the code, this document about CodeMirror's architecture
125 | will be useful. The source code itself
127 | is, for the most part, also very well commented.
128 |
129 |
Support
130 |
131 |
There is a Google group (a
133 | sort of mailing list/newsgroup thing) for discussion and news
134 | related to CodeMirror. Please check the FAQ
135 | before asking a question. You can also e-mail me directly: Marijn Haverbeke.