# `.heml` editor support `.heml` authoring should feel like HTML first: keep normal HTML highlighting, formatting, tag matching, and tree-sitter queries, then layer hemx compiler feedback on top. The shared authority is `hemx-build` diagnostics plus `docs/hemplate-syntax.md`; editors must not carry separate parser rules for the hemplate language. req: diagnostics/004 req: diagnostics/005 ## Shared language service `hemx-lsp` owns editor protocol behavior; `hemx-xtask` stays a project workflow runner, not the language-service home. From the repo, run the stdio language service: ```sh cargo run -p hemx-lsp -- lsp ``` Or install the same binary and run it directly: ```sh cargo install --path hemx-lsp hemx-lsp lsp ``` It speaks standard LSP framing over stdin/stdout. Today it supports open/change/save text synchronization, compiler-backed `textDocument/publishDiagnostics`, and small completion/hover entries for documented `.heml` constructs from `docs/hemplate-syntax.md`. Generated targets discovered by `hemx-build` in an open document are offered as `ui::target` completions. For derive-known template contexts, `self.` field completion/hover and simple `h-for` locals such as `exercise in &self.plan` come from hemx-owned Rust struct facts, not an editor parser or rust-analyzer proxy. It intentionally does not format templates, parse JavaScript, parse arbitrary Rust expressions, or replace HTML tooling. For scripts and editor wrappers that only need one-shot diagnostics, run: ```sh cargo run -p hemx-lsp -- diagnostics path/to/file.heml ``` The one-shot command prints a JSON object shaped like LSP `textDocument/publishDiagnostics` parameters: ```json { "uri": "file:///absolute/path/to/file.heml", "diagnostics": [ { "range": { "start": { "line": 0, "character": 0 }, "end": { "line": 0, "character": 0 } }, "severity": 1, "source": "hemx-build", "code": "unkeyed-generated-target", "message": "data-hemx-slot=\"todo_row\" is inside h-for=\"todo in &self.todos\" without h-key", "data": { "directive": "data-hemx-slot", "target": "todo_row", "expected": "a stable template h-key on h-for=\"todo in &self.todos\" so generated keyed helpers such as ui::todo_row.replace(row) can target this partial", "repair": "add h-key=\"todo.id\" to that h-for; dynamic +data-key on the child is rendered HTML, not the template fact hemx uses for generated targets" } } ] } ``` The diagnostic payload comes from `hemx-build`; editor integrations should display it as-is instead of recreating the rule. ## Highlighting boundary Repo-owned `.heml` highlighting is an HTML overlay, not a new language. Normal HTML highlighting owns tags, attributes, strings, comments, folding, and tag matching. The hemplate overlay may highlight only documented syntax tokens from `docs/hemplate-syntax.md`: - escaped text delimiters and expression regions: `{+` and `+}`; - trusted/rendered HTML delimiters and expression regions: `{+=` and `=+}`; - dynamic attribute prefixes such as `+class`, `+disabled`, and `+aria-label`; - structural directives: `h-if`, `h-for`, `h-key`, `h-match`, and `h-case`; - hemx facts recorded as ordinary attributes: `data-hemx-root`, `data-hemx-slot`, `data-hemx-form`, `data-hemx-handle`, and other checked `data-hemx-*` authoring attributes. Highlighting must not own diagnostics, completion, hover, formatting, Rust expression parsing, selector behavior, generated Rust facts, or build validation. Those remain with `hemx-build`, `hemx-lsp`, normal HTML tooling, and Rust tooling. Repo tests for highlighting should therefore be fixture/query tests for captures over these token classes; provider packaging or visual editor smoke is a separate release slice and cannot become syntax authority. The current repo-owned fixture and golden capture contract live in `docs/fixtures/hemplate-highlighting/`. req: diagnostics/004 req: diagnostics/008 ## VS Code and Cursor Use the shared repo extension in `editors/vscode-hemx` for VS Code and Cursor. It sets `.heml` to the built-in HTML language mode, starts `hemx-lsp`, and maps LSP diagnostics/completion/hover into the editor without adding a separate grammar. Hovering a generated root, slot, form, or handle value reports its resource kind and generated `ui::` Rust symbol from the current template. req: diagnostics/005 req: diag/010 When the workspace root is this repository, the extension starts: ```sh cargo run -p hemx-lsp -- lsp ``` In app workspaces, install `hemx-lsp` and the extension starts: ```sh hemx-lsp lsp ``` If you do not use the extension, keep the same HTML association manually so HTML syntax highlighting, completion, folding, and tag matching keep working: ```json { "files.associations": { "*.heml": "html" } } ``` Use the one-shot diagnostics command only as a fallback task if your editor cannot launch a stdio LSP server. Do not copy hemplate syntax into a VS Code/Cursor-only grammar. ## Neovim Use HTML filetype and tree-sitter HTML highlighting for `.heml`: ```lua vim.filetype.add({ extension = { heml = "html" } }) ``` If you use nvim-treesitter, this keeps `.heml` on the HTML parser. Start the shared LSP service with Neovim's built-in client: ```lua vim.lsp.start({ name = "hemx-heml", cmd = { "cargo", "run", "-p", "hemx-lsp", "--", "lsp" }, root_dir = vim.fs.root(0, { "Cargo.toml", ".git" }) or vim.fn.getcwd(), }) ``` Use `cargo run -p hemx-lsp -- diagnostics %` only as a fallback if LSP is unavailable. Do not add a separate `.heml` tree-sitter grammar unless HTML injection can no longer represent the documented syntax in `docs/hemplate-syntax.md`. ## Known limits and boundary If `hemx-lsp` is missing, crashes, or cannot be started by the editor, `.heml` files should still open as HTML and keep normal highlighting/tag tooling; use the one-shot diagnostics command until the service is available. This foundation intentionally supports diagnostics, completion, and hover/help. It does not yet implement broad go-to-definition/reference navigation, formatting, refactoring, semantic Rust analysis, arbitrary Rust expression parsing, or a `.heml` tree-sitter parser fork. Editor support may add startup glue, diagnostics display, completion, hover/help, and navigation over documented `.heml` facts. It must not add a second template language, editor-owned formatter, selector targeting model, JavaScript expression layer, or editor-specific diagnostics that disagree with `hemx-build`.