.\" lime-lsp.1 - manual page for the Lime Language Server .\" Copyright (c) 2024-2026 Lime Parser Generator Project .\" Public Domain .\" .TH LIME-LSP 1 "May 2026" "Lime 0.5.7" "User Commands" .SH NAME lime-lsp \- Language Server Protocol server for Lime grammar files .SH SYNOPSIS .B lime-lsp .RI [ options ] .SH DESCRIPTION .B lime-lsp is a Language Server Protocol (LSP) server for .B .lime grammar files. It speaks LSP 3.17 (subset) over standard input/output framed with HTTP-style .B Content-Length headers. The server is a separate binary from the .BR lime (1) parser generator: for live diagnostics it .BR fork (2)/ exec (3)s .B lime -L on a temporary copy of the open document; for navigation features (go-to-definition, hover, document outline) it runs an in-process tokenizer. .PP .B lime-lsp takes no positional arguments and reads / writes JSON-RPC 2.0 on stdio only. There is no daemon mode and no socket transport; editor integrations spawn the server as a child process per workspace. .PP v0.5.0 ships LSP "Phase 1": single-document scope, full-text sync, diagnostics, definition, hover, document symbol. v0.5.7 adds completion, references, rename (with prepareRename), and semantic tokens \(em the four capabilities the v0.5.0 man page explicitly listed as deferred. See .B docs/LSP.md for the implementation guide and .B editors/lime-lsp-config.md for editor wire-up recipes (eglot, lsp-mode, Neovim .BR lspconfig , VS Code). .SH OPTIONS .TP .BI \-\-lime " path" Path to the .BR lime (1) binary used for diagnostics. Overrides .B $LIME_BIN and the .B PATH search. .TP .B \-\-version Print the LSP server version (matches .BR LIME_VERSION_STRING ) and exit. .SH "ADVERTISED CAPABILITIES" The .B ServerCapabilities object returned at .B initialize time is the authoritative list of supported features: .PP .RS .EX { "textDocumentSync": { "openClose": true, "change": 1, "save": true }, "definitionProvider": true, "hoverProvider": true, "documentSymbolProvider": true, "referencesProvider": true, "completionProvider": { "triggerCharacters": ["%", " ", "."] }, "renameProvider": { "prepareProvider": true }, "semanticTokensProvider": { "legend": { "tokenTypes": ["keyword", "namespace", "class", "variable", "function", "string", "number", "comment", "operator", "type", "macro", "label"], "tokenModifiers": ["definition", "deprecated"] }, "full": true } } .EE .RE .PP .B "change: 1" is .B TextDocumentSyncKind.Full -- the client sends the full buffer text on every .BR didChange ; incremental sync is deferred. .PP Per-method status: .TP .B initialize / initialized / shutdown / exit Standard lifecycle. The server returns .B serverInfo.version populated from .BR LIME_VERSION_STRING . .TP .B textDocument/didOpen, didChange, didSave, didClose Maintain the per-document buffer state and push diagnostics on each event; .B didClose publishes an empty diagnostic array to clear stale markers. .TP .B textDocument/publishDiagnostics Server-to-client notification. For each open document, parsed .B lime -L output (lint and parser-stage messages) becomes an LSP .BR Diagnostic ; severity maps: .B error \(rA 1, .B warning \(rA 2, .B note / info \(rA 3, .B hint \(rA 4. .TP .B textDocument/definition Jump from a non-terminal RHS reference to its LHS-defining rule, or from a terminal use to the .B %token declaration site. .TP .B textDocument/hover Return either a one-line directive description (covering .BR %name , .BR %token , .BR %type , .BR %extra_argument , .BR %extends , .BR %dialect , .BR %embed , .BR %locations , and the rest of the directive surface), or a symbol summary (kind, declaring line, usage count). .TP .B textDocument/documentSymbol Flat outline of every directive, terminal, and non-terminal in the document, in declaration order with kinds .B Key (directive), .B Constant (terminal), .B Function (non-terminal). .TP .B textDocument/completion Context-aware suggestions. Three modes: directive context (cursor on or just after a leading .B % at the start of a line) emits the full curated list of recognized directives; RHS context (cursor inside a rule, after .B ::= before the terminating .BR . ) emits every terminal + non-terminal known to the open document, prefix-filtered; token-list context (cursor inside a .B %token / .B %left / .B %right / .B %nonassoc / .B %type / .B %fallback / .B %wildcard statement) emits terminals. Trigger characters .RB ( % , space, .BR . ) are advertised in .BR completionProvider.triggerCharacters . Directive list is hard-coded in .B src/lsp/lsp_navigation.c::kDirectiveDocs , shared with the hover handler; v0.5.8+ may parse it from .BR lime_grammar (5). .TP .B textDocument/references Resolves the symbol under the cursor and returns one .B Location per occurrence (definition + every reference site). The .B context.includeDeclaration flag toggles inclusion of definition sites; pass .B false to get use-only references. Cross-document propagation across .B %extends / .B %import is a v0.5.8+ follow-up; v0.5.7 is single-document. .TP .B textDocument/prepareRename Validates that the cursor sits on a renameable symbol (a terminal or non-terminal whose definition is in the open document). Returns .B { range, placeholder } on success and .B null on a non-renameable position (directive, comment, whitespace, unknown identifier). The editor surfaces null as a non-modal status message, not an error popup, per LSP convention. .TP .B textDocument/rename Returns a .B WorkspaceEdit .RB ( changes : URI \(rA TextEdit[]) replacing every occurrence with .BR newName . Validation: .B newName must match .BR [A-Za-z_][A-Za-z0-9_]* ; must not collide with an existing symbol of a different kind; must not match an existing .BR % -directive name. A validation failure returns JSON-RPC error .B \-32602 so the editor surfaces the reason verbatim. Multi-file rename across .B %extends is a v0.5.8+ follow-up. .TP .B textDocument/semanticTokens/full Returns a SemanticTokens object .RB ( { data: .RI [ deltaLine , .IR deltaStart , .IR length , .IR tokenType , .IR tokenMods ]* .BR } ) encoding every classified lexical token in the document, in source order, using the legend advertised at .BR initialize . Legend (12 token types): .B keyword (directive), .B namespace .RB ( %dialect / .B %extends / .B %import argument), .B class (terminal), .B variable (non-terminal), .B function (reserved), .B string .RB ( "..." / .BR '...' ), .B number (decimal literal), .B comment (block + line), .B operator .RB ( ::= / .B | / .B . / .B , / .B ; / .B ( / .B ) / .B [ / .B ] / .B { / .BR } ), .B type , .B macro , .B label (reserved for v0.5.8+). Modifiers .RB ( definition , .BR deprecated ) are reserved; v0.5.7 always emits zero. .PP The following methods are advertised as .B unsupported and are intentionally deferred: .B textDocument/codeAction , .B workspace/symbol . .B codeAction pairs with the linter's auto-fix surface, which has not yet been wired. .SH "ENVIRONMENT" .TP .B LIME_BIN Path to the .B lime binary used for diagnostics. Searched in this order: .B \-\-lime argument, .BR LIME_BIN , literal .B lime on .BR PATH . .TP .B TMPDIR Used for the temporary file that holds the open document while .B lime -L runs against it. Falls back to .B /tmp when unset. .SH "EXIT STATUS" .TP .B 0 Clean shutdown via the LSP .B shutdown \(rA .B exit sequence. .TP .B 1 LSP protocol violation, malformed JSON-RPC frame, or fatal I/O error on stdio. .TP .B 2 Argument-parsing failure. .SH "PROCESS MODEL" .RS .EX editor <-- JSON-RPC 2.0 over stdio --> lime-lsp | +--> fork+exec lime -L /tmp/.lime | (per didOpen / didChange / | didSave; output piped back | and parsed line-by-line) | +--> in-process tokenizer (definition, hover, documentSymbol; ~250 LOC) .EE .RE .PP The LSP target is intentionally decoupled from the Lime parser runtime: it does .I not link .B lime_parser_lib and does .I not include any header that would force a recompile when the parser internals change. Every byte the LSP ships lives in .BR src/lsp/ . .SH "WIRE FORMAT" JSON-RPC 2.0 framed with HTTP-style headers: .PP .RS .EX Content-Length: \\r\\n \\r\\n .EE .RE .PP The bundled JSON parser (\fBsrc/lsp/lsp_json.[ch]\fP) is hand-rolled in ~600 lines and handles UTF-16 surrogate pairs in .B \\uXXXX escapes; no external JSON dependency is linked. .SH "LIMITATIONS" .IP \(bu 2 Single document at a time. Definition / hover / outline / references / rename do not cross .B %extends or .B %import file boundaries; v0.5.8+ wires the cross-document grammar model. .IP \(bu 2 Full-text sync only (no incremental). .IP \(bu 2 No code actions or workspace symbol search. .IP \(bu 2 POSIX-only. The diagnostics path requires .BR fork (2), .BR execvp (3), and .BR pipe (2). On Windows, run the server inside WSL. A native Win32 implementation is future work. .SH "SEE ALSO" .BR lime (1), .BR lime_grammar (5), .BR lime_lex (5) .PP .B docs/LSP.md -- implementation guide and capability reference. .br .B editors/lime-lsp-config.md -- editor wire-up recipes. .br .B docs/LSP_DESIGN.md -- original (v0.2.x) design sketch (Phase 1 of which landed in v0.5.0). .SH AUTHORS The Lemon parser generator was originally written by D. Richard Hipp for the SQLite project. Lime is an extended version of Lemon with support for modular grammars, runtime extensions, and additional code generation features. .B lime-lsp is the v0.5.0 Language Server companion. .SH LICENSE Public Domain. .SH BUGS Report bugs at: .UR https://codeberg.org/gregburd/lime/issues .UE