Skip to main content

Module locals

Module locals 

Source
Expand description

Buffer-local mode-internal state — Shape A from mode-architecture.md §9.4 (M.3.2.a).

A typed analogue of emacs’s buffer-local-variables. Each piece of mode-internal data declares an OptionDecl-style type identity via the BufferLocal trait; the typed-map BufferLocals stores them keyed by TypeId for O(1) type-keyed reads. Each entry carries metadata (display name, doc, owner mode) so :describe-buffer can enumerate every local a buffer carries grouped by its owning mode.

§Distinction from options

Buffer-locals are runtime data the mode owns, not user- configurable values. They store opaque Rust structs (SyntaxHandle, Vec<FileTreeEntry>, Vec<Link>, …) that don’t have string-parseable forms and shouldn’t appear in :set autocomplete. The user can inspect them via :describe-buffer but never edit them via :set / :customize.

§Ownership and the OWNER_MODE rule

Each local declares the mode that owns it (BufferLocal::OWNER_MODE). The design (M.3.2.a) has crate::ModeContext check at write time that the currently activating mode matches the local’s owner, rejecting cross-mode mutation with ModeActivationError::WrongOwnerMode. That checked write surface is not implemented: ModeContext has no local accessors today, writes happen host-side through BufferLocals::insert (unchecked), and OWNER_MODE is attribution metadata for :describe-buffer. Treat the rule as a convention — write only the locals your mode owns.

Reads are unrestricted: any mode can read any local. This lets, e.g., lsp-completion-mode read file-tree-mode’s entries to populate path completion without a special-case handshake.

§What does NOT live here

  • Universal buffer state (rope, cursor, scroll, version) – direct fields on whatever struct holds them. Buffer-locals are for mode-specific runtime data.
  • User-facing options – those are OptionDecl in lattice-config. See mode-architecture.md §6.4.
  • Declarative contributions (option overrides, keymap layers, decoration providers) – modes return these from Mode::options() etc.; the registry applies them. The mode never writes to them directly.

§Storage shape

BufferLocals is a HashMap<TypeId, Box<dyn LocalDyn>>. LocalDyn is a sealed inner trait that lets us:

  • Read metadata (name, doc, owner_mode, describe) without knowing the concrete type — for :describe-buffer.
  • Downcast back to the concrete T for typed reads / removes — for the typed accessors.

Structs§

BufferLocals
Typed-map of buffer-local mode-internal state.
BufferScopeDir
The directory a buffer is about, when that is not its own path.
BufferScopeSourceRegistry
Registered BufferScopeSources. A Vec rather than a single handle because two providers naming buffers is normal and a single slot would let the second registration silently displace the first.
LocalDescriptor
Read-only descriptor for one buffer-local, returned by BufferLocals::iter_descriptors for :describe-buffer.

Traits§

BufferLocal
Compile-time declaration of a mode-owned per-buffer local.
BufferScopeSource
A provider’s answer to “which directory is the buffer called this about?”, asked by the host the moment it creates a synthetic buffer.

Type Aliases§

BufferScopeSourceRegistryHandle
Register and look up with this exact alias (the ServiceRegistry TypeId rule).