Skip to main content

Module plugin_lang

Module plugin_lang 

Source
Expand description

Languages registered at runtime rather than compiled in.

Design: plugin-languages.md §2.3. Slice plan: LG.2.

Lang is a closed enum, and every language lattice supports is a workspace dependency. This module is the other half: a registry a plugin contributes to at load and is withdrawn from at unload, so “which languages exist” stops being a compile-time property of the editor (paramount goal #2).

§Why the name is the id

LanguageName is a Copy newtype over a &'static str, not an index into a table. Two things fall out of that, and both were the reason for choosing it:

  • Lang::name() stays a field read. It is the key every query lookup already uses — registry.highlights_query(lang.name()), six times per highlight invocation, plus folds and indents. An index would have put a process-global table read inside it (paramount goal #1).
  • LangRegistry is already keyed by &'static str. A plugin language joins the map native languages live in, under its own name, rather than needing a parallel index space.

The name is leaked, once per distinct name — LanguageName::intern dedupes, so a plugin reloaded fifty times in a dev session leaks one string, not fifty. A leaked name also means a buffer still holding Lang::Plugin(name) after its plugin unloads keeps naming itself correctly; it simply finds no grammar and renders as plain text. Nothing dangles, and there is no kind-branch anywhere to express it.

§Why reads are process-global

Writes go through an RCU handle with teardown by provenance, exactly as contributable-registries.md prescribes. Reads do not take a handle, because Lang::detect_from_path is a free function with nineteen call sites across lattice-host, lattice-magit and lattice-multibuffer. Threading a handle through them would make plugin languages visible on some paths and invisible on others — a two-tier language concept, and the same failure the “no kind-specific logic” rule forbids for buffers. Lang::Plugin must be interpretable wherever Lang::Rust is, by the same code. LangRegistry::standard is already a process-wide memo in this crate for a related reason.

Structs§

LanguageName
The name of a language, interned so it outlives every buffer that refers to it. Doubles as the language’s identity: Lang::Plugin carries one, and it is the key into crate::LangRegistry.
LanguageRegistration
One plugin-contributed language.
PluginLanguages
The set of runtime-registered languages.

Enums§

LanguageRegistrationError
Why a registration was refused. Every variant names the offending language, because a plugin author reading a log line needs to know which of their contributions failed — and per LG.3’s error rule a failed language must not take the plugin’s other contributions with it.

Functions§

handle
The process-wide handle. See the module docs for why reads do not take one explicitly.
register
Register a language.
register_with_grammar
Register a language with its grammar and queries (LG.3a).
register_with_grammar_themed
register_with_grammar, with the theme registry in hand (TK.1).
resolve_extension
Resolve a file extension to a plugin language.
snapshot
Snapshot the live set. Wait-free; callers hold the Arc for as long as they need a coherent view.
unregister_plugin
Withdraw every language contributed by provenance, returning how many were removed.

Type Aliases§

PluginLanguagesHandle
Copy-on-write RCU, the idiom contributable-registries.md §2 establishes and the tree already carries five times over.