diff --git a/CHANGELOG.md b/CHANGELOG.md index 1ca8f2f94..245436a94 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,8 @@ syntactic changes". Fixed an issue in C and C++ where blank lines were highlighted after novel preprocessor lines. +Added support for Lua. + ## 0.24 (release 26th March 2022) ### Diffing diff --git a/README.md b/README.md index 1d29eba90..6b7d30fc2 100644 --- a/README.md +++ b/README.md @@ -53,6 +53,7 @@ Difftastic supports the following languages: * Java * JavaScript (and JSX) * JSON +* Lua * OCaml * PHP * Python diff --git a/build.rs b/build.rs index 64d9109ce..b7c092d51 100644 --- a/build.rs +++ b/build.rs @@ -129,6 +129,11 @@ fn main() { src_dir: "vendor/tree-sitter-json-src", extra_files: vec![], }, + TreeSitterParser { + name: "tree-sitter-lua", + src_dir: "vendor/tree-sitter-lua-src", + extra_files: vec!["scanner.cc"], + }, TreeSitterParser { name: "tree-sitter-ocaml", src_dir: "vendor/tree-sitter-ocaml-src/ocaml/src", diff --git a/manual/src/upstream_parsers.md b/manual/src/upstream_parsers.md index 557422c38..2ee466dbf 100644 --- a/manual/src/upstream_parsers.md +++ b/manual/src/upstream_parsers.md @@ -19,6 +19,7 @@ Difftastic uses the following tree-sitter parsers: | Java | [tree-sitter/tree-sitter-java](https://github.com/tree-sitter/tree-sitter-java) | | JavaScript, JSX | [tree-sitter/tree-sitter-javascript](https://github.com/tree-sitter/tree-sitter-javascript) | | JSON | [tree-sitter/tree-sitter-json](https://github.com/tree-sitter/tree-sitter-json) | +| Lua | [nvim-treesitter/tree-sitter-lua](https://github.com/nvim-treesitter/tree-sitter-lua) | | OCaml | [tree-sitter/tree-sitter-ocaml](https://github.com/tree-sitter/tree-sitter-ocaml) | | PHP | [tree-sitter/tree-sitter-php](https://github.com/tree-sitter/tree-sitter-php) | | Python | [tree-sitter/tree-sitter-python](https://github.com/tree-sitter/tree-sitter-python) | diff --git a/sample_files/compare.expected b/sample_files/compare.expected index cfcedc84a..bd4411b7d 100644 --- a/sample_files/compare.expected +++ b/sample_files/compare.expected @@ -64,6 +64,9 @@ f0befdc2c221d021a03acd6c0e662e37 - sample_files/load_before.js sample_files/load_after.js c5a352313dfb4ae1818190f144c4874b - +sample_files/lua_before.lua sample_files/lua_after.lua +2899a7fcb6bd0edf247a2773a7443992 - + sample_files/modules_before.ml sample_files/modules_after.ml 4c0613c6038eaea73e10a91e7a86e916 - diff --git a/sample_files/lua_after.lua b/sample_files/lua_after.lua new file mode 100644 index 000000000..9228bac62 --- /dev/null +++ b/sample_files/lua_after.lua @@ -0,0 +1,16 @@ +function test(name) + print("testing"..name) + return 10 +end + +if test("myname") == 20 then + print("20") +end + +local list = { "A", "B", "C", "D" } +local table = { a = "A", b = "B", c = "C", d = "D" } + +for k, v in pairs(table) do + print("k: "..k.." v: "..v) +end + diff --git a/sample_files/lua_before.lua b/sample_files/lua_before.lua new file mode 100644 index 000000000..32f3eaa1e --- /dev/null +++ b/sample_files/lua_before.lua @@ -0,0 +1,16 @@ +function test() + print("testing") + return 10 +end + +if test() == 20 then + print("30") +end + +local list = { "A", "B", "D" } +local table = { a = "A", b = "B", d = "D" } + +for k, v in pairs(table) do + print("k: "..k.." v: "..v) +end + diff --git a/src/guess_language.rs b/src/guess_language.rs index 7cc4d7553..f3de34bd3 100644 --- a/src/guess_language.rs +++ b/src/guess_language.rs @@ -34,6 +34,7 @@ pub enum Language { JavaScript, Json, Jsx, + Lua, OCaml, OCamlInterface, Php, @@ -192,6 +193,7 @@ fn from_extension(extension: &OsStr, src: &str) -> Option { "cjs" | "js" | "mjs" => Some(JavaScript), "jsx" => Some(Jsx), "json" => Some(Json), + "lua" => Some(Lua), "ml" => Some(OCaml), "mli" => Some(OCamlInterface), "php" if !src.starts_with(" Some(Php), diff --git a/src/tree_sitter_parser.rs b/src/tree_sitter_parser.rs index 8a5a4a927..77ac1c8f7 100644 --- a/src/tree_sitter_parser.rs +++ b/src/tree_sitter_parser.rs @@ -58,6 +58,7 @@ extern "C" { fn tree_sitter_java() -> ts::Language; fn tree_sitter_javascript() -> ts::Language; fn tree_sitter_json() -> ts::Language; + fn tree_sitter_lua() -> ts::Language; fn tree_sitter_ocaml() -> ts::Language; fn tree_sitter_ocaml_interface() -> ts::Language; fn tree_sitter_php() -> ts::Language; @@ -325,6 +326,22 @@ pub fn from_language(language: guess::Language) -> TreeSitterConfig { .unwrap(), } } + Lua => { + let language = unsafe { tree_sitter_lua() }; + TreeSitterConfig { + name: "Lua", + language, + atom_nodes: (vec!["string"]).into_iter().collect(), + delimiter_tokens: (vec![("(", ")"), ("{", "}"), ("[", "]")]) + .into_iter() + .collect(), + highlight_query: ts::Query::new( + language, + include_str!("../vendor/highlights/lua.scm"), + ) + .unwrap(), + } + } OCaml => { let language = unsafe { tree_sitter_ocaml() }; TreeSitterConfig { diff --git a/vendor/highlights/lua.scm b/vendor/highlights/lua.scm new file mode 100644 index 000000000..6c4323b30 --- /dev/null +++ b/vendor/highlights/lua.scm @@ -0,0 +1,76 @@ +;; Keywords + +[ + "goto" + "in" + "local" + "return" + "and" + "not" + "or" + "function" + "if" + "elseif" + "else" + "then" + "for" + "do" + "end" + "repeat" + "until" + "while" +] @keyword + +[ + "+" + "-" + "*" + "/" + "%" + "^" + "#" + "==" + "~=" + "<=" + ">=" + "<" + ">" + "=" + "&" + "~" + "|" + "<<" + ">>" + "//" + ".." +] @operator + +;; Variables + +(identifier) @variable + +((identifier) @variable.builtin + (#match? @variable.builtin "self")) + +;; Constants + +((identifier) @constant + (#match? @constant "^[A-Z][A-Z_0-9]*$")) + +(nil) @constant.builtin + +[ + (false) + (true) +] @boolean + +;; Others + +(comment) @comment + +(number) @number + +(string) @string + +;; Error +(ERROR) @error diff --git a/vendor/tree-sitter-lua-src b/vendor/tree-sitter-lua-src new file mode 120000 index 000000000..4e76dd562 --- /dev/null +++ b/vendor/tree-sitter-lua-src @@ -0,0 +1 @@ +tree-sitter-lua/src/ \ No newline at end of file