Unified · Split
| @@ -8716,6 +8716,15 @@ dependencies = [ · 8715 unmodified lines | |||
| 8716 | "tree-sitter", | 8716 | "tree-sitter", |
| 8717 | ] | 8717 | ] |
| 8718 | 8718 | ||
| 8719 | [[package]] | ||
| 8720 | name = "tree-sitter-zig" | ||
| 8721 | version = "0.0.1" | ||
| 8722 | source = "git+https://github.com/maxxnino/tree-sitter-zig?rev=0d08703e4c3f426ec61695d7617415fff97029bd#0d08703e4c3f426ec61695d7617415fff97029bd" | ||
| 8723 | dependencies = [ | ||
| 8724 | "cc", | ||
| 8725 | "tree-sitter", | ||
| 8726 | ] | ||
| 8727 | |||
| 8719 | [[package]] | 8728 | [[package]] |
| 8720 | name = "try-lock" | 8729 | name = "try-lock" |
| 8721 | version = "0.2.4" | 8730 | version = "0.2.4" |
| @@ -9812,6 +9821,7 @@ dependencies = [ · 1090 unmodified lines | |||
| 9812 | "tree-sitter-uiua", | 9821 | "tree-sitter-uiua", |
| 9813 | "tree-sitter-vue", | 9822 | "tree-sitter-vue", |
| 9814 | "tree-sitter-yaml", | 9823 | "tree-sitter-yaml", |
| 9824 | "tree-sitter-zig", | ||
| 9815 | "unindent", | 9825 | "unindent", |
| 9816 | "url", | 9826 | "url", |
| 9817 | "urlencoding", | 9827 | "urlencoding", |
| @@ -161,6 +161,7 @@ tree-sitter-nix = { git = "https://github.com/nix-community/tree-sitter-nix", re · 160 unmodified lines | |||
| 161 | tree-sitter-nu = { git = "https://github.com/nushell/tree-sitter-nu", rev = "26bbaecda0039df4067861ab38ea8ea169f7f5aa"} | 161 | tree-sitter-nu = { git = "https://github.com/nushell/tree-sitter-nu", rev = "26bbaecda0039df4067861ab38ea8ea169f7f5aa"} |
| 162 | tree-sitter-vue = {git = "https://github.com/zed-industries/tree-sitter-vue", rev = "6608d9d60c386f19d80af7d8132322fa11199c42"} | 162 | tree-sitter-vue = {git = "https://github.com/zed-industries/tree-sitter-vue", rev = "6608d9d60c386f19d80af7d8132322fa11199c42"} |
| 163 | tree-sitter-uiua = {git = "https://github.com/shnarazk/tree-sitter-uiua", rev = "9260f11be5900beda4ee6d1a24ab8ddfaf5a19b2"} | 163 | tree-sitter-uiua = {git = "https://github.com/shnarazk/tree-sitter-uiua", rev = "9260f11be5900beda4ee6d1a24ab8ddfaf5a19b2"} |
| 164 | tree-sitter-zig = { git = "https://github.com/maxxnino/tree-sitter-zig", rev = "0d08703e4c3f426ec61695d7617415fff97029bd" } | ||
| 164 | 165 | ||
| 165 | [patch.crates-io] | 166 | [patch.crates-io] |
| 166 | tree-sitter = { git = "https://github.com/tree-sitter/tree-sitter", rev = "31c40449749c4263a91a43593831b82229049a4c" } | 167 | tree-sitter = { git = "https://github.com/tree-sitter/tree-sitter", rev = "31c40449749c4263a91a43593831b82229049a4c" } |
| @@ -142,6 +142,7 @@ tree-sitter-nix.workspace = true · 141 unmodified lines | |||
| 142 | tree-sitter-nu.workspace = true | 142 | tree-sitter-nu.workspace = true |
| 143 | tree-sitter-vue.workspace = true | 143 | tree-sitter-vue.workspace = true |
| 144 | tree-sitter-uiua.workspace = true | 144 | tree-sitter-uiua.workspace = true |
| 145 | tree-sitter-zig.workspace = true | ||
| 145 | 146 | ||
| 146 | url = "2.2" | 147 | url = "2.2" |
| 147 | urlencoding = "2.1.2" | 148 | urlencoding = "2.1.2" |
| @@ -31,6 +31,7 @@ mod typescript; · 30 unmodified lines | |||
| 31 | mod uiua; | 31 | mod uiua; |
| 32 | mod vue; | 32 | mod vue; |
| 33 | mod yaml; | 33 | mod yaml; |
| 34 | mod zig; | ||
| 34 | 35 | ||
| 35 | // 1. Add tree-sitter-{language} parser to zed crate | 36 | // 1. Add tree-sitter-{language} parser to zed crate |
| 36 | // 2. Create a language directory in zed/crates/zed/src/languages and add the language to init function below | 37 | // 2. Create a language directory in zed/crates/zed/src/languages and add the language to init function below |
| @@ -112,6 +113,11 @@ pub fn init( · 75 unmodified lines | |||
| 112 | tree_sitter_go::language(), | 113 | tree_sitter_go::language(), |
| 113 | vec![Arc::new(go::GoLspAdapter)], | 114 | vec![Arc::new(go::GoLspAdapter)], |
| 114 | ); | 115 | ); |
| 116 | language( | ||
| 117 | "zig", | ||
| 118 | tree_sitter_zig::language(), | ||
| 119 | vec![Arc::new(zig::ZlsAdapter)], | ||
| 120 | ); | ||
| 115 | language( | 121 | language( |
| 116 | "heex", | 122 | "heex", |
| 117 | tree_sitter_heex::language(), | 123 | tree_sitter_heex::language(), |
| @@ -0,0 +1,125 @@ | |||
| 1 | use anyhow::{anyhow, Context, Result}; | ||
| 2 | use async_compression::futures::bufread::GzipDecoder; | ||
| 3 | use async_tar::Archive; | ||
| 4 | use async_trait::async_trait; | ||
| 5 | use futures::{io::BufReader, StreamExt}; | ||
| 6 | use language::{LanguageServerName, LspAdapter, LspAdapterDelegate}; | ||
| 7 | use lsp::LanguageServerBinary; | ||
| 8 | use smol::fs; | ||
| 9 | use std::env::consts::ARCH; | ||
| 10 | use std::{any::Any, path::PathBuf}; | ||
| 11 | use util::async_maybe; | ||
| 12 | use util::github::latest_github_release; | ||
| 13 | use util::{github::GitHubLspBinaryVersion, ResultExt}; | ||
| 14 | |||
| 15 | pub struct ZlsAdapter; | ||
| 16 | |||
| 17 | #[async_trait] | ||
| 18 | impl LspAdapter for ZlsAdapter { | ||
| 19 | fn name(&self) -> LanguageServerName { | ||
| 20 | LanguageServerName("zls".into()) | ||
| 21 | } | ||
| 22 | |||
| 23 | fn short_name(&self) -> &'static str { | ||
| 24 | "zls" | ||
| 25 | } | ||
| 26 | |||
| 27 | async fn fetch_latest_server_version( | ||
| 28 | &self, | ||
| 29 | delegate: &dyn LspAdapterDelegate, | ||
| 30 | ) -> Result<Box<dyn 'static + Send + Any>> { | ||
| 31 | let release = latest_github_release("zigtools/zls", false, delegate.http_client()).await?; | ||
| 32 | let asset_name = format!("zls-{}-macos.tar.gz", ARCH); | ||
| 33 | let asset = release | ||
| 34 | .assets | ||
| 35 | .iter() | ||
| 36 | .find(|asset| asset.name == asset_name) | ||
| 37 | .ok_or_else(|| anyhow!("no asset found matching {:?}", asset_name))?; | ||
| 38 | let version = GitHubLspBinaryVersion { | ||
| 39 | name: release.name, | ||
| 40 | url: asset.browser_download_url.clone(), | ||
| 41 | }; | ||
| 42 | |||
| 43 | Ok(Box::new(version) as Box<_>) | ||
| 44 | } | ||
| 45 | |||
| 46 | async fn fetch_server_binary( | ||
| 47 | &self, | ||
| 48 | version: Box<dyn 'static + Send + Any>, | ||
| 49 | container_dir: PathBuf, | ||
| 50 | delegate: &dyn LspAdapterDelegate, | ||
| 51 | ) -> Result<LanguageServerBinary> { | ||
| 52 | let version = version.downcast::<GitHubLspBinaryVersion>().unwrap(); | ||
| 53 | let binary_path = container_dir.join("bin/zls"); | ||
| 54 | |||
| 55 | if fs::metadata(&binary_path).await.is_err() { | ||
| 56 | let mut response = delegate | ||
| 57 | .http_client() | ||
| 58 | .get(&version.url, Default::default(), true) | ||
| 59 | .await | ||
| 60 | .context("error downloading release")?; | ||
| 61 | let decompressed_bytes = GzipDecoder::new(BufReader::new(response.body_mut())); | ||
| 62 | let archive = Archive::new(decompressed_bytes); | ||
| 63 | archive.unpack(container_dir).await?; | ||
| 64 | } | ||
| 65 | |||
| 66 | fs::set_permissions( | ||
| 67 | &binary_path, | ||
| 68 | <fs::Permissions as fs::unix::PermissionsExt>::from_mode(0o755), | ||
| 69 | ) | ||
| 70 | .await?; | ||
| 71 | Ok(LanguageServerBinary { | ||
| 72 | path: binary_path, | ||
| 73 | arguments: vec![], | ||
| 74 | }) | ||
| 75 | } | ||
| 76 | |||
| 77 | async fn cached_server_binary( | ||
| 78 | &self, | ||
| 79 | container_dir: PathBuf, | ||
| 80 | _: &dyn LspAdapterDelegate, | ||
| 81 | ) -> Option<LanguageServerBinary> { | ||
| 82 | get_cached_server_binary(container_dir).await | ||
| 83 | } | ||
| 84 | |||
| 85 | async fn installation_test_binary( | ||
| 86 | &self, | ||
| 87 | container_dir: PathBuf, | ||
| 88 | ) -> Option<LanguageServerBinary> { | ||
| 89 | get_cached_server_binary(container_dir) | ||
| 90 | .await | ||
| 91 | .map(|mut binary| { | ||
| 92 | binary.arguments = vec!["--help".into()]; | ||
| 93 | binary | ||
| 94 | }) | ||
| 95 | } | ||
| 96 | } | ||
| 97 | |||
| 98 | async fn get_cached_server_binary(container_dir: PathBuf) -> Option<LanguageServerBinary> { | ||
| 99 | async_maybe!({ | ||
| 100 | let mut last_binary_path = None; | ||
| 101 | let mut entries = fs::read_dir(&container_dir).await?; | ||
| 102 | while let Some(entry) = entries.next().await { | ||
| 103 | let entry = entry?; | ||
| 104 | if entry.file_type().await?.is_file() | ||
| 105 | && entry | ||
| 106 | .file_name() | ||
| 107 | .to_str() | ||
| 108 | .map_or(false, |name| name == "zls") | ||
| 109 | { | ||
| 110 | last_binary_path = Some(entry.path()); | ||
| 111 | } | ||
| 112 | } | ||
| 113 | |||
| 114 | if let Some(path) = last_binary_path { | ||
| 115 | Ok(LanguageServerBinary { | ||
| 116 | path, | ||
| 117 | arguments: Vec::new(), | ||
| 118 | }) | ||
| 119 | } else { | ||
| 120 | Err(anyhow!("no cached binary")) | ||
| 121 | } | ||
| 122 | }) | ||
| 123 | .await | ||
| 124 | .log_err() | ||
| 125 | } | ||
| @@ -0,0 +1,10 @@ | |||
| 1 | name = "Zig" | ||
| 2 | path_suffixes = ["zig"] | ||
| 3 | line_comment = "// " | ||
| 4 | autoclose_before = ";:.,=}])>" | ||
| 5 | brackets = [ | ||
| 6 | { start = "{", end = "}", close = true, newline = true }, | ||
| 7 | { start = "[", end = "]", close = true, newline = true }, | ||
| 8 | { start = "(", end = ")", close = true, newline = true }, | ||
| 9 | { start = "<", end = ">", close = true, newline = true }, | ||
| 10 | ] | ||
| @@ -0,0 +1,16 @@ | |||
| 1 | [ | ||
| 2 | (Block) | ||
| 3 | (ContainerDecl) | ||
| 4 | (SwitchExpr) | ||
| 5 | (InitList) | ||
| 6 | (AsmExpr) | ||
| 7 | (ErrorSetDecl) | ||
| 8 | (LINESTRING) | ||
| 9 | ( | ||
| 10 | [ | ||
| 11 | (IfPrefix) | ||
| 12 | (WhilePrefix) | ||
| 13 | (ForPrefix) | ||
| 14 | ] | ||
| 15 | ) | ||
| 16 | ] @fold | ||
| @@ -0,0 +1,234 @@ | |||
| 1 | [ | ||
| 2 | (container_doc_comment) | ||
| 3 | (doc_comment) | ||
| 4 | (line_comment) | ||
| 5 | ] @comment | ||
| 6 | |||
| 7 | [ | ||
| 8 | variable: (IDENTIFIER) | ||
| 9 | variable_type_function: (IDENTIFIER) | ||
| 10 | ] @variable | ||
| 11 | |||
| 12 | parameter: (IDENTIFIER) @parameter | ||
| 13 | |||
| 14 | [ | ||
| 15 | field_member: (IDENTIFIER) | ||
| 16 | field_access: (IDENTIFIER) | ||
| 17 | ] @field | ||
| 18 | |||
| 19 | ;; assume TitleCase is a type | ||
| 20 | ( | ||
| 21 | [ | ||
| 22 | variable_type_function: (IDENTIFIER) | ||
| 23 | field_access: (IDENTIFIER) | ||
| 24 | parameter: (IDENTIFIER) | ||
| 25 | ] @type | ||
| 26 | (#match? @type "^[A-Z]([a-z]+[A-Za-z0-9]*)*$") | ||
| 27 | ) | ||
| 28 | ;; assume camelCase is a function | ||
| 29 | ( | ||
| 30 | [ | ||
| 31 | variable_type_function: (IDENTIFIER) | ||
| 32 | field_access: (IDENTIFIER) | ||
| 33 | parameter: (IDENTIFIER) | ||
| 34 | ] @function | ||
| 35 | (#match? @function "^[a-z]+([A-Z][a-z0-9]*)+$") | ||
| 36 | ) | ||
| 37 | |||
| 38 | ;; assume all CAPS_1 is a constant | ||
| 39 | ( | ||
| 40 | [ | ||
| 41 | variable_type_function: (IDENTIFIER) | ||
| 42 | field_access: (IDENTIFIER) | ||
| 43 | ] @constant | ||
| 44 | (#match? @constant "^[A-Z][A-Z_0-9]+$") | ||
| 45 | ) | ||
| 46 | |||
| 47 | [ | ||
| 48 | function_call: (IDENTIFIER) | ||
| 49 | function: (IDENTIFIER) | ||
| 50 | ] @function | ||
| 51 | |||
| 52 | exception: "!" @exception | ||
| 53 | |||
| 54 | ( | ||
| 55 | (IDENTIFIER) @variable.builtin | ||
| 56 | (#eq? @variable.builtin "_") | ||
| 57 | ) | ||
| 58 | |||
| 59 | (PtrTypeStart "c" @variable.builtin) | ||
| 60 | |||
| 61 | ( | ||
| 62 | (ContainerDeclType | ||
| 63 | [ | ||
| 64 | (ErrorUnionExpr) | ||
| 65 | "enum" | ||
| 66 | ] | ||
| 67 | ) | ||
| 68 | (ContainerField (IDENTIFIER) @constant) | ||
| 69 | ) | ||
| 70 | |||
| 71 | field_constant: (IDENTIFIER) @constant | ||
| 72 | |||
| 73 | (BUILTINIDENTIFIER) @keyword | ||
| 74 | |||
| 75 | ; No idea why this doesnt work | ||
| 76 | ; ((BUILTINIDENTIFIER) @include | ||
| 77 | ; (#any-of? @include "@import" "@cImport")) | ||
| 78 | |||
| 79 | (INTEGER) @number | ||
| 80 | |||
| 81 | (FLOAT) @float | ||
| 82 | |||
| 83 | [ | ||
| 84 | "true" | ||
| 85 | "false" | ||
| 86 | ] @boolean | ||
| 87 | |||
| 88 | [ | ||
| 89 | (LINESTRING) | ||
| 90 | (STRINGLITERALSINGLE) | ||
| 91 | ] @string | ||
| 92 | |||
| 93 | (CHAR_LITERAL) @character | ||
| 94 | (EscapeSequence) @string.escape | ||
| 95 | (FormatSequence) @string.special | ||
| 96 | |||
| 97 | (BreakLabel (IDENTIFIER) @label) | ||
| 98 | (BlockLabel (IDENTIFIER) @label) | ||
| 99 | |||
| 100 | [ | ||
| 101 | "asm" | ||
| 102 | "defer" | ||
| 103 | "errdefer" | ||
| 104 | "test" | ||
| 105 | "struct" | ||
| 106 | "union" | ||
| 107 | "enum" | ||
| 108 | "opaque" | ||
| 109 | "error" | ||
| 110 | ] @keyword | ||
| 111 | |||
| 112 | [ | ||
| 113 | "async" | ||
| 114 | "await" | ||
| 115 | "suspend" | ||
| 116 | "nosuspend" | ||
| 117 | "resume" | ||
| 118 | ] @keyword.coroutine | ||
| 119 | |||
| 120 | [ | ||
| 121 | "fn" | ||
| 122 | ] @keyword.function | ||
| 123 | |||
| 124 | [ | ||
| 125 | "and" | ||
| 126 | "or" | ||
| 127 | "orelse" | ||
| 128 | ] @keyword.operator | ||
| 129 | |||
| 130 | [ | ||
| 131 | "return" | ||
| 132 | ] @keyword.return | ||
| 133 | |||
| 134 | [ | ||
| 135 | "if" | ||
| 136 | "else" | ||
| 137 | "switch" | ||
| 138 | ] @conditional | ||
| 139 | |||
| 140 | [ | ||
| 141 | "for" | ||
| 142 | "while" | ||
| 143 | "break" | ||
| 144 | "continue" | ||
| 145 | ] @keyword | ||
| 146 | |||
| 147 | [ | ||
| 148 | "usingnamespace" | ||
| 149 | ] @include | ||
| 150 | |||
| 151 | [ | ||
| 152 | "try" | ||
| 153 | "catch" | ||
| 154 | ] @keyword | ||
| 155 | |||
| 156 | [ | ||
| 157 | "anytype" | ||
| 158 | (BuildinTypeExpr) | ||
| 159 | ] @type.builtin | ||
| 160 | |||
| 161 | [ | ||
| 162 | "const" | ||
| 163 | "var" | ||
| 164 | "volatile" | ||
| 165 | "allowzero" | ||
| 166 | "noalias" | ||
| 167 | ] @type.qualifier | ||
| 168 | |||
| 169 | [ | ||
| 170 | "addrspace" | ||
| 171 | "align" | ||
| 172 | "callconv" | ||
| 173 | "linksection" | ||
| 174 | ] @storageclass | ||
| 175 | |||
| 176 | [ | ||
| 177 | "comptime" | ||
| 178 | "export" | ||
| 179 | "extern" | ||
| 180 | "inline" | ||
| 181 | "noinline" | ||
| 182 | "packed" | ||
| 183 | "pub" | ||
| 184 | "threadlocal" | ||
| 185 | ] @attribute | ||
| 186 | |||
| 187 | [ | ||
| 188 | "null" | ||
| 189 | "unreachable" | ||
| 190 | "undefined" | ||
| 191 | ] @constant.builtin | ||
| 192 | |||
| 193 | [ | ||
| 194 | (CompareOp) | ||
| 195 | (BitwiseOp) | ||
| 196 | (BitShiftOp) | ||
| 197 | (AdditionOp) | ||
| 198 | (AssignOp) | ||
| 199 | (MultiplyOp) | ||
| 200 | (PrefixOp) | ||
| 201 | "*" | ||
| 202 | "**" | ||
| 203 | "->" | ||
| 204 | ".?" | ||
| 205 | ".*" | ||
| 206 | "?" | ||
| 207 | ] @operator | ||
| 208 | |||
| 209 | [ | ||
| 210 | ";" | ||
| 211 | "." | ||
| 212 | "," | ||
| 213 | ":" | ||
| 214 | ] @punctuation.delimiter | ||
| 215 | |||
| 216 | [ | ||
| 217 | ".." | ||
| 218 | "..." | ||
| 219 | ] @punctuation.special | ||
| 220 | |||
| 221 | [ | ||
| 222 | "[" | ||
| 223 | "]" | ||
| 224 | "(" | ||
| 225 | ")" | ||
| 226 | "{" | ||
| 227 | "}" | ||
| 228 | (Payload "|") | ||
| 229 | (PtrPayload "|") | ||
| 230 | (PtrIndexPayload "|") | ||
| 231 | ] @punctuation.bracket | ||
| 232 | |||
| 233 | ; Error | ||
| 234 | (ERROR) @error | ||
| @@ -0,0 +1,22 @@ | |||
| 1 | [ | ||
| 2 | (Block) | ||
| 3 | (ContainerDecl) | ||
| 4 | (SwitchExpr) | ||
| 5 | (InitList) | ||
| 6 | ] @indent | ||
| 7 | |||
| 8 | [ | ||
| 9 | "(" | ||
| 10 | ")" | ||
| 11 | "[" | ||
| 12 | "]" | ||
| 13 | "{" | ||
| 14 | "}" | ||
| 15 | ] @branch | ||
| 16 | |||
| 17 | [ | ||
| 18 | (line_comment) | ||
| 19 | (container_doc_comment) | ||
| 20 | (doc_comment) | ||
| 21 | (LINESTRING) | ||
| 22 | ] @ignore | ||
| @@ -0,0 +1,5 @@ | |||
| 1 | [ | ||
| 2 | (container_doc_comment) | ||
| 3 | (doc_comment) | ||
| 4 | (line_comment) | ||
| 5 | ] @comment | ||