From bbdc324b7f9bfc7737b2ce158fb7b262a30dceae Mon Sep 17 00:00:00 2001 From: Wilfred Hughes Date: Fri, 19 Aug 2022 00:48:26 -0700 Subject: Add CMake support Fixes #333 --- CHANGELOG.md | 5 ++ build.rs | 5 ++ manual/src/languages_supported.md | 1 + src/diff/sliders.rs | 2 +- src/parse/guess_language.rs | 3 + src/parse/tree_sitter_parser.rs | 15 +++++ vendor/highlights/cmake.scm | 128 ++++++++++++++++++++++++++++++++++++++ vendor/tree-sitter-cmake-src | 1 + 8 files changed, 159 insertions(+), 1 deletion(-) create mode 100644 vendor/highlights/cmake.scm create mode 120000 vendor/tree-sitter-cmake-src diff --git a/CHANGELOG.md b/CHANGELOG.md index 49f8699ef..d2c5f3ac8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,11 @@ ### Parsing +Added support for CMake. + +Improved comment detection using tree-sitter syntax highlighting +queries. + Fixed an issue with language detection when file names were very short. diff --git a/build.rs b/build.rs index 97d2cd017..7ce79811f 100644 --- a/build.rs +++ b/build.rs @@ -88,6 +88,11 @@ fn main() { src_dir: "vendor/tree-sitter-clojure-src", extra_files: vec![], }, + TreeSitterParser { + name: "tree-sitter-cmake", + src_dir: "vendor/tree-sitter-cmake-src", + extra_files: vec!["scanner.cc"], + }, TreeSitterParser { name: "tree-sitter-commonlisp", src_dir: "vendor/tree-sitter-commonlisp-src", diff --git a/manual/src/languages_supported.md b/manual/src/languages_supported.md index 3987d3688..3c9448498 100644 --- a/manual/src/languages_supported.md +++ b/manual/src/languages_supported.md @@ -9,6 +9,7 @@ Difftastic supports the following programming languages. | C++ | [tree-sitter/tree-sitter-cpp](https://github.com/tree-sitter/tree-sitter-cpp) | | C# | [tree-sitter/tree-sitter-c-sharp](https://github.com/tree-sitter/tree-sitter-c-sharp) | | Clojure | [sogaiu/tree-sitter-clojure](https://github.com/sogaiu/tree-sitter-clojure) ([branched](https://github.com/sogaiu/tree-sitter-clojure/tree/issue-21)) | +| CMake | [uyha/tree-sitter-cmake](https://github.com/uyha/tree-sitter-cmake) | | Common Lisp | [theHamsta/tree-sitter-commonlisp](https://github.com/theHamsta/tree-sitter-commonlisp) | | Dart | [UserNobody14/tree-sitter-dart](https://github.com/UserNobody14/tree-sitter-dart) | | Elixir | [elixir-lang/tree-sitter-elixir](https://github.com/elixir-lang/tree-sitter-elixir) | diff --git a/src/diff/sliders.rs b/src/diff/sliders.rs index e71731bfe..a6a5de4fb 100644 --- a/src/diff/sliders.rs +++ b/src/diff/sliders.rs @@ -67,7 +67,7 @@ fn prefer_outer_delimiter(language: guess_language::Language) -> bool { // For everything else, prefer the inner delimiter. These // languages have syntax like `foo(bar)` or `foo[bar]` where // the inner delimiter is more relevant. - Bash | C | CPlusPlus | CSharp | Css | Dart | Elixir | Elm | Elvish | Gleam | Go | Hack + Bash | C | CMake | CPlusPlus | CSharp | Css | Dart | Elixir | Elm | Elvish | Gleam | Go | Hack | Haskell | Html | Java | JavaScript | Jsx | Julia | Kotlin | Lua | Nix | OCaml | OCamlInterface | Perl | Php | Python | Ruby | Rust | Scala | Swift | Tsx | TypeScript | Yaml | Zig => false, diff --git a/src/parse/guess_language.rs b/src/parse/guess_language.rs index ff0af41d7..34eceb661 100644 --- a/src/parse/guess_language.rs +++ b/src/parse/guess_language.rs @@ -21,6 +21,7 @@ pub enum Language { Bash, C, Clojure, + CMake, CommonLisp, CPlusPlus, CSharp, @@ -196,6 +197,7 @@ fn from_name(path: &Path) -> Option { | "PKGBUILD" | "bash_aliases" | "bash_logout" | "bash_profile" | "bashrc" | "cshrc" | "gradlew" | "kshrc" | "login" | "man" | "profile" | "zlogin" | "zlogout" | "zprofile" | "zshenv" | "zshrc" => Some(Bash), + "CMakeLists.txt" => Some(CMake), ".emacs" | "_emacs" | "Cask" => Some(EmacsLisp), ".arcconfig" | ".auto-changelog" | ".c8rc" | ".htmlhintrc" | ".imgbotconfig" | ".nycrc" | ".tern-config" | ".tern-project" | ".watchmanconfig" | "Pipfile.lock" @@ -222,6 +224,7 @@ pub fn from_extension(extension: &OsStr) -> Option { Some(Clojure) } "lisp" | "lsp" | "asd" => Some(CommonLisp), + "cmake" | "cmake.in" => Some(CMake), "cs" => Some(CSharp), "css" => Some(Css), "dart" => Some(Dart), diff --git a/src/parse/tree_sitter_parser.rs b/src/parse/tree_sitter_parser.rs index 9cc98aab7..c52f62533 100644 --- a/src/parse/tree_sitter_parser.rs +++ b/src/parse/tree_sitter_parser.rs @@ -47,6 +47,7 @@ extern "C" { fn tree_sitter_c() -> ts::Language; fn tree_sitter_c_sharp() -> ts::Language; fn tree_sitter_clojure() -> ts::Language; + fn tree_sitter_cmake() -> ts::Language; fn tree_sitter_cpp() -> ts::Language; fn tree_sitter_commonlisp() -> ts::Language; fn tree_sitter_css() -> ts::Language; @@ -164,6 +165,20 @@ pub fn from_language(language: guess::Language) -> TreeSitterConfig { .unwrap(), } } + CMake => { + let language = unsafe { tree_sitter_cmake() }; + TreeSitterConfig { + name: "CMake", + language, + atom_nodes: vec!["argument"].into_iter().collect(), + delimiter_tokens: vec![("(", ")")].into_iter().collect(), + highlight_query: ts::Query::new( + language, + include_str!("../../vendor/highlights/cmake.scm"), + ) + .unwrap(), + } + } CommonLisp => { let language = unsafe { tree_sitter_commonlisp() }; TreeSitterConfig { diff --git a/vendor/highlights/cmake.scm b/vendor/highlights/cmake.scm new file mode 100644 index 000000000..d118992f8 --- /dev/null +++ b/vendor/highlights/cmake.scm @@ -0,0 +1,128 @@ +;; Based on the nvim-treesitter highlighting, which is under the Apache license. +;; https://github.com/nvim-treesitter/nvim-treesitter/blob/d76b0de6536c2461f97cfeca0550f8cb89793935/queries/cmake/highlights.scm + +[ + (quoted_argument) + (bracket_argument) +] @string + +(variable_ref) @none +(variable) @variable + +[ + (bracket_comment) + (line_comment) +] @comment + +(normal_command (identifier) @function) + +["ENV" "CACHE"] @symbol +["$" "{" "}" "<" ">"] @punctuation.special +["(" ")"] @punctuation.bracket + +[ + (function) + (endfunction) + (macro) + (endmacro) +] @keyword.function + +[ + (if) + (elseif) + (else) + (endif) +] @conditional + +[ + (foreach) + (endforeach) + (while) + (endwhile) +] @repeat + +(function_command + (function) + . (argument) @function + (argument)* @parameter +) + +(macro_command + (macro) + . (argument) @function.macro + (argument)* @parameter +) + +;; (normal_command +;; (identifier) @function.builtin +;; . (argument) @variable +;; (#match? @function.builtin "\\c^(set)$") +;; ) + +;; (normal_command +;; (identifier) @function.builtin +;; (#match? @function.builtin "\\c^(set)$") +;; ( +;; (argument) @constant +;; (#any-of? @constant "PARENT_SCOPE") +;; ) . +;; ) + +;; (normal_command +;; (identifier) @function.builtin +;; (#match? @function.builtin "\\c^(set)$") +;; . (argument) +;; ( +;; (argument) @_cache @constant +;; . +;; (argument) @_type @constant +;; (#any-of? @_cache "CACHE") +;; (#any-of? @_type "BOOL" "FILEPATH" "PATH" "STRING" "INTERNAL") +;; ) +;; ) +;; (normal_command +;; (identifier) @function.builtin +;; (#match? @function.builtin "\\c^(set)$") +;; . (argument) +;; (argument) @_cache +;; (#any-of? @_cache "CACHE") +;; ( +;; (argument) @_force @constant +;; (#any-of? @_force "FORCE") +;; ) . +;; ) + +;; ((argument) @boolean +;; (#match? @boolean "\\c^(1|on|yes|true|y|0|off|no|false|n|ignore|notfound|.*-notfound)$") +;; ) + +(if_command + (if) + (argument) @keyword.operator + (#any-of? @keyword.operator "NOT" "AND" "OR" + "COMMAND" "POLICY" "TARGET" "TEST" "DEFINED" "IN_LIST" + "EXISTS" "IS_NEWER_THAN" "IS_DIRECTORY" "IS_SYMLINK" "IS_ABSOLUTE" + "MATCHES" + "LESS" "GREATER" "EQUAL" "LESS_EQUAL" "GREATER_EQUAL" + "STRLESS" "STRGREATER" "STREQUAL" "STRLESS_EQUAL" "STRGREATER_EQUAL" + "VERSION_LESS" "VERSION_GREATER" "VERSION_EQUAL" "VERSION_LESS_EQUAL" "VERSION_GREATER_EQUAL" + ) +) + +;; (normal_command +;; (identifier) @function.builtin +;; . (argument) +;; (argument) @constant +;; (#any-of? @constant "ALL" "COMMAND" "DEPENDS" "BYPRODUCTS" "WORKING_DIRECTORY" "COMMENT" +;; "JOB_POOL" "VERBATIM" "USES_TERMINAL" "COMMAND_EXPAND_LISTS" "SOURCES") +;; (#match? @function.builtin "\\c^(add_custom_target)$") +;; ) + +;; (normal_command +;; (identifier) @function.builtin +;; (argument) @constant +;; (#any-of? @constant "OUTPUT" "COMMAND" "MAIN_DEPENDENCY" "DEPENDS" "BYPRODUCTS" "IMPLICIT_DEPENDS" "WORKING_DIRECTORY" +;; "COMMENT" "DEPFILE" "JOB_POOL" "VERBATIM" "APPEND" "USES_TERMINAL" "COMMAND_EXPAND_LISTS") +;; (#match? @function.builtin "\\c^(add_custom_command)$") +;; ) + diff --git a/vendor/tree-sitter-cmake-src b/vendor/tree-sitter-cmake-src new file mode 120000 index 000000000..f24d4927f --- /dev/null +++ b/vendor/tree-sitter-cmake-src @@ -0,0 +1 @@ +tree-sitter-cmake/src \ No newline at end of file -- cgit v1.2.3