Kiss me on GitHub
Codemirror Grammar
Build your own Codemirror syntax-highlight grammar
Ctrl-L: toggle comments, Ctrl-Space: keyword autocompletion popup
Codemirror v.
0
, CodemirrorGrammar v.
0
CodeMirror Editor
available token styles
Sample Code to be highlighted:
// this is part of the CodeMirrorGrammar code itself function get_mode( grammar, DEFAULT, CodeMirror ) { // Codemirror-compatible Mode CodeMirror = CodeMirror || $CodeMirror$; /* pass CodeMirror reference if not already available */ function CMode( conf, parserConf ) { return { startState: function( ) { return new State( ); } ,copyState: function( state ) { return new State( 0, state ); } ,token: function( stream, state ) { var pstream = Stream( stream.string, stream.start, stream.pos ), token = CMode.$parser.token( pstream, state ).type; stream.pos = pstream.pos; return token; } ,indent: function( state, textAfter, fullLine ) { return CMode.$parser.indent( state, textAfter, fullLine, conf, parserConf, CodeMirror ); } // support comments toggle functionality ,lineComment: CMode.$parser.LC ,blockCommentStart: CMode.$parser.BCS ,blockCommentEnd: CMode.$parser.BCE ,blockCommentContinue: CMode.$parser.BCC ,blockCommentLead: CMode.$parser.BCL // support extra functionality defined in grammar // eg. code folding, electriChars etc.. ,electricInput: CMode.$parser.$grammar.$extra.electricInput || false ,electricChars: CMode.$parser.$grammar.$extra.electricChars || false ,fold: CMode.foldType }; } CMode.$id = uuid("codemirror_grammar_mode"); CMode.$parser = new CodeMirrorGrammar.Parser( parse_grammar( grammar ), DEFAULT ); // custom, user-defined, syntax lint-like validation/annotations generated from grammar CMode.supportGrammarAnnotations = false; CMode.validator = function validator( code, options ) { return CMode.supportGrammarAnnotations && CMode.$parser && code && code.length ? CMode.$parser.validate( code, validator.options||options||{}, CodeMirror ) : []; }; CMode.linter = CMode.validator; // alias // custom, user-defined, code folding generated from grammar CMode.supportCodeFolding = true; CMode.foldType = "fold_"+CMode.$id; CMode.folder = function folder( cm, start ) { var fold; if ( CMode.supportCodeFolding && CMode.$parser && (fold = CMode.$parser.fold( cm, start, CodeMirror )) ) { return { from: CodeMirror.Pos( fold[0], fold[1] ), to: CodeMirror.Pos( fold[2], fold[3] ) }; } }; // custom, user-defined, autocompletions generated from grammar CMode.supportAutoCompletion = true; CMode.autocompleter = function autocompleter( cm, options ) { if ( CMode.supportAutoCompletion && CMode.$parser ) { options = autocompleter.options || options || {}; if ( !options[HAS]('renderer') ) options.renderer = autocompleter.renderer || autocomplete_renderer; return CMode.$parser.autocomplete( cm, options, CodeMirror ); } }; CMode.autocompleter.renderer = autocomplete_renderer; CMode.autocomplete = CMode.autocompleter; // deprecated, alias for compatibility CMode.dispose = function( ) { if ( CMode.$parser ) CMode.$parser.dispose( ); CMode.$parser = CMode.validator = CMode.linter = CMode.autocompleter = CMode.autocomplete = CMode.folder = null; }; return CMode; }
Grammar (JSON format):
Enable Grammar Annotations
// a partial javascript grammar in simple JSON format { // prefix ID for regular expressions used in the grammar "RegExpID" : "RE::", // Style model "Style" : { "comment" : "comment" ,"atom" : "atom" ,"keyword" : "keyword" ,"this" : "keyword" ,"builtin" : "builtin" ,"operator" : "operator" ,"identifier" : "variable" ,"property" : "attribute" ,"number" : "number" ,"string" : "string" ,"regex" : "string-2" }, // Lexical model "Lex" : { "comment" : {"type":"comment","tokens":[ // line comment // start, end delims (null matches end-of-line) [ "//", null ], // block comments // start, end delims [ "/*", "*/" ] ]} ,"identifier" : "RE::/[_A-Za-z$][_A-Za-z0-9$]*/" ,"this" : "RE::/this\\b/" ,"property" : "RE::/[_A-Za-z$][_A-Za-z0-9$]*/" ,"number" : [ // floats "RE::/\\d*\\.\\d+(e[\\+\\-]?\\d+)?/", "RE::/\\d+\\.\\d*/", "RE::/\\.\\d+/", // integers // hex "RE::/0x[0-9a-fA-F]+L?/", // binary "RE::/0b[01]+L?/", // octal "RE::/0o[0-7]+L?/", // decimal "RE::/[1-9]\\d*(e[\\+\\-]?\\d+)?L?/", // just zero "RE::/0(?![\\dx])/" ] ,"string" : {"type":"escaped-block","escape":"\\","tokens": // start, end of string (can be the matched regex group ie. 1 ) [ "RE::/(['\"])/", 1 ] } ,"regex" : {"type":"escaped-block","escape":"\\","tokens": // javascript literal regular expressions can be parsed similar to strings [ "/", "RE::#/[gimy]{0,4}#" ] } ,"operator" : {"tokens":[ "+", "-", "++", "--", "%", ">>", "<<", ">>>", "*", "/", "^", "|", "&", "!", "~", ">", "<", "<=", ">=", "!=", "!==", "=", "==", "===", "+=", "-=", "%=", ">>=", ">>>=", "<<=", "*=", "/=", "|=", "&=" ]} ,"delimiter" : {"tokens":[ "(", ")", "[", "]", "{", "}", ",", "=", ";", "?", ":", "+=", "-=", "*=", "/=", "%=", "&=", "|=", "^=", "++", "--", ">>=", "<<=" ]} ,"atom" : {"autocomplete":true,"tokens":[ "true", "false", "null", "undefined", "NaN", "Infinity" ]} ,"keyword" : {"autocomplete":true,"tokens":[ "if", "while", "with", "else", "do", "try", "finally", "return", "break", "continue", "new", "delete", "throw", "var", "const", "let", "function", "catch", "void", "for", "switch", "case", "default", "class", "import", "yield", "in", "typeof", "instanceof" ]} ,"builtin" : {"autocomplete":true,"tokens":[ "Object", "Function", "Array", "String", "Date", "Number", "RegExp", "Math", "Exception", "setTimeout", "setInterval", "parseInt", "parseFloat", "isFinite", "isNan", "alert", "prompt", "console", "window", "global", "this" ]} }, // Syntax model (optional) "Syntax" : { "dot_property" : {"sequence":[".", "property"]} ,"js" : "comment | number | string | regex | keyword | operator | atom | (('}' | ')' | this | builtin | identifier | dot_property) dot_property*)" }, // what to parse and in what order "Parser" : [ ["js"] ] }