Extract Erlang support into an extension (#9974)
This PR extracts Erlang support into an extension and removes the built-in Erlang support from Zed. Tested using a Nix shell: ``` nix-shell -p erlang-ls ``` Release Notes: - Removed built-in support for Erlang, in favor of making it available as an extension. The Erlang extension will be suggested for download when you open a `.erl` or `.hrl` file.
This commit is contained in:
parent
30193647f3
commit
b0fb02e4be
16 changed files with 69 additions and 81 deletions
16
extensions/erlang/Cargo.toml
Normal file
16
extensions/erlang/Cargo.toml
Normal file
|
@ -0,0 +1,16 @@
|
|||
[package]
|
||||
name = "zed_erlang"
|
||||
version = "0.0.1"
|
||||
edition = "2021"
|
||||
publish = false
|
||||
license = "Apache-2.0"
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
[lib]
|
||||
path = "src/erlang.rs"
|
||||
crate-type = ["cdylib"]
|
||||
|
||||
[dependencies]
|
||||
zed_extension_api = "0.0.4"
|
1
extensions/erlang/LICENSE-APACHE
Symbolic link
1
extensions/erlang/LICENSE-APACHE
Symbolic link
|
@ -0,0 +1 @@
|
|||
../../LICENSE-APACHE
|
15
extensions/erlang/extension.toml
Normal file
15
extensions/erlang/extension.toml
Normal file
|
@ -0,0 +1,15 @@
|
|||
id = "erlang"
|
||||
name = "Erlang"
|
||||
description = "Erlang support."
|
||||
version = "0.0.1"
|
||||
schema_version = 1
|
||||
authors = ["Dairon M <dairon.medina@gmail.com>"]
|
||||
repository = "https://github.com/zed-industries/zed"
|
||||
|
||||
[language_servers.erlang-ls]
|
||||
name = "Erlang Language Server"
|
||||
language = "Erlang"
|
||||
|
||||
[grammars.erlang]
|
||||
repository = "https://github.com/WhatsApp/tree-sitter-erlang"
|
||||
commit = "57e69513efd831f9cc8207d65d96bad917ca4aa4"
|
3
extensions/erlang/languages/erlang/brackets.scm
Normal file
3
extensions/erlang/languages/erlang/brackets.scm
Normal file
|
@ -0,0 +1,3 @@
|
|||
("(" @open ")" @close)
|
||||
("[" @open "]" @close)
|
||||
("{" @open "}" @close)
|
24
extensions/erlang/languages/erlang/config.toml
Normal file
24
extensions/erlang/languages/erlang/config.toml
Normal file
|
@ -0,0 +1,24 @@
|
|||
name = "Erlang"
|
||||
grammar = "erlang"
|
||||
# TODO: support parsing rebar.config files
|
||||
# # https://github.com/WhatsApp/tree-sitter-erlang/issues/3
|
||||
path_suffixes = ["erl", "hrl", "app.src", "escript", "xrl", "yrl", "Emakefile", "rebar.config"]
|
||||
line_comments = ["% ", "%% ", "%%% "]
|
||||
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, not_in = ["string"] },
|
||||
{ start = "\"", end = "\"", close = true, newline = false, not_in = ["string"] },
|
||||
{ start = "'", end = "'", close = true, newline = false, not_in = ["string", "comment"] },
|
||||
]
|
||||
# Indent if a line ends brackets, "->" or most keywords. Also if prefixed
|
||||
# with "||". This should work with most formatting models.
|
||||
# The ([^%]).* is to ensure this doesn't match inside comments.
|
||||
increase_indent_pattern = "^([^%]).*([{(\\[]]|\\->|after|begin|case|catch|fun|if|of|try|when|maybe|else|(\\|\\|.*))\\s*$"
|
||||
|
||||
# Dedent after brackets, end or lone "->". The latter happens in a spec
|
||||
# with indented types, typically after "when". Only do this if it's _only_
|
||||
# preceded by whitespace.
|
||||
decrease_indent_pattern = "^\\s*([)}\\]]|end|else|\\->\\s*$)"
|
231
extensions/erlang/languages/erlang/highlights.scm
Normal file
231
extensions/erlang/languages/erlang/highlights.scm
Normal file
|
@ -0,0 +1,231 @@
|
|||
;; Copyright (c) Facebook, Inc. and its affiliates.
|
||||
;;
|
||||
;; 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
|
||||
;;
|
||||
;; http://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.
|
||||
;; ---------------------------------------------------------------------
|
||||
|
||||
;; Based initially on the contents of https://github.com/WhatsApp/tree-sitter-erlang/issues/2 by @Wilfred
|
||||
;; and https://github.com/the-mikedavis/tree-sitter-erlang/blob/main/queries/highlights.scm
|
||||
;;
|
||||
;; The tests are also based on those in
|
||||
;; https://github.com/the-mikedavis/tree-sitter-erlang/tree/main/test/highlight
|
||||
;;
|
||||
|
||||
|
||||
;; First match wins in this file
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
;; Attributes
|
||||
|
||||
;; module attribute
|
||||
(module_attribute
|
||||
name: (atom) @module)
|
||||
|
||||
;; behaviour
|
||||
(behaviour_attribute name: (atom) @module)
|
||||
|
||||
;; export
|
||||
|
||||
;; Import attribute
|
||||
(import_attribute
|
||||
module: (atom) @module)
|
||||
|
||||
;; export_type
|
||||
|
||||
;; optional_callbacks
|
||||
|
||||
;; compile
|
||||
(compile_options_attribute
|
||||
options: (tuple
|
||||
expr: (atom)
|
||||
expr: (list
|
||||
exprs: (binary_op_expr
|
||||
lhs: (atom)
|
||||
rhs: (integer)))))
|
||||
|
||||
;; file attribute
|
||||
|
||||
;; record
|
||||
(record_decl name: (atom) @type)
|
||||
(record_decl name: (macro_call_expr name: (var) @constant))
|
||||
(record_field name: (atom) @property)
|
||||
|
||||
;; type alias
|
||||
|
||||
;; opaque
|
||||
|
||||
;; Spec attribute
|
||||
(spec fun: (atom) @function)
|
||||
(spec
|
||||
module: (module name: (atom) @module)
|
||||
fun: (atom) @function)
|
||||
|
||||
;; callback
|
||||
(callback fun: (atom) @function)
|
||||
|
||||
;; fun decl
|
||||
|
||||
;; include/include_lib
|
||||
|
||||
;; ifdef/ifndef
|
||||
(pp_ifdef name: (_) @keyword.directive)
|
||||
(pp_ifndef name: (_) @keyword.directive)
|
||||
|
||||
;; define
|
||||
(pp_define
|
||||
lhs: (macro_lhs
|
||||
name: (_) @keyword.directive
|
||||
args: (var_args args: (var))))
|
||||
(pp_define
|
||||
lhs: (macro_lhs
|
||||
name: (var) @constant))
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Functions
|
||||
(fa fun: (atom) @function)
|
||||
(type_name name: (atom) @function)
|
||||
(call expr: (atom) @function)
|
||||
(function_clause name: (atom) @function)
|
||||
(internal_fun fun: (atom) @function)
|
||||
|
||||
;; This is a fudge, we should check that the operator is '/'
|
||||
;; But our grammar does not (currently) provide it
|
||||
(binary_op_expr lhs: (atom) @function rhs: (integer))
|
||||
|
||||
;; Others
|
||||
(remote_module module: (atom) @module)
|
||||
(remote fun: (atom) @function)
|
||||
(macro_call_expr name: (var) @keyword.directive args: (_) )
|
||||
(macro_call_expr name: (var) @constant)
|
||||
(macro_call_expr name: (atom) @keyword.directive)
|
||||
(record_field_name name: (atom) @property)
|
||||
(record_name name: (atom) @type)
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Reserved words
|
||||
[ "after"
|
||||
"and"
|
||||
"band"
|
||||
"begin"
|
||||
"behavior"
|
||||
"behaviour"
|
||||
"bnot"
|
||||
"bor"
|
||||
"bsl"
|
||||
"bsr"
|
||||
"bxor"
|
||||
"callback"
|
||||
"case"
|
||||
"catch"
|
||||
"compile"
|
||||
"define"
|
||||
"deprecated"
|
||||
"div"
|
||||
"elif"
|
||||
"else"
|
||||
"end"
|
||||
"endif"
|
||||
"export"
|
||||
"export_type"
|
||||
"file"
|
||||
"fun"
|
||||
"if"
|
||||
"ifdef"
|
||||
"ifndef"
|
||||
"import"
|
||||
"include"
|
||||
"include_lib"
|
||||
"maybe"
|
||||
"module"
|
||||
"of"
|
||||
"opaque"
|
||||
"optional_callbacks"
|
||||
"or"
|
||||
"receive"
|
||||
"record"
|
||||
"spec"
|
||||
"try"
|
||||
"type"
|
||||
"undef"
|
||||
"unit"
|
||||
"when"
|
||||
"xor"] @keyword
|
||||
|
||||
["andalso" "orelse"] @keyword.operator
|
||||
|
||||
;; Punctuation
|
||||
["," "." ";"] @punctuation.delimiter
|
||||
["(" ")" "{" "}" "[" "]" "<<" ">>"] @punctuation.bracket
|
||||
|
||||
;; Operators
|
||||
["!"
|
||||
"->"
|
||||
"<-"
|
||||
"#"
|
||||
"::"
|
||||
"|"
|
||||
":"
|
||||
"="
|
||||
"||"
|
||||
|
||||
"+"
|
||||
"-"
|
||||
"bnot"
|
||||
"not"
|
||||
|
||||
"/"
|
||||
"*"
|
||||
"div"
|
||||
"rem"
|
||||
"band"
|
||||
"and"
|
||||
|
||||
"+"
|
||||
"-"
|
||||
"bor"
|
||||
"bxor"
|
||||
"bsl"
|
||||
"bsr"
|
||||
"or"
|
||||
"xor"
|
||||
|
||||
"++"
|
||||
"--"
|
||||
|
||||
"=="
|
||||
"/="
|
||||
"=<"
|
||||
"<"
|
||||
">="
|
||||
">"
|
||||
"=:="
|
||||
"=/="
|
||||
] @operator
|
||||
|
||||
;;; Comments
|
||||
((var) @comment.discard
|
||||
(#match? @comment.discard "^_"))
|
||||
|
||||
(dotdotdot) @comment.discard
|
||||
(comment) @comment
|
||||
|
||||
;; Primitive types
|
||||
(string) @string
|
||||
(char) @constant
|
||||
(integer) @number
|
||||
(var) @variable
|
||||
(atom) @string.special.symbol
|
||||
|
||||
;; wild attribute (Should take precedence over atoms, otherwise they are highlighted as atoms)
|
||||
(wild_attribute name: (attr_name name: (_) @keyword))
|
3
extensions/erlang/languages/erlang/indents.scm
Normal file
3
extensions/erlang/languages/erlang/indents.scm
Normal file
|
@ -0,0 +1,3 @@
|
|||
(_ "[" "]" @end) @indent
|
||||
(_ "{" "}" @end) @indent
|
||||
(_ "(" ")" @end) @indent
|
31
extensions/erlang/languages/erlang/outline.scm
Normal file
31
extensions/erlang/languages/erlang/outline.scm
Normal file
|
@ -0,0 +1,31 @@
|
|||
(module_attribute
|
||||
"module" @context
|
||||
name: (_) @name) @item
|
||||
|
||||
(behaviour_attribute
|
||||
"behaviour" @context
|
||||
(atom) @name) @item
|
||||
|
||||
(type_alias
|
||||
"type" @context
|
||||
name: (_) @name) @item
|
||||
|
||||
(opaque
|
||||
"opaque" @context
|
||||
name: (_) @name) @item
|
||||
|
||||
(pp_define
|
||||
"define" @context
|
||||
lhs: (_) @name) @item
|
||||
|
||||
(record_decl
|
||||
"record" @context
|
||||
name: (_) @name) @item
|
||||
|
||||
(callback
|
||||
"callback" @context
|
||||
fun: (_) @function ( (_) @name)) @item
|
||||
|
||||
(fun_decl (function_clause
|
||||
name: (_) @name
|
||||
args: (_) @context)) @item
|
27
extensions/erlang/src/erlang.rs
Normal file
27
extensions/erlang/src/erlang.rs
Normal file
|
@ -0,0 +1,27 @@
|
|||
use zed_extension_api::{self as zed, Result};
|
||||
|
||||
struct ErlangExtension;
|
||||
|
||||
impl zed::Extension for ErlangExtension {
|
||||
fn new() -> Self {
|
||||
Self
|
||||
}
|
||||
|
||||
fn language_server_command(
|
||||
&mut self,
|
||||
_config: zed::LanguageServerConfig,
|
||||
worktree: &zed::Worktree,
|
||||
) -> Result<zed::Command> {
|
||||
let path = worktree
|
||||
.which("erlang_ls")
|
||||
.ok_or_else(|| "erlang_ls must be installed and available on your $PATH".to_string())?;
|
||||
|
||||
Ok(zed::Command {
|
||||
command: path,
|
||||
args: Vec::new(),
|
||||
env: Default::default(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
zed::register_extension!(ErlangExtension);
|
Loading…
Add table
Add a link
Reference in a new issue