From 0c43468dc0b13c7f30bd084210b2ed1fd94b564c Mon Sep 17 00:00:00 2001 From: Luke Boswell Date: Sat, 17 Jan 2026 21:50:42 +1100 Subject: [PATCH 1/2] Use new experimental LSP integrated into roc CLI Switch from the standalone `roc_language_server` binary to the new LSP invoked via `roc experimental-lsp`. This is the new Zig-based LSP implementation integrated directly into the main roc binary. Co-Authored-By: Claude Opus 4.5 --- README.md | 10 +++++----- src/lib.rs | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index d4083a6..fd87bd3 100644 --- a/README.md +++ b/README.md @@ -5,17 +5,17 @@ An extension for Zed that adds Roc language support: - syntax highlighting through treesitter and - type tooltips, error marker, completion ... through the roc language server -## Preqrequisites +## Prerequisites -- install roc from the [roc-lang](https://roc-lang.org) website -- add roc and roc_language_server to your PATH -- install Zed from the [Zed](https://zed.dev) website +- Install Roc from the [roc-lang](https://roc-lang.org) website +- Ensure the `roc` binary is in your PATH +- Install Zed from the [Zed](https://zed.dev) website ## ROC - Website: [roc-lang.org](https://roc-lang.org) - Tree Sitter: [tree-sitter-roc](https://github.com/faldor20/tree-sitter-roc) -- Language Server: [roc-language-server](https://github.com/roc-lang/roc/tree/main) included in nightly builds of the ROC compiler e.g. https://github.com/roc-lang/roc/releases/download/nightly/roc_nightly-macos_apple_silicon-latest.tar.gz, the roc_language_server binary should be included in PATH. +- Language Server: This extension uses the new experimental LSP integrated into the `roc` CLI via `roc experimental-lsp`. ## Development diff --git a/src/lib.rs b/src/lib.rs index 87edd15..14f24ed 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -12,14 +12,14 @@ impl zed::Extension for RocExtension { _config: &zed::LanguageServerId, worktree: &zed::Worktree, ) -> Result { - let binary_name = "roc_language_server"; + let binary_name = "roc"; let path = worktree .which(binary_name) .ok_or_else(|| format!("{binary_name} executable not found in $PATH"))?; Ok(zed::Command { command: path, - args: vec![], + args: vec!["experimental-lsp".to_string()], env: Default::default(), }) } From 7bc29683c3b8c0b621dc7e0939f22f78b2823428 Mon Sep 17 00:00:00 2001 From: Luke Boswell Date: Sun, 18 Jan 2026 19:53:29 +1100 Subject: [PATCH 2/2] Update tree-sitter grammar and improve dev workflow - Update grammar to lukewilliamboswell/tree-sitter-roc@80b6bbe (modern-roc-syntax) - Add languages = ["languages/roc"] to extension.toml (required for Zed) - Sync query files (highlights, locals, textobjects) with new grammar - Expand README with development instructions and troubleshooting - Add note that branch is not ready to merge until upstream tree-sitter lands - Simplify justfile with useful dev commands - Bump version to 0.1.0 Co-Authored-By: Claude Opus 4.5 --- README.md | 73 +++++++++++++++++++++++++++++++++-- extension.toml | 7 ++-- justfile | 22 ++++++----- languages/roc/highlights.scm | 30 +++++++------- languages/roc/locals.scm | 4 +- languages/roc/textobjects.scm | 2 +- 6 files changed, 103 insertions(+), 35 deletions(-) diff --git a/README.md b/README.md index fd87bd3..e757932 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # Roc lang support for Zed +> **Note:** This branch (`use-new-roc-lsp`) uses a fork of tree-sitter-roc with modern Roc syntax support. It is not ready to merge until the changes land upstream at [faldor20/tree-sitter-roc](https://github.com/faldor20/tree-sitter-roc). + An extension for Zed that adds Roc language support: - syntax highlighting through treesitter and @@ -14,14 +16,79 @@ An extension for Zed that adds Roc language support: ## ROC - Website: [roc-lang.org](https://roc-lang.org) -- Tree Sitter: [tree-sitter-roc](https://github.com/faldor20/tree-sitter-roc) +- Tree Sitter: [tree-sitter-roc](https://github.com/lukewilliamboswell/tree-sitter-roc) - Language Server: This extension uses the new experimental LSP integrated into the `roc` CLI via `roc experimental-lsp`. ## Development +### Installing the Dev Extension + +1. Open Zed's command palette (Cmd+Shift+P / Ctrl+Shift+P) +2. Run "zed: install dev extension" +3. Select this repository folder +4. Click "Rebuild" if prompted + +**Note:** The version shown in Zed's Extensions panel may display the marketplace version (e.g., v0.0.6) even when the dev extension is active. This is a Zed caching behavior when the extension ID matches a marketplace extension. + +### Verifying the Dev Extension is Running + +Check Zed's logs (Command palette → "zed: open log file") and look for: +``` +compiling Rust extension /path/to/your/zed-roc +``` + +If the path points to your local repository (not `~/Library/Application Support/Zed/extensions/installed/roc`), the dev extension is active. + +### Key Files + +- `extension.toml` - Extension manifest (id, version, grammar source, language config) +- `languages/roc/config.toml` - Language configuration (file extensions, comments, brackets) +- `languages/roc/*.scm` - Tree-sitter queries (highlights, indents, etc.) +- `grammars/roc/` - Git clone of tree-sitter-roc (must match repository in extension.toml) + +### Updating the Tree-sitter Grammar + +The `grammars/roc/` directory must be a git clone of the repository specified in `extension.toml`. To update: + +1. Update the commit hash in `extension.toml` under `[grammars.roc]` +2. Update the grammar submodule: + ```sh + cd grammars/roc + git fetch origin + git checkout + ``` +3. Sync query files: `cp grammars/roc/queries/*.scm languages/roc/` +4. Delete cached wasm to force recompilation: `rm grammars/roc.wasm` +5. In Zed, click "Rebuild" on the extension + +### Troubleshooting + +**Extension not detecting .roc files:** +- Check Zed logs for errors (Command palette → "zed: open log file") +- Ensure `languages = ["languages/roc"]` is in `extension.toml` + +**Conflict with marketplace version:** +- Uninstall the marketplace Roc extension first +- If uninstall doesn't work, quit Zed and manually edit the extensions index.json to remove "roc" entries +- Zed stores extensions in: + - macOS: `~/Library/Application Support/Zed/extensions/` + - Linux: `~/.local/share/zed/extensions/` + +**Grammar compilation errors:** +- Ensure `grammars/roc/` is a git clone of the repository URL in `extension.toml` +- The git remote origin must match the repository URL exactly + +### Useful Commands + ```sh -~/Library/Application\ Support/Zed/extensions/installed/ -less ~/Library/Logs/Zed/Zed.log +# Sync query files from grammar to languages +cp grammars/roc/queries/*.scm languages/roc/ + +# Clean build artifacts +rm -f grammars/roc.wasm extension.wasm + +# Check Zed logs (macOS) +tail -f ~/Library/Logs/Zed/Zed.log | grep -i roc ``` ![Zed Example](https://github.com/h2000/zed-roc/assets/187650/1ec0cda3-3679-4223-bc5e-3272babde364) diff --git a/extension.toml b/extension.toml index 5c3551b..5d1a38e 100644 --- a/extension.toml +++ b/extension.toml @@ -1,14 +1,15 @@ id = "roc" name = "Roc" description = "Roc language support for Zed" -version = "0.0.6" +version = "0.1.0" schema_version = 1 authors = ["Alf Richter "] repository = "https://github.com/h2000/zed-roc" +languages = ["languages/roc"] [grammars.roc] -repository = "https://github.com/faldor20/tree-sitter-roc" -commit = "6ea64b6434a45472bd87b0772fd84a017de0a557" +repository = "https://github.com/lukewilliamboswell/tree-sitter-roc" +commit = "80b6bbe1bab45396db0943db410b97e6f4579801" [language_servers.roc] language = "Roc" diff --git a/justfile b/justfile index 286f545..700ef11 100644 --- a/justfile +++ b/justfile @@ -1,11 +1,15 @@ -update-tree-sitter: - -rm languages/roc/*.scm - cd ../tree-sitter-roc && git pullr - cp -v ../tree-sitter-roc/queries/*.scm languages/roc +# Sync query files from tree-sitter-roc to languages/roc +sync-queries: + cp -v grammars/roc/queries/*.scm languages/roc/ -clean: - -rm -rf grammars - -rm -f extension.wasm +# Update grammar to a specific commit and sync queries +update-grammar COMMIT: + cd grammars/roc && git fetch origin && git checkout {{COMMIT}} + just sync-queries + rm -f grammars/roc.wasm + @echo "Done. Click 'Rebuild' in Zed to recompile the grammar." -update-extension: - cd ../zed-roc-extensions && git pullr && cd extensions/roc && git pullr +# Clean build artifacts +clean: + rm -f grammars/roc.wasm + rm -f extension.wasm diff --git a/languages/roc/highlights.scm b/languages/roc/highlights.scm index 53c8787..44c4d97 100644 --- a/languages/roc/highlights.scm +++ b/languages/roc/highlights.scm @@ -10,8 +10,9 @@ ;; opinion: typedefs cross into documentation and should be ;; highlighted differently from normal code -(opaque_type_def (_ (concrete_type) @type.definition)) +(nominal_type_def (_ (concrete_type) @type.definition)) (function_type (arrow) @punctuation.delimiter.structural.typedef) +(function_type (effect_arrow) @punctuation.delimiter.structural.typedef) (parenthesized_type ["(" ")"] @punctuation.bracket.typedef) (tuple_type ["(" ")"] @punctuation.bracket.typedef) @@ -24,14 +25,8 @@ (record_field_type ":" @punctuation.delimiter.typedef) (record_field_type (field_name) @variable.other.enum.typedef) -(ability_chain "&" @operator.typedef) - -(where_implements _ - (where) @type.keyword - (identifier) @type.parameter - (implements) @type.keyword - (ability_chain) @type.parameter) - +(where_clause + (where) @type.keyword) ((concrete_type) @type.builtin (#match? @type.builtin "^(Bool|Str|Num|List|Result|Dict|Set|Dec)")) @@ -50,8 +45,10 @@ "?" (arrow) (back_arrow) -(backslash) ] @punctuation.delimiter.structural + +; Lambda pipes +(anon_fun_expr "|" @punctuation.delimiter.structural) (bang_expr "!" @punctuation.delimiter.structural) [ "," @@ -79,18 +76,18 @@ [ "if" - "then" "else" ] @keyword.control.conditional [ -(implements) -(when) -(is) +"match" "as" (to) ] @keyword.control.roc +; Match expression fat arrow +(match_branch "=>" @punctuation.delimiter.structural) + ;----headers----- [ @@ -154,8 +151,6 @@ (function_call_expr caller: (field_access_expr (identifier)@function .)) -(bin_op_expr (operator "|>")@operator(variable_expr(identifier)@function)) - ;----function arguments---- (argument_patterns(identifier_pattern @@ -167,7 +162,7 @@ (argument_patterns(_(_(_(_(_(identifier_pattern(identifier)@variable.parameter))))))) ; pattern captures -(when_is_branch pattern: (_ (identifier_pattern (identifier) @variable.parameter))) +(match_branch pattern: (_ (identifier_pattern (identifier) @variable.parameter))) (range_pattern (identifier) @variable.parameter) @@ -200,6 +195,7 @@ (string)@string (multiline_string)@string +(line_string)@string (char) @constant.character (escape_char)@constant.character.escape diff --git a/languages/roc/locals.scm b/languages/roc/locals.scm index 4d25923..5027cee 100644 --- a/languages/roc/locals.scm +++ b/languages/roc/locals.scm @@ -20,10 +20,10 @@ (exposes_list(ident)@local.reference) (import_expr(as)(module)@local.definition) -(opaque_type_def(apply_type(concrete_type)@local.definition)) +(nominal_type_def(apply_type(concrete_type)@local.definition)) (alias_type_def(apply_type(concrete_type)@local.definition)) -(when_is_branch pattern: (_ (identifier_pattern (identifier) @local.definition))) +(match_branch pattern: (_ (identifier_pattern (identifier) @local.definition))) (range_pattern (identifier) @local.definition) (identifier)@local.reference diff --git a/languages/roc/textobjects.scm b/languages/roc/textobjects.scm index 0e053f7..a2b729a 100644 --- a/languages/roc/textobjects.scm +++ b/languages/roc/textobjects.scm @@ -24,7 +24,7 @@ [ (annotation_type_def ) @class.inside (alias_type_def ) @class.inside - (opaque_type_def ) @class.inside + (nominal_type_def ) @class.inside ] @class.around (apply_type_arg) @parameter.inside