| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -21,3 +21,7 @@ | |
| color: inherit; | ||
| font-family: monospace; | ||
| } | ||
|
|
||
| .CodeMirror-dialog button { | ||
| font-size: 70%; | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,137 @@ | ||
| | ||
| (function() { | ||
|
|
||
| CodeMirror.xmlHints = []; | ||
|
|
||
| CodeMirror.xmlHint = function(cm, simbol) { | ||
|
|
||
| if(simbol.length > 0) { | ||
| var cursor = cm.getCursor(); | ||
| cm.replaceSelection(simbol); | ||
| cursor = {line: cursor.line, ch: cursor.ch + 1}; | ||
| cm.setCursor(cursor); | ||
| } | ||
|
|
||
| // dirty hack for simple-hint to receive getHint event on space | ||
| var getTokenAt = editor.getTokenAt; | ||
|
|
||
| editor.getTokenAt = function() { return 'disabled'; } | ||
| CodeMirror.simpleHint(cm, getHint); | ||
|
|
||
| editor.getTokenAt = getTokenAt; | ||
| }; | ||
|
|
||
| var getHint = function(cm) { | ||
|
|
||
| var cursor = cm.getCursor(); | ||
|
|
||
| if (cursor.ch > 0) { | ||
|
|
||
| var text = cm.getRange({line: 0, ch: 0}, cursor); | ||
| var typed = ''; | ||
| var simbol = ''; | ||
| for(var i = text.length - 1; i >= 0; i--) { | ||
| if(text[i] == ' ' || text[i] == '<') { | ||
| simbol = text[i]; | ||
| break; | ||
| } | ||
| else { | ||
| typed = text[i] + typed; | ||
| } | ||
| } | ||
|
|
||
| text = text.substr(0, text.length - typed.length); | ||
|
|
||
| var path = getActiveElement(cm, text) + simbol; | ||
| var hints = CodeMirror.xmlHints[path]; | ||
|
|
||
| if(typeof hints === 'undefined') | ||
| hints = ['']; | ||
| else { | ||
| hints = hints.slice(0); | ||
| for (var i = hints.length - 1; i >= 0; i--) { | ||
| if(hints[i].indexOf(typed) != 0) | ||
| hints.splice(i, 1); | ||
| } | ||
| } | ||
|
|
||
| return { | ||
| list: hints, | ||
| from: { line: cursor.line, ch: cursor.ch - typed.length }, | ||
| to: cursor, | ||
| }; | ||
| }; | ||
| } | ||
|
|
||
| var getActiveElement = function(codeMirror, text) { | ||
|
|
||
| var element = ''; | ||
|
|
||
| if(text.length >= 0) { | ||
|
|
||
| var regex = new RegExp('<([^!?][^\\s/>]*).*?>', 'g'); | ||
|
|
||
| var matches = []; | ||
| var match; | ||
| while ((match = regex.exec(text)) != null) { | ||
| matches.push({ | ||
| tag: match[1], | ||
| selfclose: (match[0].substr(-1) === '/>') | ||
| }); | ||
| } | ||
|
|
||
| for (var i = matches.length - 1, skip = 0; i >= 0; i--) { | ||
|
|
||
| var item = matches[i]; | ||
|
|
||
| if (item.tag[0] == '/') | ||
| { | ||
| skip++; | ||
| } | ||
| else if (item.selfclose == false) | ||
| { | ||
| if (skip > 0) | ||
| { | ||
| skip--; | ||
| } | ||
| else | ||
| { | ||
| element = '<' + item.tag + '>' + element; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| element += getOpenTag(text); | ||
| } | ||
|
|
||
| return element; | ||
| }; | ||
|
|
||
| var getOpenTag = function(text) { | ||
|
|
||
| var open = text.lastIndexOf('<'); | ||
| var close = text.lastIndexOf('>'); | ||
|
|
||
| if (close < open) | ||
| { | ||
| text = text.substr(open); | ||
|
|
||
| if(text != '<') { | ||
|
|
||
| var space = text.indexOf(' '); | ||
| if(space < 0) | ||
| space = text.indexOf('\t'); | ||
| if(space < 0) | ||
| space = text.indexOf('\n'); | ||
|
|
||
| if (space < 0) | ||
| space = text.length; | ||
|
|
||
| return text.substr(0, space); | ||
| } | ||
| } | ||
|
|
||
| return ''; | ||
| }; | ||
|
|
||
| })(); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,90 @@ | ||
| <!doctype html> | ||
| <html> | ||
| <head> | ||
| <title>CodeMirror: Haxe mode</title> | ||
| <link rel="stylesheet" href="../../lib/codemirror.css"> | ||
| <script src="../../lib/codemirror.js"></script> | ||
| <script src="haxe.js"></script> | ||
| <link rel="stylesheet" href="../../doc/docs.css"> | ||
| <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style> | ||
| </head> | ||
| <body> | ||
| <h1>CodeMirror: Haxe mode</h1> | ||
|
|
||
| <div><textarea id="code" name="code"> | ||
| import one.two.Three; | ||
|
|
||
| @attr("test") | ||
| class Foo<T> extends Three | ||
| { | ||
| public function new() | ||
| { | ||
| noFoo = 12; | ||
| } | ||
|
|
||
| public static inline function doFoo(obj:{k:Int, l:Float}):Int | ||
| { | ||
| for(i in 0...10) | ||
| { | ||
| obj.k++; | ||
| trace(i); | ||
| var var1 = new Array(); | ||
| if(var1.length > 1) | ||
| throw "Error"; | ||
| } | ||
| // The following line should not be colored, the variable is scoped out | ||
| var1; | ||
| /* Multi line | ||
| * Comment test | ||
| */ | ||
| return obj.k; | ||
| } | ||
| private function bar():Void | ||
| { | ||
| #if flash | ||
| var t1:String = "1.21"; | ||
| #end | ||
| try { | ||
| doFoo({k:3, l:1.2}); | ||
| } | ||
| catch (e : String) { | ||
| trace(e); | ||
| } | ||
| var t2:Float = cast(3.2); | ||
| var t3:haxe.Timer = new haxe.Timer(); | ||
| var t4 = {k:Std.int(t2), l:Std.parseFloat(t1)}; | ||
| var t5 = ~/123+.*$/i; | ||
| doFoo(t4); | ||
| untyped t1 = 4; | ||
| bob = new Foo<Int> | ||
| } | ||
| public var okFoo(default, never):Float; | ||
| var noFoo(getFoo, null):Int; | ||
| function getFoo():Int { | ||
| return noFoo; | ||
| } | ||
|
|
||
| public var three:Int; | ||
| } | ||
| enum Color | ||
| { | ||
| red; | ||
| green; | ||
| blue; | ||
| grey( v : Int ); | ||
| rgb (r:Int,g:Int,b:Int); | ||
| } | ||
| </textarea></div> | ||
|
|
||
| <script> | ||
| var editor = CodeMirror.fromTextArea(document.getElementById("code"), { | ||
| lineNumbers: true, | ||
| matchBrackets: true, | ||
| indentUnit: 4, | ||
| indentWithTabs: true | ||
| }); | ||
| </script> | ||
|
|
||
| <p><strong>MIME types defined:</strong> <code>text/x-haxe</code>.</p> | ||
| </body> | ||
| </html> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,130 @@ | ||
| <!doctype html> | ||
| <meta charset=utf-8> | ||
| <title>CodeMirror: OCaml mode</title> | ||
|
|
||
| <link rel=stylesheet href=../../lib/codemirror.css> | ||
| <link rel=stylesheet href=../../doc/docs.css> | ||
|
|
||
| <style type=text/css> | ||
| .CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;} | ||
| </style> | ||
|
|
||
| <script src=../../lib/codemirror.js></script> | ||
| <script src=ocaml.js></script> | ||
|
|
||
| <h1>CodeMirror: OCaml mode</h1> | ||
|
|
||
| <textarea id=code> | ||
| (* Summing a list of integers *) | ||
| let rec sum xs = | ||
| match xs with | ||
| | [] -> 0 | ||
| | x :: xs' -> x + sum xs' | ||
|
|
||
| (* Quicksort *) | ||
| let rec qsort = function | ||
| | [] -> [] | ||
| | pivot :: rest -> | ||
| let is_less x = x < pivot in | ||
| let left, right = List.partition is_less rest in | ||
| qsort left @ [pivot] @ qsort right | ||
|
|
||
| (* Fibonacci Sequence *) | ||
| let rec fib_aux n a b = | ||
| match n with | ||
| | 0 -> a | ||
| | _ -> fib_aux (n - 1) (a + b) a | ||
| let fib n = fib_aux n 0 1 | ||
|
|
||
| (* Birthday paradox *) | ||
| let year_size = 365. | ||
|
|
||
| let rec birthday_paradox prob people = | ||
| let prob' = (year_size -. float people) /. year_size *. prob in | ||
| if prob' < 0.5 then | ||
| Printf.printf "answer = %d\n" (people+1) | ||
| else | ||
| birthday_paradox prob' (people+1) ;; | ||
|
|
||
| birthday_paradox 1.0 1 | ||
|
|
||
| (* Church numerals *) | ||
| let zero f x = x | ||
| let succ n f x = f (n f x) | ||
| let one = succ zero | ||
| let two = succ (succ zero) | ||
| let add n1 n2 f x = n1 f (n2 f x) | ||
| let to_string n = n (fun k -> "S" ^ k) "0" | ||
| let _ = to_string (add (succ two) two) | ||
|
|
||
| (* Elementary functions *) | ||
| let square x = x * x;; | ||
| let rec fact x = | ||
| if x <= 1 then 1 else x * fact (x - 1);; | ||
|
|
||
| (* Automatic memory management *) | ||
| let l = 1 :: 2 :: 3 :: [];; | ||
| [1; 2; 3];; | ||
| 5 :: l;; | ||
|
|
||
| (* Polymorphism: sorting lists *) | ||
| let rec sort = function | ||
| | [] -> [] | ||
| | x :: l -> insert x (sort l) | ||
|
|
||
| and insert elem = function | ||
| | [] -> [elem] | ||
| | x :: l -> | ||
| if elem < x then elem :: x :: l else x :: insert elem l;; | ||
|
|
||
| (* Imperative features *) | ||
| let add_polynom p1 p2 = | ||
| let n1 = Array.length p1 | ||
| and n2 = Array.length p2 in | ||
| let result = Array.create (max n1 n2) 0 in | ||
| for i = 0 to n1 - 1 do result.(i) <- p1.(i) done; | ||
| for i = 0 to n2 - 1 do result.(i) <- result.(i) + p2.(i) done; | ||
| result;; | ||
| add_polynom [| 1; 2 |] [| 1; 2; 3 |];; | ||
|
|
||
| (* We may redefine fact using a reference cell and a for loop *) | ||
| let fact n = | ||
| let result = ref 1 in | ||
| for i = 2 to n do | ||
| result := i * !result | ||
| done; | ||
| !result;; | ||
| fact 5;; | ||
|
|
||
| (* Triangle (graphics) *) | ||
| let () = | ||
| ignore( Glut.init Sys.argv ); | ||
| Glut.initDisplayMode ~double_buffer:true (); | ||
| ignore (Glut.createWindow ~title:"OpenGL Demo"); | ||
| let angle t = 10. *. t *. t in | ||
| let render () = | ||
| GlClear.clear [ `color ]; | ||
| GlMat.load_identity (); | ||
| GlMat.rotate ~angle: (angle (Sys.time ())) ~z:1. (); | ||
| GlDraw.begins `triangles; | ||
| List.iter GlDraw.vertex2 [-1., -1.; 0., 1.; 1., -1.]; | ||
| GlDraw.ends (); | ||
| Glut.swapBuffers () in | ||
| GlMat.mode `modelview; | ||
| Glut.displayFunc ~cb:render; | ||
| Glut.idleFunc ~cb:(Some Glut.postRedisplay); | ||
| Glut.mainLoop () | ||
|
|
||
| (* A Hundred Lines of Caml - http://caml.inria.fr/about/taste.en.html *) | ||
| (* OCaml page on Wikipedia - http://en.wikipedia.org/wiki/OCaml *) | ||
| </textarea> | ||
|
|
||
| <script> | ||
| var editor = CodeMirror.fromTextArea(document.getElementById('code'), { | ||
| mode: 'ocaml', | ||
| lineNumbers: true, | ||
| matchBrackets: true | ||
| }); | ||
| </script> | ||
|
|
||
| <p><strong>MIME types defined:</strong> <code>text/x-ocaml</code>.</p> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,114 @@ | ||
| CodeMirror.defineMode('ocaml', function(config) { | ||
|
|
||
| var words = { | ||
| 'true': 'atom', | ||
| 'false': 'atom', | ||
| 'let': 'keyword', | ||
| 'rec': 'keyword', | ||
| 'in': 'keyword', | ||
| 'of': 'keyword', | ||
| 'and': 'keyword', | ||
| 'succ': 'keyword', | ||
| 'if': 'keyword', | ||
| 'then': 'keyword', | ||
| 'else': 'keyword', | ||
| 'for': 'keyword', | ||
| 'to': 'keyword', | ||
| 'while': 'keyword', | ||
| 'do': 'keyword', | ||
| 'done': 'keyword', | ||
| 'fun': 'keyword', | ||
| 'function': 'keyword', | ||
| 'val': 'keyword', | ||
| 'type': 'keyword', | ||
| 'mutable': 'keyword', | ||
| 'match': 'keyword', | ||
| 'with': 'keyword', | ||
| 'try': 'keyword', | ||
| 'raise': 'keyword', | ||
| 'begin': 'keyword', | ||
| 'end': 'keyword', | ||
| 'open': 'builtin', | ||
| 'trace': 'builtin', | ||
| 'ignore': 'builtin', | ||
| 'exit': 'builtin', | ||
| 'print_string': 'builtin', | ||
| 'print_endline': 'builtin' | ||
| }; | ||
|
|
||
| function tokenBase(stream, state) { | ||
| var sol = stream.sol(); | ||
| var ch = stream.next(); | ||
|
|
||
| if (ch === '"') { | ||
| state.tokenize = tokenString; | ||
| return state.tokenize(stream, state); | ||
| } | ||
| if (ch === '(') { | ||
| if (stream.eat('*')) { | ||
| state.commentLevel++; | ||
| state.tokenize = tokenComment; | ||
| return state.tokenize(stream, state); | ||
| } | ||
| } | ||
| if (ch === '~') { | ||
| stream.eatWhile(/\w/); | ||
| return 'variable-2'; | ||
| } | ||
| if (ch === '`') { | ||
| stream.eatWhile(/\w/); | ||
| return 'quote'; | ||
| } | ||
| if (/\d/.test(ch)) { | ||
| stream.eatWhile(/[\d]/); | ||
| if (stream.eat('.')) { | ||
| stream.eatWhile(/[\d]/); | ||
| } | ||
| return 'number'; | ||
| } | ||
| if ( /[+\-*&%=<>!?|]/.test(ch)) { | ||
| return 'operator'; | ||
| } | ||
| stream.eatWhile(/\w/); | ||
| var cur = stream.current(); | ||
| return words[cur] || 'variable'; | ||
| } | ||
|
|
||
| function tokenString(stream, state) { | ||
| var next, end = false, escaped = false; | ||
| while ((next = stream.next()) != null) { | ||
| if (next === '"' && !escaped) { | ||
| end = true; | ||
| break; | ||
| } | ||
| escaped = !escaped && next === '\\'; | ||
| } | ||
| if (end && !escaped) { | ||
| state.tokenize = tokenBase; | ||
| } | ||
| return 'string'; | ||
| }; | ||
|
|
||
| function tokenComment(stream, state) { | ||
| var prev, next; | ||
| while(state.commentLevel > 0 && (next = stream.next()) != null) { | ||
| if (prev === '(' && next === '*') state.commentLevel++; | ||
| if (prev === '*' && next === ')') state.commentLevel--; | ||
| prev = next; | ||
| } | ||
| if (state.commentLevel <= 0) { | ||
| state.tokenize = tokenBase; | ||
| } | ||
| return 'comment'; | ||
| } | ||
|
|
||
| return { | ||
| startState: function() {return {tokenize: tokenBase, commentLevel: 0}}, | ||
| token: function(stream, state) { | ||
| if (stream.eatSpace()) return null; | ||
| return state.tokenize(stream, state); | ||
| } | ||
| }; | ||
| }); | ||
|
|
||
| CodeMirror.defineMIME('text/x-ocaml', 'ocaml'); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| The MIT License | ||
|
|
||
| Copyright (c) 2012 Codility Limited, 107 Cheapside, London EC2V 6DN, UK | ||
|
|
||
| Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| of this software and associated documentation files (the "Software"), to deal | ||
| in the Software without restriction, including without limitation the rights | ||
| to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
| copies of the Software, and to permit persons to whom the Software is | ||
| furnished to do so, subject to the following conditions: | ||
|
|
||
| The above copyright notice and this permission notice shall be included in | ||
| all copies or substantial portions of the Software. | ||
|
|
||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
| THE SOFTWARE. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,88 @@ | ||
| <html> | ||
| <head> | ||
| <title>CodeMirror: VB.NET mode</title> | ||
| <link rel="stylesheet" href="../../lib/codemirror.css"> | ||
| <script src="../../lib/codemirror.js"></script> | ||
| <script src="vb.js"></script> | ||
| <link rel="stylesheet" href="../../doc/docs.css"> | ||
| <link href="http://fonts.googleapis.com/css?family=Inconsolata" rel="stylesheet" type="text/css"> | ||
| <style> | ||
| .CodeMirror {border: 1px solid #aaa; height:210px;} | ||
| .CodeMirror-scroll { overflow-x: auto; height: 100%;} | ||
| .CodeMirror pre { font-family: Inconsolata; font-size: 14px} | ||
| </style> | ||
| <script type="text/javascript" src="../../lib/util/runmode.js"></script> | ||
| </head> | ||
| <body onload="init()"> | ||
| <h1>CodeMirror: VB.NET mode</h1> | ||
| <script type="text/javascript"> | ||
| function test(golden, text) { | ||
| var ok = true; | ||
| var i = 0; | ||
| function callback(token, style, lineNo, pos){ | ||
| //console.log(String(token) + " " + String(style) + " " + String(lineNo) + " " + String(pos)); | ||
| var result = [String(token), String(style)]; | ||
| if (golden[i][0] != result[0] || golden[i][1] != result[1]){ | ||
| return "Error, expected: " + String(golden[i]) + ", got: " + String(result); | ||
| ok = false; | ||
| } | ||
| i++; | ||
| } | ||
| CodeMirror.runMode(text, "text/x-vb",callback); | ||
|
|
||
| if (ok) return "Tests OK"; | ||
| } | ||
| function testTypes() { | ||
| var golden = [['Integer','keyword'],[' ','null'],['Float','keyword']] | ||
| var text = "Integer Float"; | ||
| return test(golden,text); | ||
| } | ||
| function testIf(){ | ||
| var golden = [['If','keyword'],[' ','null'],['True','keyword'],[' ','null'],['End','keyword'],[' ','null'],['If','keyword']]; | ||
| var text = 'If True End If'; | ||
| return test(golden, text); | ||
| } | ||
| function testDecl(){ | ||
| var golden = [['Dim','keyword'],[' ','null'],['x','variable'],[' ','null'],['as','keyword'],[' ','null'],['Integer','keyword']]; | ||
| var text = 'Dim x as Integer'; | ||
| return test(golden, text); | ||
| } | ||
| function testAll(){ | ||
| var result = ""; | ||
|
|
||
| result += testTypes() + "\n"; | ||
| result += testIf() + "\n"; | ||
| result += testDecl() + "\n"; | ||
| return result; | ||
|
|
||
| } | ||
| function initText(editor) { | ||
| var content = 'Class rocket\nPrivate quality as Double\nPublic Sub launch() as String\nif quality > 0.8\nlaunch = "Successful"\nElse\nlaunch = "Failed"\nEnd If\nEnd sub\nEnd class\n'; | ||
| editor.setValue(content); | ||
| for (var i =0; i< editor.lineCount(); i++) editor.indentLine(i); | ||
| } | ||
| function init() { | ||
| editor = CodeMirror.fromTextArea(document.getElementById("solution"), { | ||
| lineNumbers: true, | ||
| matchBrackets: true, | ||
| mode: "text/x-vb", | ||
| readOnly: false, | ||
| tabMode: "shift" | ||
| }); | ||
| runTest(); | ||
| } | ||
| function runTest() { | ||
| document.getElementById('testresult').innerHTML = testAll(); | ||
| initText(editor); | ||
|
|
||
| } | ||
| </script> | ||
|
|
||
|
|
||
| <div id="edit"> | ||
| <textarea style="width:95%;height:200px;padding:5px;" name="solution" id="solution" ></textarea> | ||
| </div> | ||
| <pre id="testresult"></pre> | ||
| <p>MIME type defined: <code>text/x-vb</code>.</p> | ||
|
|
||
| </body></html> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,260 @@ | ||
| CodeMirror.defineMode("vb", function(conf, parserConf) { | ||
| var ERRORCLASS = 'error'; | ||
|
|
||
| function wordRegexp(words) { | ||
| return new RegExp("^((" + words.join(")|(") + "))\\b", "i"); | ||
| } | ||
|
|
||
| var singleOperators = new RegExp("^[\\+\\-\\*/%&\\\\|\\^~<>!]"); | ||
| var singleDelimiters = new RegExp('^[\\(\\)\\[\\]\\{\\}@,:`=;\\.]'); | ||
| var doubleOperators = new RegExp("^((==)|(<>)|(<=)|(>=)|(<>)|(<<)|(>>)|(//)|(\\*\\*))"); | ||
| var doubleDelimiters = new RegExp("^((\\+=)|(\\-=)|(\\*=)|(%=)|(/=)|(&=)|(\\|=)|(\\^=))"); | ||
| var tripleDelimiters = new RegExp("^((//=)|(>>=)|(<<=)|(\\*\\*=))"); | ||
| var identifiers = new RegExp("^[_A-Za-z][_A-Za-z0-9]*"); | ||
|
|
||
| var openingKeywords = ['class','module', 'sub','enum','select','while','if','function', 'get','set','property']; | ||
| var middleKeywords = ['else','elseif','case']; | ||
| var endKeywords = ['next','loop']; | ||
|
|
||
| var wordOperators = wordRegexp(['and', 'or', 'not', 'xor', 'in']); | ||
| var commonkeywords = ['as', 'dim', 'break', 'continue','optional', 'then', 'until', | ||
| 'goto', 'byval','byref','new','handles','property', 'return', | ||
| 'const','private', 'protected', 'friend', 'public', 'shared', 'static', 'true','false']; | ||
| var commontypes = ['integer','string','double','decimal','boolean','short','char', 'float','single']; | ||
|
|
||
| var keywords = wordRegexp(commonkeywords); | ||
| var types = wordRegexp(commontypes); | ||
| var stringPrefixes = '"'; | ||
|
|
||
| var opening = wordRegexp(openingKeywords); | ||
| var middle = wordRegexp(middleKeywords); | ||
| var closing = wordRegexp(endKeywords); | ||
| var doubleClosing = wordRegexp(['end']); | ||
| var doOpening = wordRegexp(['do']); | ||
|
|
||
| var indentInfo = null; | ||
|
|
||
|
|
||
|
|
||
|
|
||
| function indent(stream, state) { | ||
| state.currentIndent++; | ||
| } | ||
|
|
||
| function dedent(stream, state) { | ||
| state.currentIndent--; | ||
| } | ||
| // tokenizers | ||
| function tokenBase(stream, state) { | ||
| if (stream.eatSpace()) { | ||
| return null; | ||
| } | ||
|
|
||
| var ch = stream.peek(); | ||
|
|
||
| // Handle Comments | ||
| if (ch === "'") { | ||
| stream.skipToEnd(); | ||
| return 'comment'; | ||
| } | ||
|
|
||
|
|
||
| // Handle Number Literals | ||
| if (stream.match(/^((&H)|(&O))?[0-9\.a-f]/i, false)) { | ||
| var floatLiteral = false; | ||
| // Floats | ||
| if (stream.match(/^\d*\.\d+F?/i)) { floatLiteral = true; } | ||
| else if (stream.match(/^\d+\.\d*F?/)) { floatLiteral = true; } | ||
| else if (stream.match(/^\.\d+F?/)) { floatLiteral = true; } | ||
|
|
||
| if (floatLiteral) { | ||
| // Float literals may be "imaginary" | ||
| stream.eat(/J/i); | ||
| return 'number'; | ||
| } | ||
| // Integers | ||
| var intLiteral = false; | ||
| // Hex | ||
| if (stream.match(/^&H[0-9a-f]+/i)) { intLiteral = true; } | ||
| // Octal | ||
| else if (stream.match(/^&O[0-7]+/i)) { intLiteral = true; } | ||
| // Decimal | ||
| else if (stream.match(/^[1-9]\d*F?/)) { | ||
| // Decimal literals may be "imaginary" | ||
| stream.eat(/J/i); | ||
| // TODO - Can you have imaginary longs? | ||
| intLiteral = true; | ||
| } | ||
| // Zero by itself with no other piece of number. | ||
| else if (stream.match(/^0(?![\dx])/i)) { intLiteral = true; } | ||
| if (intLiteral) { | ||
| // Integer literals may be "long" | ||
| stream.eat(/L/i); | ||
| return 'number'; | ||
| } | ||
| } | ||
|
|
||
| // Handle Strings | ||
| if (stream.match(stringPrefixes)) { | ||
| state.tokenize = tokenStringFactory(stream.current()); | ||
| return state.tokenize(stream, state); | ||
| } | ||
|
|
||
| // Handle operators and Delimiters | ||
| if (stream.match(tripleDelimiters) || stream.match(doubleDelimiters)) { | ||
| return null; | ||
| } | ||
| if (stream.match(doubleOperators) | ||
| || stream.match(singleOperators) | ||
| || stream.match(wordOperators)) { | ||
| return 'operator'; | ||
| } | ||
| if (stream.match(singleDelimiters)) { | ||
| return null; | ||
| } | ||
| if (stream.match(doOpening)) { | ||
| indent(stream,state); | ||
| state.doInCurrentLine = true; | ||
| return 'keyword'; | ||
| } | ||
| if (stream.match(opening)) { | ||
| if (! state.doInCurrentLine) | ||
| indent(stream,state); | ||
| else | ||
| state.doInCurrentLine = false; | ||
| return 'keyword'; | ||
| } | ||
| if (stream.match(middle)) { | ||
| return 'keyword'; | ||
| } | ||
|
|
||
| if (stream.match(doubleClosing)) { | ||
| dedent(stream,state); | ||
| dedent(stream,state); | ||
| return 'keyword'; | ||
| } | ||
| if (stream.match(closing)) { | ||
| dedent(stream,state); | ||
| return 'keyword'; | ||
| } | ||
|
|
||
| if (stream.match(types)) { | ||
| return 'keyword'; | ||
| } | ||
|
|
||
| if (stream.match(keywords)) { | ||
| return 'keyword'; | ||
| } | ||
|
|
||
| if (stream.match(identifiers)) { | ||
| return 'variable'; | ||
| } | ||
|
|
||
| // Handle non-detected items | ||
| stream.next(); | ||
| return ERRORCLASS; | ||
| } | ||
|
|
||
| function tokenStringFactory(delimiter) { | ||
| var singleline = delimiter.length == 1; | ||
| var OUTCLASS = 'string'; | ||
|
|
||
| return function tokenString(stream, state) { | ||
| while (!stream.eol()) { | ||
| stream.eatWhile(/[^'"]/); | ||
| if (stream.match(delimiter)) { | ||
| state.tokenize = tokenBase; | ||
| return OUTCLASS; | ||
| } else { | ||
| stream.eat(/['"]/); | ||
| } | ||
| } | ||
| if (singleline) { | ||
| if (parserConf.singleLineStringErrors) { | ||
| return ERRORCLASS; | ||
| } else { | ||
| state.tokenize = tokenBase; | ||
| } | ||
| } | ||
| return OUTCLASS; | ||
| }; | ||
| } | ||
|
|
||
|
|
||
| function tokenLexer(stream, state) { | ||
| var style = state.tokenize(stream, state); | ||
| var current = stream.current(); | ||
|
|
||
| // Handle '.' connected identifiers | ||
| if (current === '.') { | ||
| style = state.tokenize(stream, state); | ||
| current = stream.current(); | ||
| if (style === 'variable') { | ||
| return 'variable'; | ||
| } else { | ||
| return ERRORCLASS; | ||
| } | ||
| } | ||
|
|
||
|
|
||
| var delimiter_index = '[({'.indexOf(current); | ||
| if (delimiter_index !== -1) { | ||
| indent(stream, state ); | ||
| } | ||
| if (indentInfo === 'dedent') { | ||
| if (dedent(stream, state)) { | ||
| return ERRORCLASS; | ||
| } | ||
| } | ||
| delimiter_index = '])}'.indexOf(current); | ||
| if (delimiter_index !== -1) { | ||
| if (dedent(stream, state)) { | ||
| return ERRORCLASS; | ||
| } | ||
| } | ||
|
|
||
| return style; | ||
| } | ||
|
|
||
| var external = { | ||
| electricChars:"dDpPtTfFeE ", | ||
| startState: function(basecolumn) { | ||
| return { | ||
| tokenize: tokenBase, | ||
| lastToken: null, | ||
| currentIndent: 0, | ||
| nextLineIndent: 0, | ||
| doInCurrentLine: false | ||
|
|
||
|
|
||
| }; | ||
| }, | ||
|
|
||
| token: function(stream, state) { | ||
| if (stream.sol()) { | ||
| state.currentIndent += state.nextLineIndent; | ||
| state.nextLineIndent = 0; | ||
| state.doInCurrentLine = 0; | ||
| } | ||
| var style = tokenLexer(stream, state); | ||
|
|
||
| state.lastToken = {style:style, content: stream.current()}; | ||
|
|
||
|
|
||
|
|
||
| return style; | ||
| }, | ||
|
|
||
| indent: function(state, textAfter) { | ||
| var trueText = textAfter.replace(/^\s+|\s+$/g, '') ; | ||
| if (trueText.match(closing) || trueText.match(doubleClosing) || trueText.match(middle)) return conf.indentUnit*(state.currentIndent-1); | ||
| if(state.currentIndent < 0) return 0; | ||
| return state.currentIndent * conf.indentUnit; | ||
| } | ||
|
|
||
| }; | ||
| return external; | ||
| }); | ||
|
|
||
| CodeMirror.defineMIME("text/x-vb", "vb"); | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,42 @@ | ||
| var tests = [], runOnly = null; | ||
|
|
||
| function Failure(why) {this.message = why;} | ||
|
|
||
| function test(name, run) {tests.push({name: name, func: run}); return name;} | ||
| function testCM(name, run, opts) { | ||
| return test(name, function() { | ||
| var place = document.getElementById("testground"), cm = CodeMirror(place, opts); | ||
| try {run(cm);} | ||
| finally {place.removeChild(cm.getWrapperElement());} | ||
| }); | ||
| } | ||
|
|
||
| function runTests(callback) { | ||
| function step(i) { | ||
| if (i == tests.length) return callback("done"); | ||
| var test = tests[i]; | ||
| if (runOnly != null && runOnly != test.name) return step(i + 1); | ||
| try {test.func(); callback("ok", test.name);} | ||
| catch(e) { | ||
| if (e instanceof Failure) | ||
| callback("fail", test.name, e.message); | ||
| else | ||
| callback("error", test.name, e.toString()); | ||
| } | ||
| setTimeout(function(){step(i + 1);}, 20); | ||
| } | ||
| step(0); | ||
| } | ||
|
|
||
| function eq(a, b, msg) { | ||
| if (a != b) throw new Failure(a + " != " + b + (msg ? " (" + msg + ")" : "")); | ||
| } | ||
| function eqPos(a, b, msg) { | ||
| if (a == b) return; | ||
| if (a == null || b == null) throw new Failure("comparing point to null"); | ||
| eq(a.line, b.line, msg); | ||
| eq(a.ch, b.ch, msg); | ||
| } | ||
| function is(a, msg) { | ||
| if (!a) throw new Failure("assertion failed" + (msg ? " (" + msg + ")" : "")); | ||
| } |