diff options
-rw-r--r-- | AUTHORS | 1 | ||||
-rw-r--r-- | pygments/lexers/_mapping.py | 1 | ||||
-rw-r--r-- | pygments/lexers/web.py | 133 | ||||
-rw-r--r-- | tests/examplefiles/livescript-demo.ls | 41 |
4 files changed, 166 insertions, 10 deletions
@@ -112,5 +112,6 @@ Other contributors, listed alphabetically, are: * Davy Wybiral -- Clojure lexer * Diego Zamboni -- CFengine3 lexer * Alex Zimin -- Nemerle lexer +* Paul Miller -- LiveScript lexer Many thanks for all contributions! diff --git a/pygments/lexers/_mapping.py b/pygments/lexers/_mapping.py index 95fd114f..0647f32e 100644 --- a/pygments/lexers/_mapping.py +++ b/pygments/lexers/_mapping.py @@ -137,6 +137,7 @@ LEXERS = { 'KotlinLexer': ('pygments.lexers.jvm', 'Kotlin', ('kotlin',), ('*.kt',), ('text/x-kotlin',)), 'LighttpdConfLexer': ('pygments.lexers.text', 'Lighttpd configuration file', ('lighty', 'lighttpd'), (), ('text/x-lighttpd-conf',)), 'LiterateHaskellLexer': ('pygments.lexers.functional', 'Literate Haskell', ('lhs', 'literate-haskell'), ('*.lhs',), ('text/x-literate-haskell',)), + 'LiveScriptLexer': ('pygments.lexers.web', 'LiveScript', ('livescript',), ('*.ls',), ('text/livescript',)), 'LlvmLexer': ('pygments.lexers.asm', 'LLVM', ('llvm',), ('*.ll',), ('text/x-llvm',)), 'LogtalkLexer': ('pygments.lexers.other', 'Logtalk', ('logtalk',), ('*.lgt',), ('text/x-logtalk',)), 'LuaLexer': ('pygments.lexers.agile', 'Lua', ('lua',), ('*.lua', '*.wlua'), ('text/x-lua', 'application/x-lua')), diff --git a/pygments/lexers/web.py b/pygments/lexers/web.py index 6b788e82..a26726d1 100644 --- a/pygments/lexers/web.py +++ b/pygments/lexers/web.py @@ -25,8 +25,9 @@ from pygments.lexers.compiled import ScalaLexer __all__ = ['HtmlLexer', 'XmlLexer', 'JavascriptLexer', 'JSONLexer', 'CssLexer', 'PhpLexer', 'ActionScriptLexer', 'XsltLexer', 'ActionScript3Lexer', 'MxmlLexer', 'HaxeLexer', 'HamlLexer', 'SassLexer', 'ScssLexer', - 'ObjectiveJLexer', 'CoffeeScriptLexer', 'DuelLexer', 'ScamlLexer', - 'JadeLexer', 'XQueryLexer', 'DtdLexer', 'DartLexer'] + 'ObjectiveJLexer', 'CoffeeScriptLexer', 'LiveScriptLexer', + 'DuelLexer', 'ScamlLexer', 'JadeLexer', 'XQueryLexer', + 'DtdLexer', 'DartLexer'] class JavascriptLexer(RegexLexer): @@ -1817,28 +1818,32 @@ class CoffeeScriptLexer(RegexLexer): # this next expr leads to infinite loops root -> slashstartsregex #(r'^(?=\s|/|<!--)', Text, 'slashstartsregex'), include('commentsandwhitespace'), - (r'\+\+|--|~|&&|\band\b|\bor\b|\bis\b|\bisnt\b|\bnot\b|\?|:|=|' - r'\|\||\\(?=\n)|(<<|>>>?|==?|!=?|[-<>+*`%&\|\^/])=?', + (r'\+\+|~|&&|\band\b|\bor\b|\bis\b|\bisnt\b|\bnot\b|\?|:|' + r'\|\||\\(?=\n)|(<<|>>>?|==?|!=?|' + r'=(?!>)|-(?!>)|[<>+*`%&\|\^/])=?', Operator, 'slashstartsregex'), - (r'\([^()]*\)\s*->', Name.Function), + (r'(?:\([^()]+\))?\s*[=-]>', Name.Function), (r'[{(\[;,]', Punctuation, 'slashstartsregex'), (r'[})\].]', Punctuation), - (r'(for|in|of|while|break|return|continue|switch|when|then|if|else|' + (r'(?<![\.\$])(for|own|in|of|while|until|' + r'loop|break|return|continue|' + r'switch|when|then|if|unless|else|' r'throw|try|catch|finally|new|delete|typeof|instanceof|super|' r'extends|this|class|by)\b', Keyword, 'slashstartsregex'), - (r'(true|false|yes|no|on|off|null|NaN|Infinity|undefined)\b', + (r'(?<![\.\$])(true|false|yes|no|on|off|null|' + r'NaN|Infinity|undefined)\b', Keyword.Constant), (r'(Array|Boolean|Date|Error|Function|Math|netscape|' r'Number|Object|Packages|RegExp|String|sun|decodeURI|' r'decodeURIComponent|encodeURI|encodeURIComponent|' r'eval|isFinite|isNaN|parseFloat|parseInt|document|window)\b', Name.Builtin), - (r'[$a-zA-Z_][a-zA-Z0-9_\.:]*\s*[:=]\s', Name.Variable, + (r'[$a-zA-Z_][a-zA-Z0-9_\.:\$]*\s*[:=]\s', Name.Variable, 'slashstartsregex'), - (r'@[$a-zA-Z_][a-zA-Z0-9_\.:]*\s*[:=]\s', Name.Variable.Instance, + (r'@[$a-zA-Z_][a-zA-Z0-9_\.:\$]*\s*[:=]\s', Name.Variable.Instance, 'slashstartsregex'), (r'@', Name.Other, 'slashstartsregex'), - (r'@?[$a-zA-Z_][a-zA-Z0-9_]*', Name.Other, 'slashstartsregex'), + (r'@?[$a-zA-Z_][a-zA-Z0-9_\$]*', Name.Other, 'slashstartsregex'), (r'[0-9][0-9]*\.[0-9]+([eE][0-9]+)?[fd]?', Number.Float), (r'0x[0-9a-fA-F]+', Number.Hex), (r'[0-9]+', Number.Integer), @@ -1880,6 +1885,114 @@ class CoffeeScriptLexer(RegexLexer): ], } + +class LiveScriptLexer(RegexLexer): + """ + For `LiveScript`_ source code. + + .. LiveScript: http://gkz.github.com/LiveScript/ + """ + + name = 'LiveScript' + aliases = ['live-script', 'livescript'] + filenames = ['*.ls'] + mimetypes = ['text/livescript'] + + flags = re.DOTALL + tokens = { + 'commentsandwhitespace': [ + (r'\s+', Text), + (r'/\*.*?\*/', Comment.Multiline), + (r'#.*?\n', Comment.Single), + ], + 'multilineregex': [ + include('commentsandwhitespace'), + (r'//([gim]+\b|\B)', String.Regex, '#pop'), + (r'/', String.Regex), + (r'[^/#]+', String.Regex) + ], + 'slashstartsregex': [ + include('commentsandwhitespace'), + (r'//', String.Regex, ('#pop', 'multilineregex')), + (r'/(?! )(\\.|[^[/\\\n]|\[(\\.|[^\]\\\n])*])+/' + r'([gim]+\b|\B)', String.Regex, '#pop'), + (r'', Text, '#pop'), + ], + 'root': [ + # this next expr leads to infinite loops root -> slashstartsregex + #(r'^(?=\s|/|<!--)', Text, 'slashstartsregex'), + include('commentsandwhitespace'), + (r'(?:\([^()]+\))?[ ]*[~-]{1,2}>|' + r'(?:\(?[^()\n]+\)?)?[ ]*<[~-]{1,2}', Name.Function), + (r'\+\+|&&|(?<![\.\$])\b(?:and|x?or|is|isnt|not)\b|\?|:|=|' + r'\|\||\\(?=\n)|(<<|>>>?|==?|!=?|' + r'~(?!\~?>)|-(?!\-?>)|<(?!\[)|(?<!\])>|' + r'[+*`%&\|\^/])=?', + Operator, 'slashstartsregex'), + (r'[{(\[;,]', Punctuation, 'slashstartsregex'), + (r'[})\].]', Punctuation), + (r'(?<![\.\$])(for|own|in|of|while|until|loop|break|' + r'return|continue|switch|when|then|if|unless|else|' + r'throw|try|catch|finally|new|delete|typeof|instanceof|super|' + r'extends|this|class|by|const|var|to|til)\b', Keyword, + 'slashstartsregex'), + (r'(?<![\.\$])(true|false|yes|no|on|off|' + r'null|NaN|Infinity|undefined|void)\b', + Keyword.Constant), + (r'(Array|Boolean|Date|Error|Function|Math|netscape|' + r'Number|Object|Packages|RegExp|String|sun|decodeURI|' + r'decodeURIComponent|encodeURI|encodeURIComponent|' + r'eval|isFinite|isNaN|parseFloat|parseInt|document|window)\b', + Name.Builtin), + (r'[$a-zA-Z_][a-zA-Z0-9_\.\-:\$]*\s*[:=]\s', Name.Variable, + 'slashstartsregex'), + (r'@[$a-zA-Z_][a-zA-Z0-9_\.\-:\$]*\s*[:=]\s', Name.Variable.Instance, + 'slashstartsregex'), + (r'@', Name.Other, 'slashstartsregex'), + (r'@?[$a-zA-Z_][a-zA-Z0-9_\-]*', Name.Other, 'slashstartsregex'), + (r'[0-9]+\.[0-9]+([eE][0-9]+)?[fd]?(?:[a-zA-Z_]+)?', Number.Float), + (r'[0-9]+(~[0-9a-z]+)?(?:[a-zA-Z_]+)?', Number.Integer), + ('"""', String, 'tdqs'), + ("'''", String, 'tsqs'), + ('"', String, 'dqs'), + ("'", String, 'sqs'), + (r'\\[\w$-]+', String), + (r'<\[.*\]>', String), + ], + 'strings': [ + (r'[^#\\\'"]+', String), + # note that all coffee script strings are multi-line. + # hashmarks, quotes and backslashes must be parsed one at a time + ], + 'interpoling_string' : [ + (r'}', String.Interpol, "#pop"), + include('root') + ], + 'dqs': [ + (r'"', String, '#pop'), + (r'\\.|\'', String), # double-quoted string don't need ' escapes + (r'#{', String.Interpol, "interpoling_string"), + include('strings') + ], + 'sqs': [ + (r"'", String, '#pop'), + (r'#|\\.|"', String), # single quoted strings don't need " escapses + include('strings') + ], + 'tdqs': [ + (r'"""', String, '#pop'), + (r'\\.|\'|"', String), # no need to escape quotes in triple-string + (r'#{', String.Interpol, "interpoling_string"), + include('strings'), + ], + 'tsqs': [ + (r"'''", String, '#pop'), + (r'#|\\.|\'|"', String), # no need to escape quotes in triple-strings + include('strings') + ], + } + + class DuelLexer(RegexLexer): """ Lexer for Duel Views Engine (formerly JBST) markup with JavaScript code blocks. diff --git a/tests/examplefiles/livescript-demo.ls b/tests/examplefiles/livescript-demo.ls new file mode 100644 index 00000000..2ff68c63 --- /dev/null +++ b/tests/examplefiles/livescript-demo.ls @@ -0,0 +1,41 @@ +a = -> [1 to 50] +const b = --> [2 til 5] +var c = ~~> 10_000_000km * 500ms - 16~ff / 32~lol +e = (a) -> (b) ~> (c) --> (d, e) ~~> <[list of words]> +dashes-identifiers = -> + a - a b -- c 1-1 1- -1 a- a a -a +underscores_i$d = -> + /regexp1/ + //regexp2//g + 'strings' and "strings" and \strings + +[2 til 10] + |> map (* 2) + |> filter (> 5) + |> fold (+) + +obj = + prop1: 1 + prop2: 2 + +class Class extends Anc-est-or + (args) -> + <- # Comment + <~ /* Comment */ + void undefined yes no on off + a.void b.undefined c.off d.if f.no g.not + avoid bundefined coff dif fno gnot + "inter #{2 + 2} #variable" + '''HELLO 'world' ''' + +copy = (from, to, callback) --> + error, data <- read file + return callback error if error? + error <~ write file, data + return callback error if error? + callback() + +take(n, [x, ...xs]:list) = + | n <= 0 => [] + | empty list => [] + | otherwise => [x] +++ take n - 1, xs |