From 6c0786edc575c5b70bd0d5dcbdaf083f8b5525b1 Mon Sep 17 00:00:00 2001 From: Michael Davis Date: Mon, 11 Oct 2021 20:31:47 -0500 Subject: [PATCH 01/10] prefer elixir-lang/tree-sitter-elixir --- .gitmodules | 2 +- helix-syntax/languages/tree-sitter-elixir | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitmodules b/.gitmodules index a8e6481ea..01260b847 100644 --- a/.gitmodules +++ b/.gitmodules @@ -84,7 +84,7 @@ shallow = true [submodule "helix-syntax/languages/tree-sitter-elixir"] path = helix-syntax/languages/tree-sitter-elixir - url = https://github.com/IceDragon200/tree-sitter-elixir + url = https://github.com/elixir-lang/tree-sitter-elixir shallow = true [submodule "helix-syntax/languages/tree-sitter-nix"] path = helix-syntax/languages/tree-sitter-nix diff --git a/helix-syntax/languages/tree-sitter-elixir b/helix-syntax/languages/tree-sitter-elixir index 295e62a43..7ae20df18 160000 --- a/helix-syntax/languages/tree-sitter-elixir +++ b/helix-syntax/languages/tree-sitter-elixir @@ -1 +1 @@ -Subproject commit 295e62a43b92cea909cfabe57e8818d177f4857b +Subproject commit 7ae20df181b86c79d826abd5aec7a3e32e3d8438 From d1b434d2304218673b7e7564f9e59910b475349c Mon Sep 17 00:00:00 2001 From: Michael Davis Date: Mon, 11 Oct 2021 21:10:14 -0500 Subject: [PATCH 02/10] add highlights query from elixir-lang/tree-sitter-elixir --- runtime/queries/elixir/highlights.scm | 301 +++++++++++++++----------- 1 file changed, 179 insertions(+), 122 deletions(-) diff --git a/runtime/queries/elixir/highlights.scm b/runtime/queries/elixir/highlights.scm index 6bf93a210..bb88e4502 100644 --- a/runtime/queries/elixir/highlights.scm +++ b/runtime/queries/elixir/highlights.scm @@ -1,125 +1,186 @@ -["when" "and" "or" "not in" "not" "in" "fn" "do" "end" "catch" "rescue" "after" "else"] @keyword - -[(true) (false) (nil)] @constant.builtin - -(keyword - [(keyword_literal) - ":"] @tag) - -(keyword - (keyword_string - [(string_start) - (string_content) - (string_end)] @tag)) - -[(atom_literal) - (atom_start) - (atom_content) - (atom_end)] @tag - -[(comment) - (unused_identifier)] @comment - -(escape_sequence) @escape - -(call function: (function_identifier) @keyword - (#match? @keyword "^(defmodule|defexception|defp|def|with|case|cond|raise|import|require|use|defmacrop|defmacro|defguardp|defguard|defdelegate|defstruct|alias|defimpl|defprotocol|defoverridable|receive|if|for|try|throw|unless|reraise|super|quote|unquote|unquote_splicing)$")) - -(call function: (function_identifier) @keyword - [(call - function: (function_identifier) @function - (arguments - [(identifier) @variable.parameter - (_ (identifier) @variable.parameter) - (_ (_ (identifier) @variable.parameter)) - (_ (_ (_ (identifier) @variable.parameter))) - (_ (_ (_ (_ (identifier) @variable.parameter)))) - (_ (_ (_ (_ (_ (identifier) @variable.parameter)))))])) - (binary_op - left: - (call - function: (function_identifier) @function - (arguments - [(identifier) @variable.parameter - (_ (identifier) @variable.parameter) - (_ (_ (identifier) @variable.parameter)) - (_ (_ (_ (identifier) @variable.parameter))) - (_ (_ (_ (_ (identifier) @variable.parameter)))) - (_ (_ (_ (_ (_ (identifier) @variable.parameter)))))])) +; Reserved keywords + +["when" "and" "or" "not" "in" "fn" "do" "end" "catch" "rescue" "after" "else"] @keyword + +; Operators + +; * doc string +(unary_operator + operator: "@" @comment.doc + operand: (call + target: (identifier) @comment.doc.__attribute__ + (arguments + [ + (string) @comment.doc + (charlist) @comment.doc + (sigil + quoted_start: _ @comment.doc + quoted_end: _ @comment.doc) @comment.doc + (boolean) @comment.doc + ])) + (#match? @comment.doc.__attribute__ "^(moduledoc|typedoc|doc)$")) + +; * module attribute +(unary_operator + operator: "@" @attribute + operand: [ + (identifier) @attribute + (call + target: (identifier) @attribute) + (boolean) @attribute + (nil) @attribute + ]) + +; * capture operand +(unary_operator + operator: "&" + operand: (integer) @operator) + +(operator_identifier) @operator + +(unary_operator + operator: _ @operator) + +(binary_operator + operator: _ @operator) + +(dot + operator: _ @operator) + +(stab_clause + operator: _ @operator) + +; Literals + +[ + (boolean) + (nil) +] @constant + +[ + (integer) + (float) +] @number + +(alias) @type + +(char) @constant + +; Quoted content + +(interpolation "#{" @punctuation.special "}" @punctuation.special) @embedded + +(escape_sequence) @string.escape + +[ + (atom) + (quoted_atom) + (keyword) + (quoted_keyword) +] @string.special.symbol + +[ + (string) + (charlist) +] @string + +; Note that we explicitly target sigil quoted start/end, so they are not overridden by delimiters + +(sigil + (sigil_name) @__name__ + quoted_start: _ @string + quoted_end: _ @string + (#match? @__name__ "^[sS]$")) @string + +(sigil + (sigil_name) @__name__ + quoted_start: _ @string.regex + quoted_end: _ @string.regex + (#match? @__name__ "^[rR]$")) @string.regex + +(sigil + (sigil_name) @__name__ + quoted_start: _ @string.special + quoted_end: _ @string.special) @string.special + +; Calls + +; * definition keyword +(call + target: (identifier) @keyword + (#match? @keyword "^(def|defdelegate|defexception|defguard|defguardp|defimpl|defmacro|defmacrop|defmodule|defn|defnp|defoverridable|defp|defprotocol|defstruct)$")) + +; * kernel or special forms keyword +(call + target: (identifier) @keyword + (#match? @keyword "^(alias|case|cond|else|for|if|import|quote|raise|receive|require|reraise|super|throw|try|unless|unquote|unquote_splicing|use|with)$")) + +; * function call +(call + target: [ + ; local + (identifier) @function + ; remote + (dot + right: (identifier) @function) + ]) + +; * just identifier in function definition +(call + target: (identifier) @keyword + (arguments + [ + (identifier) @function + (binary_operator + left: (identifier) @function operator: "when") - (binary_op - left: (identifier) @variable.parameter - operator: _ @function - right: (identifier) @variable.parameter)] - (#match? @keyword "^(defp|def|defmacrop|defmacro|defguardp|defguard|defdelegate)$")) - -(call (function_identifier) @keyword - [(call - function: (function_identifier) @function) - (identifier) @function - (binary_op - left: - [(call - function: (function_identifier) @function) - (identifier) @function] - operator: "when")] - (#match? @keyword "^(defp|def|defmacrop|defmacro|defguardp|defguard|defdelegate)$")) - -(anonymous_function - (stab_expression - left: (bare_arguments - [(identifier) @variable.parameter - (_ (identifier) @variable.parameter) - (_ (_ (identifier) @variable.parameter)) - (_ (_ (_ (identifier) @variable.parameter))) - (_ (_ (_ (_ (identifier) @variable.parameter)))) - (_ (_ (_ (_ (_ (identifier) @variable.parameter)))))]))) - -(unary_op - operator: "@" - (call (identifier) @attribute - (heredoc - [(heredoc_start) - (heredoc_content) - (heredoc_end)] @doc)) - (#match? @attribute "^(doc|moduledoc)$")) - -(module) @type - -(unary_op - operator: "@" @attribute - [(call - function: (function_identifier) @attribute) - (identifier) @attribute]) - -(unary_op - operator: _ @operator) - -(binary_op - operator: _ @operator) - -(heredoc - [(heredoc_start) - (heredoc_content) - (heredoc_end)] @string) - -(string - [(string_start) - (string_content) - (string_end)] @string) - -(sigil_start) @string.special -(sigil_content) @string -(sigil_end) @string.special - -(interpolation - "#{" @punctuation.special - "}" @punctuation.special) + ]) + (#match? @keyword "^(def|defdelegate|defguard|defguardp|defmacro|defmacrop|defn|defnp|defp)$")) + +; * pipe into identifier (definition) +(call + target: (identifier) @keyword + (arguments + (binary_operator + operator: "|>" + right: (identifier) @variable)) + (#match? @keyword "^(def|defdelegate|defguard|defguardp|defmacro|defmacrop|defn|defnp|defp)$")) + +; * pipe into identifier (function call) +(binary_operator + operator: "|>" + right: (identifier) @function) + +; Identifiers + +; * special +( + (identifier) @constant.builtin + (#match? @constant.builtin "^(__MODULE__|__DIR__|__ENV__|__CALLER__|__STACKTRACE__)$") +) + +; * unused +( + (identifier) @comment.unused + (#match? @comment.unused "^_") +) + +; * regular +(identifier) @variable + +; Comment + +(comment) @comment + +; Punctuation + +[ + "%" +] @punctuation [ "," - "->" - "." + ";" ] @punctuation.delimiter [ @@ -132,7 +193,3 @@ "<<" ">>" ] @punctuation.bracket - -(special_identifier) @function.special - -(ERROR) @warning From 5db248cc1ce6077293e4bc96513daf6448f12774 Mon Sep 17 00:00:00 2001 From: Michael Davis Date: Mon, 11 Oct 2021 21:47:49 -0500 Subject: [PATCH 03/10] describe atoms as tags --- runtime/queries/elixir/highlights.scm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/queries/elixir/highlights.scm b/runtime/queries/elixir/highlights.scm index bb88e4502..e37f9b8d9 100644 --- a/runtime/queries/elixir/highlights.scm +++ b/runtime/queries/elixir/highlights.scm @@ -77,7 +77,7 @@ (quoted_atom) (keyword) (quoted_keyword) -] @string.special.symbol +] @tag [ (string) From 95ab40d1718b3ed4c4cfef6cf02603651e6159f6 Mon Sep 17 00:00:00 2001 From: Michael Davis Date: Mon, 11 Oct 2021 21:48:14 -0500 Subject: [PATCH 04/10] use the warning type for tree-sitter ERRORs --- runtime/queries/elixir/highlights.scm | 2 ++ 1 file changed, 2 insertions(+) diff --git a/runtime/queries/elixir/highlights.scm b/runtime/queries/elixir/highlights.scm index e37f9b8d9..f9ceb46e4 100644 --- a/runtime/queries/elixir/highlights.scm +++ b/runtime/queries/elixir/highlights.scm @@ -193,3 +193,5 @@ "<<" ">>" ] @punctuation.bracket + +(ERROR) @warning From b2655a7f5ca0edfffcaabb8ab84b53571afba19a Mon Sep 17 00:00:00 2001 From: Michael Davis Date: Mon, 11 Oct 2021 21:59:07 -0500 Subject: [PATCH 05/10] add LICENSE snippet at elixir hightlights top --- runtime/queries/elixir/highlights.scm | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/runtime/queries/elixir/highlights.scm b/runtime/queries/elixir/highlights.scm index f9ceb46e4..a840018a2 100644 --- a/runtime/queries/elixir/highlights.scm +++ b/runtime/queries/elixir/highlights.scm @@ -1,3 +1,20 @@ +; The following code originates mostly from +; https://github.com/elixir-lang/tree-sitter-elixir, with minor edits to +; align the captures with helix. The following should be considered +; Copyright 2021 The Elixir Team +; +; Licensed under the Apache License, Version 2.0 (the "License"); +; you may not use this file except in compliance with the License. +; You may obtain a copy of the License at +; +; https://www.apache.org/licenses/LICENSE-2.0 +; +; Unless required by applicable law or agreed to in writing, software +; distributed under the License is distributed on an "AS IS" BASIS, +; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +; See the License for the specific language governing permissions and +; limitations under the License. + ; Reserved keywords ["when" "and" "or" "not" "in" "fn" "do" "end" "catch" "rescue" "after" "else"] @keyword From c502cafecc42cc6099241e7ba129727bedf150d7 Mon Sep 17 00:00:00 2001 From: Michael Davis Date: Tue, 12 Oct 2021 16:14:32 -0500 Subject: [PATCH 06/10] highlight calls to erlang modules as types connects https://github.com/elixir-lang/tree-sitter-elixir/pull/5 --- runtime/queries/elixir/highlights.scm | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/runtime/queries/elixir/highlights.scm b/runtime/queries/elixir/highlights.scm index a840018a2..a5b3884e0 100644 --- a/runtime/queries/elixir/highlights.scm +++ b/runtime/queries/elixir/highlights.scm @@ -81,6 +81,10 @@ (alias) @type +(call + target: (dot + left: (atom) @type)) + (char) @constant ; Quoted content From 4771cc7ee49ebf59f837a6899a6b1d7e044c011a Mon Sep 17 00:00:00 2001 From: Michael Davis Date: Thu, 14 Oct 2021 13:45:32 -0500 Subject: [PATCH 07/10] align highlight scopes with documented scopes --- book/src/themes.md | 2 ++ runtime/queries/elixir/highlights.scm | 45 +++++++++++++-------------- 2 files changed, 24 insertions(+), 23 deletions(-) diff --git a/book/src/themes.md b/book/src/themes.md index a99e3a59e..2d75ac576 100644 --- a/book/src/themes.md +++ b/book/src/themes.md @@ -120,6 +120,8 @@ We use a similar set of scopes as - `path` - `url` +- `symbol` - Elixir atoms, Ruby symbols, Clojure keywords + - `comment` - Code comments - `line` - Single line comments (`//`) - `block` - Block comments (e.g. (`/* */`) diff --git a/runtime/queries/elixir/highlights.scm b/runtime/queries/elixir/highlights.scm index a5b3884e0..82ef081db 100644 --- a/runtime/queries/elixir/highlights.scm +++ b/runtime/queries/elixir/highlights.scm @@ -23,29 +23,29 @@ ; * doc string (unary_operator - operator: "@" @comment.doc + operator: "@" @comment.block.documentation operand: (call - target: (identifier) @comment.doc.__attribute__ + target: (identifier) @comment.block.documentation.__attribute__ (arguments [ - (string) @comment.doc - (charlist) @comment.doc + (string) @comment.block.documentation + (charlist) @comment.block.documentation (sigil - quoted_start: _ @comment.doc - quoted_end: _ @comment.doc) @comment.doc - (boolean) @comment.doc + quoted_start: _ @comment.block.documentation + quoted_end: _ @comment.block.documentation) @comment.block.documentation + (boolean) @comment.block.documentation ])) - (#match? @comment.doc.__attribute__ "^(moduledoc|typedoc|doc)$")) + (#match? @comment.block.documentation.__attribute__ "^(moduledoc|typedoc|doc)$")) ; * module attribute (unary_operator - operator: "@" @attribute + operator: "@" @variable.property operand: [ - (identifier) @attribute + (identifier) @variable.property (call - target: (identifier) @attribute) - (boolean) @attribute - (nil) @attribute + target: (identifier) @variable.property) + (boolean) @variable.property + (nil) @variable.property ]) ; * capture operand @@ -69,10 +69,9 @@ ; Literals -[ - (boolean) - (nil) -] @constant +(nil) @constant.builtin + +(boolean) @constant.builtin.boolean [ (integer) @@ -85,20 +84,20 @@ target: (dot left: (atom) @type)) -(char) @constant +(char) @constant.character ; Quoted content -(interpolation "#{" @punctuation.special "}" @punctuation.special) @embedded +(interpolation "#{" @escape "}" @escape) @embedded -(escape_sequence) @string.escape +(escape_sequence) @escape [ (atom) (quoted_atom) (keyword) (quoted_keyword) -] @tag +] @symbol [ (string) @@ -182,8 +181,8 @@ ; * unused ( - (identifier) @comment.unused - (#match? @comment.unused "^_") + (identifier) @comment + (#match? @comment "^_") ) ; * regular From 8f658f0dceffa7bcf2ea18cd6fd0a7dab4e37663 Mon Sep 17 00:00:00 2001 From: Michael Davis Date: Thu, 14 Oct 2021 13:46:58 -0500 Subject: [PATCH 08/10] use latest tree-sitter-elixir with 'not in' query support connects https://github.com/elixir-lang/tree-sitter-elixir/issues/9 --- helix-syntax/languages/tree-sitter-elixir | 2 +- runtime/queries/elixir/highlights.scm | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/helix-syntax/languages/tree-sitter-elixir b/helix-syntax/languages/tree-sitter-elixir index 7ae20df18..f5d7bda54 160000 --- a/helix-syntax/languages/tree-sitter-elixir +++ b/helix-syntax/languages/tree-sitter-elixir @@ -1 +1 @@ -Subproject commit 7ae20df181b86c79d826abd5aec7a3e32e3d8438 +Subproject commit f5d7bda543da788bd507b05bd722627dde66c9ec diff --git a/runtime/queries/elixir/highlights.scm b/runtime/queries/elixir/highlights.scm index 82ef081db..33a84ace8 100644 --- a/runtime/queries/elixir/highlights.scm +++ b/runtime/queries/elixir/highlights.scm @@ -17,7 +17,7 @@ ; Reserved keywords -["when" "and" "or" "not" "in" "fn" "do" "end" "catch" "rescue" "after" "else"] @keyword +["when" "and" "or" "not" "in" "not in" "fn" "do" "end" "catch" "rescue" "after" "else"] @keyword ; Operators From 80b54f2f69165897bfab376d031fab8e040331b6 Mon Sep 17 00:00:00 2001 From: Michael Davis Date: Thu, 14 Oct 2021 13:58:08 -0500 Subject: [PATCH 09/10] use special.string.symbol instead of symbol this aligns better with how ruby highlights symbols --- book/src/themes.md | 3 +-- runtime/queries/elixir/highlights.scm | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/book/src/themes.md b/book/src/themes.md index 2d75ac576..5a4d04038 100644 --- a/book/src/themes.md +++ b/book/src/themes.md @@ -119,8 +119,7 @@ We use a similar set of scopes as - `special` - `path` - `url` - -- `symbol` - Elixir atoms, Ruby symbols, Clojure keywords + - `symbol` - Erlang/Elixir atoms, Ruby symbols, Clojure keywords - `comment` - Code comments - `line` - Single line comments (`//`) diff --git a/runtime/queries/elixir/highlights.scm b/runtime/queries/elixir/highlights.scm index 33a84ace8..a882fb63b 100644 --- a/runtime/queries/elixir/highlights.scm +++ b/runtime/queries/elixir/highlights.scm @@ -97,7 +97,7 @@ (quoted_atom) (keyword) (quoted_keyword) -] @symbol +] @string.special.symbol [ (string) From 4d8eb09b7c436a82e3deff09cbf65a8c68201522 Mon Sep 17 00:00:00 2001 From: Michael Davis Date: Fri, 15 Oct 2021 17:39:05 -0500 Subject: [PATCH 10/10] scope arities in captures as operators --- runtime/queries/elixir/highlights.scm | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/runtime/queries/elixir/highlights.scm b/runtime/queries/elixir/highlights.scm index a882fb63b..08e09f37a 100644 --- a/runtime/queries/elixir/highlights.scm +++ b/runtime/queries/elixir/highlights.scm @@ -48,10 +48,17 @@ (nil) @variable.property ]) -; * capture operand +; * capture operator (unary_operator operator: "&" - operand: (integer) @operator) + operand: [ + (integer) @operator + (binary_operator + left: [ + (call target: (dot left: (_) right: (identifier) @function)) + (identifier) @function + ] operator: "/" right: (integer) @operator) + ]) (operator_identifier) @operator