Unified · Split
| @@ -8716,6 +8716,15 @@ dependencies = [ · 8715 unmodified lines | ||
| 8716 | 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 | 8728 | [[package]] |
| 8720 | 8729 | name = "try-lock" |
| 8721 | 8730 | version = "0.2.4" |
| @@ -9812,6 +9821,7 @@ dependencies = [ · 1090 unmodified lines | ||
| 9812 | 9821 | "tree-sitter-uiua", |
| 9813 | 9822 | "tree-sitter-vue", |
| 9814 | 9823 | "tree-sitter-yaml", |
| 9824 | + "tree-sitter-zig", | |
| 9815 | 9825 | "unindent", |
| 9816 | 9826 | "url", |
| 9817 | 9827 | "urlencoding", |
| @@ -161,6 +161,7 @@ tree-sitter-nix = { git = "https://github.com/nix-community/tree-sitter-nix", re · 160 unmodified lines | ||
| 161 | 161 | tree-sitter-nu = { git = "https://github.com/nushell/tree-sitter-nu", rev = "26bbaecda0039df4067861ab38ea8ea169f7f5aa"} |
| 162 | 162 | tree-sitter-vue = {git = "https://github.com/zed-industries/tree-sitter-vue", rev = "6608d9d60c386f19d80af7d8132322fa11199c42"} |
| 163 | 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 | 166 | [patch.crates-io] |
| 166 | 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 | 142 | tree-sitter-nu.workspace = true |
| 143 | 143 | tree-sitter-vue.workspace = true |
| 144 | 144 | tree-sitter-uiua.workspace = true |
| 145 | +tree-sitter-zig.workspace = true | |
| 145 | 146 | |
| 146 | 147 | url = "2.2" |
| 147 | 148 | urlencoding = "2.1.2" |
| @@ -31,6 +31,7 @@ mod typescript; · 30 unmodified lines | ||
| 31 | 31 | mod uiua; |
| 32 | 32 | mod vue; |
| 33 | 33 | mod yaml; |
| 34 | +mod zig; | |
| 34 | 35 | |
| 35 | 36 | // 1. Add tree-sitter-{language} parser to zed crate |
| 36 | 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 | 113 | tree_sitter_go::language(), |
| 113 | 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 | 121 | language( |
| 116 | 122 | "heex", |
| 117 | 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 | |