diff --git a/.gitmodules b/.gitmodules index 2426d305..6a8f3c40 100644 --- a/.gitmodules +++ b/.gitmodules @@ -203,6 +203,9 @@ [submodule "assets/syntaxes/02_Extra/Lean"] path = assets/syntaxes/02_Extra/Lean url = https://github.com/leanprover/vscode-lean.git +[submodule "assets/syntaxes/02_Extra/LiveScript"] + path = assets/syntaxes/02_Extra/LiveScript + url = https://github.com/paulmillr/LiveScript.tmbundle [submodule "assets/syntaxes/02_Extra/Zig"] path = assets/syntaxes/02_Extra/Zig url = https://github.com/ziglang/sublime-zig-language.git diff --git a/CHANGELOG.md b/CHANGELOG.md index a8b38ee7..b0ab9534 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,6 +30,7 @@ - Syslog highlighting improvements, see #1793 (@scop) - Added support for `slim` syntax, see #1693 (@mfinelli) - Racket, see #1884 (@jubnzv) +- LiveScript, see #1915 (@Enselic) ## New themes diff --git a/assets/syntaxes/02_Extra/LiveScript b/assets/syntaxes/02_Extra/LiveScript new file mode 160000 index 00000000..25750138 --- /dev/null +++ b/assets/syntaxes/02_Extra/LiveScript @@ -0,0 +1 @@ +Subproject commit 25750138511925b74da9508050c766f360618055 diff --git a/assets/syntaxes/02_Extra/LiveScript.sublime-syntax b/assets/syntaxes/02_Extra/LiveScript.sublime-syntax new file mode 100644 index 00000000..24f27d68 --- /dev/null +++ b/assets/syntaxes/02_Extra/LiveScript.sublime-syntax @@ -0,0 +1,400 @@ +%YAML 1.2 +--- +# http://www.sublimetext.com/docs/3/syntax.html +name: LiveScript +comment: "LiveScript Syntax: version 1" +file_extensions: + - ls + - Slakefile + - ls.erb +first_line_match: ^#!.*\bls +scope: source.livescript +contexts: + main: + - match: |- + (?x) + !?[~-]{1,2}>\*? + |<[~-]{1,2}!? + |\(\s* (?= instanceof[\s)]|and[\s)]|or[\s)]|is[\s)]|isnt[\s)]|in[\s)]|import[\s)]|import\ all[\s)] |\.|[-+/*%^&<>=|][\b\s)\w$]|\*\*|\%\%) + | (?<=[\s(]instanceof|[\s(]and|[\s(]or|[\s(]is|[\s(]isnt|[\s(]in|[\s(]import|[\s(]import\ all|[\s(]do|\.|\*\*|\%\%|[\b\s(\w$][-+/*%^&<>=|]) \s*\) + scope: storage.type.function.livescript + - match: \/\* + captures: + 0: punctuation.definition.comment.livescript + push: + - meta_scope: comment.block.livescript + - match: \*\/ + captures: + 0: punctuation.definition.comment.livescript + pop: true + - match: '@\w*' + scope: storage.type.annotation.livescriptscript + - match: '(#)(?!\{).*$\n?' + scope: comment.line.number-sign.livescript + captures: + 1: punctuation.definition.comment.livescript + - match: '((?:!|~|!~|~!)?function\*?)\s+([$\w\-]*[$\w]+)' + captures: + 1: storage.type.function.livescript + 2: entity.name.function.livescript + - match: (new)\s+(\w+(?:\.\w*)*) + captures: + 1: keyword.operator.new.livescript + 2: entity.name.type.instance.livescript + - match: \b(package|private|protected|public|interface|enum|static)(?!-)\b + scope: keyword.illegal.livescript + - match: "'''" + captures: + 0: punctuation.definition.string.begin.livescript + push: + - meta_scope: string.quoted.heredoc.livescript + - match: "'''" + captures: + 0: punctuation.definition.string.end.livescript + pop: true + - match: '"""' + captures: + 0: punctuation.definition.string.begin.livescript + push: + - meta_scope: string.quoted.double.heredoc.livescript + - match: '"""' + captures: + 0: punctuation.definition.string.end.livescript + pop: true + - match: \\. + scope: constant.character.escape.livescript + - include: interpolated_livescript + - match: "``" + captures: + 0: punctuation.definition.string.begin.livescript + push: + - meta_scope: string.quoted.script.livescript + - match: "``" + captures: + 0: punctuation.definition.string.end.livescript + pop: true + - match: '\\(x[0-9A-Fa-f]{2}|[0-2][0-7]{0,2}|3[0-6][0-7]|37[0-7]?|[4-7][0-7]?|.)' + scope: constant.character.escape.livescript + - match: '<\[' + push: + - meta_scope: string.array-literal.livescript + - match: '\]>' + pop: true + - match: '/{2}(?![\s=/*+{}?]).*?[^\\]/[igmy]{0,4}(?![a-zA-Z0-9])/{2}' + scope: string.regexp.livescript + - match: '/{2}\n' + push: + - meta_scope: string.regexp.livescript + - match: "/{2}[imgy]{0,4}" + pop: true + - include: embedded_spaced_comment + - include: interpolated_livescript + - match: "/{2}" + push: + - meta_scope: string.regexp.livescript + - match: "/{2}[imgy]{0,4}" + pop: true + - match: '\\(x[0-9A-Fa-f]{2}|[0-2][0-7]{0,2}|3[0-6][0-7]|37[0-7]?|[4-7][0-7]?|.)' + scope: constant.character.escape.livescript + - include: interpolated_livescript + - match: '/(?![\s=/*+{}?]).*?[^\\]/[igmy]{0,4}(?![a-zA-Z0-9])' + scope: string.regexp.livescript + - match: |- + (?x) + \b(? + scope: keyword.operator.livescript + - match: "=>" + scope: keyword.control.livescript + - match: |- + (?x) + \b(?)|\+\+|\+| + ~(?!~?>)|==|=|!=|<=|>=|<<=|>>=| + >>>=|<>|<(?!\[)|(?|(?)|&&|\.\.(\.)?|\s\.\s|\?|\|\||\:|\*=|(?)))\s*(?!(\s*!?\s*\(.*\))?\s*(!?[~-]{1,2}>\*?))' + captures: + 1: variable.assignment.livescript + 3: punctuation.separator.key-value, keyword.operator.livescript + 4: keyword.operator.livescript + - match: '(?<=\s|^)([\[\{])(?=.*?[\]\}]\s+[:=])' + captures: + 0: keyword.operator.livescript + push: + - meta_scope: meta.variable.assignment.destructured.livescript + - match: '([\]\}]\s*[:=])' + captures: + 0: keyword.operator.livescript + pop: true + - include: variable_name + - include: instance_variable + - include: single_quoted_string + - include: double_quoted_string + - include: numeric + - match: |- + (?x) + (\s*) + (?=[a-zA-Z\$_]) + ([a-zA-Z\$_]([\w$.:-])*)\s* + (?=[:=](\s*!?\s*\(.*\))?\s*(!?[~-]{1,2}>\*?)) + scope: meta.function.livescript + captures: + 2: entity.name.function.livescript + 3: entity.name.function.livescript + 4: variable.parameter.function.livescript + 5: storage.type.function.livescript + - match: \b(?][ =)]|[`}%*)]|/(?!.*?/)|&&|[.][^.]|=>|\/ +|\||\|\||\-\-|\+\+|\|>|<|\||$|\n|\#|/\*))' + captures: + 1: meta.function-call.livescript + 2: keyword.operator.livescript + - match: \| _ + scope: keyword.control.livescript + - match: '\|(?![.])' + scope: keyword.control.livescript + - match: \| + scope: keyword.operator.livescript + - match: ((?<=console\.)(debug|warn|info|log|error|time(End|-end)|assert))\b + scope: support.function.console.livescript + - match: |- + (?x)\b( + decodeURI(Component)?|encodeURI(Component)?|eval|parse(Float|Int)|require + )\b + scope: support.function.livescript + - match: |- + (?x)(? 1 +const b = --> 2 +var c = ~> 3 +d = ~~> +e = (a) -> (b) ~> (c) --> (d, e) ~~> 5 +dashes-identifiers = -> + a - a + b -- c + 1-1 1- -1 + a- a + a -a + +//abc #eaze #@ // +// +a #baze +// + +publi +if it is \abc and ($-y = !(a,) ->) ~= map //a#// +then match that | _ | otherwise => implements $("#abc #@a") + +switch |a=>b +| a then b + +if a => b else c + +underscores_i$d = -> +/regexp1/ and //regexp2//g +'strings' and "strings" and \strings +([2 til 10] or [1 to 50]) + |> map (* 2) + |> filter (> 5) + |> fold (+) + +setTimeout _, 3000 <| do-stuff +_.map; _abc; __ + + +class Class extends Anc-est-or + (args) -> + +copy = (from, to, callback) --> + error, data <- read file + return callback error if error? + error <~ write file, data + return callback error if error? + callback() + +$(\#gafBr).text $t.fmtFloat(efb.gaf) + +-> +~> +~~> +--> +# Comment +/* Comment */ +# error, data <- read file + /* error, data <- read file */ + +add = (a=1, b=2) --> a + b +add 1 2 +do-stuff! +do-stuff? # +do-stuff? 1 +do-stuff + 1 +@do-stuff +1 +@do-stuff /1 +a b c |> d <| e f(g) +'cats' is 'cats' +'cats' `_.is-insensitive` 'CATS' +setTimeout _, 1000 <| !-> console.log 'Who summoned me' +private-list = yield @get-private-list! +switch | true => "#@@spaghetti" +~function add a=1, b=2 => a + b +row.0._id +new Spaghetti +(++a++) (++ 2 ++) +(.cool.) (+ a -) (/ 2 *) +(ina -a in) (-> a) +(ina in$a) +(a is-in) +(in) +((((((+ a((a)))))))) diff --git a/tests/syntax-tests/source/LiveScript/LICENSE.md b/tests/syntax-tests/source/LiveScript/LICENSE.md new file mode 100644 index 00000000..5c436445 --- /dev/null +++ b/tests/syntax-tests/source/LiveScript/LICENSE.md @@ -0,0 +1,23 @@ +The `livescript-demo.ls` file has been added from https://github.com/paulmillr/LiveScript.tmbundle under the following license: + +The MIT License (MIT) + +Copyright (c) 2012 Paul Miller (http://paulmillr.com/), Jeremy Ashkenas + +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. diff --git a/tests/syntax-tests/source/LiveScript/livescript-demo.ls b/tests/syntax-tests/source/LiveScript/livescript-demo.ls new file mode 100644 index 00000000..dc34f8cf --- /dev/null +++ b/tests/syntax-tests/source/LiveScript/livescript-demo.ls @@ -0,0 +1,83 @@ +a = -> 1 +const b = --> 2 +var c = ~> 3 +d = ~~> +e = (a) -> (b) ~> (c) --> (d, e) ~~> 5 +dashes-identifiers = -> + a - a + b -- c + 1-1 1- -1 + a- a + a -a + +//abc #eaze #@ // +// +a #baze +// + +publi +if it is \abc and ($-y = !(a,) ->) ~= map //a#// +then match that | _ | otherwise => implements $("#abc #@a") + +switch |a=>b +| a then b + +if a => b else c + +underscores_i$d = -> +/regexp1/ and //regexp2//g +'strings' and "strings" and \strings +([2 til 10] or [1 to 50]) + |> map (* 2) + |> filter (> 5) + |> fold (+) + +setTimeout _, 3000 <| do-stuff +_.map; _abc; __ + + +class Class extends Anc-est-or + (args) -> + +copy = (from, to, callback) --> + error, data <- read file + return callback error if error? + error <~ write file, data + return callback error if error? + callback() + +$(\#gafBr).text $t.fmtFloat(efb.gaf) + +-> +~> +~~> +--> +# Comment +/* Comment */ +# error, data <- read file + /* error, data <- read file */ + +add = (a=1, b=2) --> a + b +add 1 2 +do-stuff! +do-stuff? # +do-stuff? 1 +do-stuff + 1 +@do-stuff +1 +@do-stuff /1 +a b c |> d <| e f(g) +'cats' is 'cats' +'cats' `_.is-insensitive` 'CATS' +setTimeout _, 1000 <| !-> console.log 'Who summoned me' +private-list = yield @get-private-list! +switch | true => "#@@spaghetti" +~function add a=1, b=2 => a + b +row.0._id +new Spaghetti +(++a++) (++ 2 ++) +(.cool.) (+ a -) (/ 2 *) +(ina -a in) (-> a) +(ina in$a) +(a is-in) +(in) +((((((+ a((a))))))))