Lcl for Visual Studio Code
Syntax highlighting and editing support for
Lcl (Lexical Command Language), a
Tcl-inspired scripting language with lexical scoping.
Features
- Syntax highlighting for
.lcl files: comments and ;;; doc comments,
"..." templates with $var, ${qualified::name}, \-escapes and
nested [...] commands, strict numeric literals, (...) lists,
#{...} dicts, @ spread and ,/,, unquote markers, operators,
core builtins and special forms.
- Definitions:
proc/macro names and parameters (including
(name default) and *rest), lambda parameters, let/var/set!
and foreach bound names, namespace and import names.
- Editing:
;; comment toggling, bracket matching and auto-closing for
{} [] () "", indentation on {, [ and (, and a word
pattern that treats max-len and empty? as single words.
- Highlighting of
```lcl fenced blocks in Markdown.
Install
From the Marketplace or Open VSX, search for Lcl. To install from
source:
npm install
npm run package # produces vscode-lcl-<version>.vsix
code --install-extension vscode-lcl-*.vsix
To hack on it, open this folder in VS Code and press F5; the Extension
Development Host opens test/snapshot/examples.lcl.
How it relates to tree-sitter-lcl
VS Code colors files with TextMate grammars, not tree-sitter, so this
extension carries its own regex grammar in syntaxes/lcl.tmLanguage.json.
The grammar is generated by scripts/build-grammar.py from the word
rules of the Lcl reader, and its keyword, builtin and operator lists are
copied from queries/highlights.scm in
tree-sitter-lcl. When that
file changes, update the lists in the script and run:
npm run grammar:build
npm test
Emacs, Neovim, Helix and Zed use the tree-sitter grammar directly. When
an Lcl language server exists, it will plug into this same extension and
layer semantic tokens over the TextMate colors; the grammar and language
configuration stay as they are.
Known limitations
A regex grammar cannot run Lcl's speculative compile of every brace
word, so a few things are approximations:
- Every
{...} is colored as code. Lcl treats a brace word whose
contents cannot compile (regexes, shell snippets, {unmatched '['})
as an opaque literal. The grammar does follow Lcl's brace-depth rule
for the extent of a brace word: strings, brackets and parens inside
a block end at an unbalanced }, so an odd literal never derails the
rest of the file.
- The consequence of that rule: a
"..." string containing an
unbalanced } ends early, even at top level.
- Comments inside blocks end at an unbalanced
} (as in Lcl) but
otherwise run to end of line, so a ] inside a comment inside [...]
is not seen as closing the bracket.
- The first word on a continuation line inside
[...] is colored as a
command name.
Testing
npm test # scope assertions in test/unit, snapshot of test/snapshot
npm run test:snap:update # accept snapshot changes after a grammar edit
test/snapshot/examples.lcl is the syntax tour from tree-sitter-lcl; it
runs under lcl and parses cleanly with the tree-sitter grammar, so it
is the shared acceptance fixture for both projects.
License
MIT