LSP & Environment Awareness
The formatter stays hermetic—its output is a pure function of the input plus shipped data (see Non-goals). The language server is allowed more latitude: it may look past the document’s directory into the installed TeX tree, because navigation is inherently about the local environment. This page covers that sanctioned, LSP-only environment awareness, and the LSP technology choice.
Why lsp-server, not tower-lsp
The LSP is built on lsp-server + lsp-types (rust-analyzer’s stack), not
tower-lsp-server. salsa cancellation is a synchronous unwind (salsa::Cancelled)
that composes with lsp-server’s sync main loop plus threadpool, and fights
tower-lsp’s async &self model. text/line_index.rs uses lsp_types::Position.
Environment awareness
Two tiers of environment awareness, both reading static facts only (no macro meaning, no typesetting):
1. Shipped static CTAN metadata
data/package_metadata.json (generated by scripts/gen_package_names.py from the
pinned tlpdb) is a stem → {desc, ctan} map, with the same read-only posture as the
name lists and CWL. It drives package hover and completion detail
(semantic::signature::package_metadata).
2. A read-only TEXMF file index
project::texmf indexes the installed .sty/.cls/.dtx files, discovered by
delegating root discovery to kpsewhich -var-value (reimplementing kpathsea’s
texmf.cnf resolution is out of scope, and MiKTeX doesn’t use it) and enumerating via
ls-R/walk. It is cached to the OS cache dir keyed by a distro fingerprint—a lazy
process-global (first config wins). It powers document links, go-to-definition, and
installed-set completion for system packages.
3. The compile’s .aux artifacts
project::aux is a dedicated line-oriented scanner (never the LaTeX parser—aux files
are written under \makeatletter, so \@input/\@writefile would mis-lex). It
extracts \newlabel numbers and \@writefile{toc} entries, following \@input
per-chapter chains. Freshness is a per-file (mtime, len)-keyed process cache—a
recompile is picked up on the next request, no watcher. Aux files are located per
label namespace (sibling .aux, or [build] aux-dir for out-of-tree builds;
latexmkrc/Tectonic auto-detection is deferred). This powers label hover (Figure 3: A chart) and document-symbol number enrichment (1.2 Intro; toc titles are matched
whitespace-normalized, consumed in document order). Guarded by
format_never_reads_the_aux_file (tests/format_packages.rs).
The distinction
A runtime distro query feeding the formatter stays a non-goal—it would break the formatter’s hermeticism. A read-only index or metadata feeding LSP navigation is sanctioned.
The index is gated by the texmf editor settings (enabled/roots/useKpsewhich,
supplied as initializationOptions or via didChangeConfiguration—machine config,
so it lives in the editor, not badness.toml; project::texmf::TexmfConfig) and is
never wired into scope_signatures/DiskPackageSource (guarded by
formatter_scope_never_reaches_the_texmf_tree).