hjkl-bonsai
Tree-sitter syntax highlighting for the hjkl editor stack — runtime grammar loading, no baked-in languages.
Renamed from
hjkl-tree-sitter(the old crate stays as a deprecated 0.5.0 artifact on crates.io). New releases ship underhjkl-bonsai.
bonsai ships a manifest of 421 languages (sourced from helix +
nvim-treesitter) and resolves grammars at runtime through a chain of:
- System — distro-shipped
.sounder/usr/share/bonsai/grammars/(or/usr/local/share/bonsai/grammars/). - User —
.sopreviously installed under<user_data>/bonsai/grammars/. - On-demand — clone the upstream repo, compile with
cc/c++, and install the result into the user dir for next time.
A <name>.rev sidecar tracks <git_rev>:abi<N>, so a manifest bump or a
tree-sitter ABI change recompiles in place automatically.
The release rlib is ~720 KB because no grammars are baked in. The first edit
of an unknown language pays a one-time clone+compile cost; everything after that
is a dlopen.
API
GrammarLoader::load is synchronous and suitable for blocking contexts (xtask,
CLI one-shots, tests). For TUI/GUI event loops that cannot block 1–3 s on a
first-ever clone+compile, wrap the loader in AsyncGrammarLoader from
runtime::async_loader — it dispatches to a 2-worker pool and automatically
deduplicates concurrent requests for the same grammar name.
Usage
= "0.3"
use Arc;
use ;
use ;
// 1. Load the embedded manifest + standard XDG-everywhere loader.
let registry = embedded?;
let loader = user_default?;
// 2. Resolve a language by name (or path → registry.name_for_path).
let spec = registry.by_name.expect;
let grammar = new;
// 3. Highlight.
let mut highlighter = new?;
let spans = highlighter.highlight;
let theme = dark;
for span in &spans
# Ok::
Distro packagers
The runtime layout bonsai looks for is:
<prefix>/bonsai/grammars/<name>.so
<prefix>/bonsai/grammars/<name>.scm
To pre-build the full set against the current manifest:
System-shipped grammars are not rev-checked at runtime — the packager owns that lifecycle.
On-disk layout
/usr/share/bonsai/grammars/ # 1st lookup (system)
/usr/local/share/bonsai/grammars/ # 2nd lookup (system)
<user_data>/bonsai/grammars/ # 3rd lookup + install target
rust.so rust.scm rust.rev
python.so python.scm python.rev
<user_cache>/bonsai/grammars/ # source clones, transient
rust-e86119bdb496/
python-710796b8b877/
<user_data> and <user_cache> follow XDG-everywhere — same paths on every
platform:
| Variable | Default |
|---|---|
$XDG_DATA_HOME |
~/.local/share |
$XDG_CACHE_HOME |
~/.cache |
macOS and Windows do not get their platform-native dirs
(~/Library/Application Support, %APPDATA%). bonsai stores its grammar cache
uniformly across platforms so a ~/.local/share/bonsai/ checkout looks
identical everywhere. The resolver is self-contained — no hjkl-config or other
umbrella deps.
License
MIT. See LICENSE.