Start adding support for Elixir

Antonio Scandurra created

Change summary

Cargo.lock                                     |  10 +
assets/settings/default.json                   |   3 
crates/zed/Cargo.toml                          |   1 
crates/zed/src/languages.rs                    |   1 
crates/zed/src/languages/elixir/brackets.scm   |   5 
crates/zed/src/languages/elixir/config.toml    |  11 +
crates/zed/src/languages/elixir/highlights.scm | 155 ++++++++++++++++++++
crates/zed/src/languages/elixir/indents.scm    |   8 +
crates/zed/src/languages/elixir/outline.scm    |   0 
9 files changed, 194 insertions(+)

Detailed changes

Cargo.lock 🔗

@@ -5868,6 +5868,15 @@ dependencies = [
  "tree-sitter",
 ]
 
+[[package]]
+name = "tree-sitter-elixir"
+version = "0.19.0"
+source = "git+https://github.com/elixir-lang/tree-sitter-elixir?rev=05e3631c6a0701c1fa518b0fee7be95a2ceef5e2#05e3631c6a0701c1fa518b0fee7be95a2ceef5e2"
+dependencies = [
+ "cc",
+ "tree-sitter",
+]
+
 [[package]]
 name = "tree-sitter-go"
 version = "0.19.1"
@@ -7056,6 +7065,7 @@ dependencies = [
  "tree-sitter",
  "tree-sitter-c",
  "tree-sitter-cpp",
+ "tree-sitter-elixir",
  "tree-sitter-go",
  "tree-sitter-json 0.20.0",
  "tree-sitter-markdown",

crates/zed/Cargo.toml 🔗

@@ -91,6 +91,7 @@ toml = "0.5"
 tree-sitter = "0.20"
 tree-sitter-c = "0.20.1"
 tree-sitter-cpp = "0.20.0"
+tree-sitter-elixir = { git = "https://github.com/elixir-lang/tree-sitter-elixir", rev = "05e3631c6a0701c1fa518b0fee7be95a2ceef5e2" }
 tree-sitter-go = { git = "https://github.com/tree-sitter/tree-sitter-go", rev = "aeb2f33b366fd78d5789ff104956ce23508b85db" }
 tree-sitter-json = { git = "https://github.com/tree-sitter/tree-sitter-json", rev = "137e1ce6a02698fc246cdb9c6b886ed1de9a1ed8" }
 tree-sitter-rust = "0.20.1"

crates/zed/src/languages.rs 🔗

@@ -45,6 +45,7 @@ pub async fn init(languages: Arc<LanguageRegistry>, _executor: Arc<Background>)
             tree_sitter_cpp::language(),
             Some(CachedLspAdapter::new(c::CLspAdapter).await),
         ),
+        ("elixir", tree_sitter_elixir::language(), None),
         (
             "go",
             tree_sitter_go::language(),

crates/zed/src/languages/elixir/config.toml 🔗

@@ -0,0 +1,11 @@
+name = "Elixir"
+path_suffixes = ["ex", "exs"]
+line_comment = "# "
+autoclose_before = ";:.,=}])>"
+brackets = [
+    { start = "{", end = "}", close = true, newline = true },
+    { start = "[", end = "]", close = true, newline = true },
+    { start = "(", end = ")", close = true, newline = true },
+    { start = "\"", end = "\"", close = true, newline = false },
+    { start = "do", end = " end", close = true, newline = true },
+]

crates/zed/src/languages/elixir/highlights.scm 🔗

@@ -0,0 +1,155 @@
+["when" "and" "or" "not" "in" "not in" "fn" "do" "end" "catch" "rescue" "after" "else"] @keyword
+
+(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)$"))
+
+(unary_operator
+  operator: "&"
+  operand: (integer) @operator)
+
+(operator_identifier) @operator
+
+(unary_operator
+  operator: _ @operator)
+
+(binary_operator
+  operator: _ @operator)
+
+(dot
+  operator: _ @operator)
+
+(stab_clause
+  operator: _ @operator)
+
+[
+  (boolean)
+  (nil)
+] @constant
+
+[
+  (integer)
+  (float)
+] @number
+
+(alias) @module
+
+(call
+  target: (dot
+    left: (atom) @module))
+
+(char) @constant
+
+(interpolation "#{" @punctuation.special "}" @punctuation.special) @embedded
+
+(escape_sequence) @string.escape
+
+[
+  (atom)
+  (quoted_atom)
+  (keyword)
+  (quoted_keyword)
+] @string.special.symbol
+
+[
+  (string)
+  (charlist)
+] @string
+
+(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
+
+(call
+  target: [
+    (identifier) @function
+    (dot
+      right: (identifier) @function)
+  ])
+
+(call
+  target: (identifier) @keyword
+  (arguments
+    [
+      (identifier) @function
+      (binary_operator
+        left: (identifier) @function
+        operator: "when")
+    ])
+  (#match? @keyword "^(def|defdelegate|defguard|defguardp|defmacro|defmacrop|defn|defnp|defp)$"))
+
+(call
+  target: (identifier) @keyword
+  (arguments
+    (binary_operator
+      operator: "|>"
+      right: (identifier)))
+  (#match? @keyword "^(def|defdelegate|defguard|defguardp|defmacro|defmacrop|defn|defnp|defp)$"))
+
+(binary_operator
+  operator: "|>"
+  right: (identifier) @function)
+
+(call
+  target: (identifier) @keyword
+  (#match? @keyword "^(def|defdelegate|defexception|defguard|defguardp|defimpl|defmacro|defmacrop|defmodule|defn|defnp|defoverridable|defp|defprotocol|defstruct)$"))
+
+(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)$"))
+
+(
+  (identifier) @constant.builtin
+  (#match? @constant.builtin "^(__MODULE__|__DIR__|__ENV__|__CALLER__|__STACKTRACE__)$")
+)
+
+(
+  (identifier) @comment.unused
+  (#match? @comment.unused "^_")
+)
+
+(comment) @comment
+
+[
+ "%"
+] @punctuation
+
+[
+ ","
+ ";"
+] @punctuation.delimiter
+
+[
+  "("
+  ")"
+  "["
+  "]"
+  "{"
+  "}"
+  "<<"
+  ">>"
+] @punctuation.bracket