Expand description
The typed options system: every editor, mode, renderer and plugin
setting is a registered, typed value in one ConfigRegistry, read
on the hot path by type and written at the boundaries (:set,
lattice.toml, :setlocal, plugins) by name (DESIGN.md §5.12).
Renderer-agnostic option machinery: the OptionType trait,
the typed option::Option<T> spec, the type-erased ErasedOption
trait the registry stores, and ConfigRegistry itself.
§What it owns
- Declaration. The
options!/groups!macros (fromlattice-config-macros) turn a declaration into anOptionDeclmarker type plus anOptionDeclMetadataentry in theOPTION_DECLSlink-time slice;ConfigRegistry::init_from_linkmeregisters every one linked into the binary. The built-in set lives incore_optionsand is re-exported here (Tabstop,Wrap, …); groups (OptionGroup) organise them for:customize. - Values.
OptionType(parse / format / enumerate / schema) with impls forbool,i64,String, the lattice-core domain enums, and the display-policy value types defined here (SignColumn,ModelineZone,DiagnosticsInline,Decorations, …).ConfigSchema/ConfigValuedescribe composite (list / record) values as data — seeschema. - Access. Type-keyed reads/writes (
ConfigRegistry::get_typed/ConfigRegistry::set_typed), handle reads for runtime-registered options (option::OptionHandle), and the by-name:setpath (parse_set→ConfigRegistry::parse_and_set_command). - Layering. Per-buffer resolution: modes and
:setlocalcontributeOptionOverrideSets, theResolvermerges them by layer andOverridePriorityinto aResolvedOptionscache, each winner tagged with itsOptionOrigin. - Files. The TOML
loader(lattice.toml,.lattice/config.toml) and the config-home paths (config_home,cache_home). - Completion.
OptionsGenerator, the:set <Tab>candidate source.
§What it must not depend on
Its dependencies are the foundation only (lattice-protocol,
lattice-core, lattice-completion). Almost every crate reads options,
so anything this crate imported would sit beneath the whole editor:
no host / App, no renderer, no mode registry, no event bus
(lattice-runtime — events leave through an injected
EventPublisher closure instead), no plugin host (so
PluginTraceLevel duplicates the host’s trace-level labels rather
than importing the type). The layer-input override types moved into
this crate for the same reason (see overrides).
§Example
use lattice_config::{ConfigRegistry, Tabstop};
let config = ConfigRegistry::new();
config.init_from_linkme(); // register every `options!` declaration
// Hot path: read by type.
assert_eq!(*config.get_typed::<Tabstop>().unwrap(), 4);
// Boundary: write by name, exactly as `:set ts=2` does.
assert_eq!(config.parse_and_set_command("ts=2").unwrap(), "tabstop=2");
assert_eq!(*config.get_typed::<Tabstop>().unwrap(), 2);
// Validation runs on every write; a rejected write changes nothing.
assert!(config.parse_and_set_command("tabstop=99").is_err());
assert_eq!(*config.get_typed::<Tabstop>().unwrap(), 2);Design: docs/dev/architecture/typed-configuration.md (schemas, composite
values), docs/dev/architecture/config-and-init.md (when configuration
arrives), docs/dev/architecture/buffer-local-options.md (:setlocal,
origins), docs/dev/architecture/mode-architecture.md §6 (declarations,
layering, groups).
§Design (γ — value-on-spec storage)
Each option::Option<T> owns its current value behind an
[arc_swap::ArcSwap<T>]. Reads through a typed
crate::option::OptionHandle<T> are wait-free pointer loads. Writes go
through the registry (typed via set / by-name via
parse_and_set_command), which validates and stores.
Renderer-specific options live in the renderer’s crate but
register against the same ConfigRegistry at App startup.
The crate has no knowledge of the App or any concrete renderer.
§Crate boundary
The trait + the three primitive impls (bool, i64, String)
live here. So do the impls for the lattice-core domain enums
(FoldMethod, IndentMethod, …): the orphan rule allows a local
trait on a foreign type, and lattice-core cannot depend on this
crate. A crate above this one that defines its own value type
implements OptionType itself, importing the trait from
lattice-config.
§What’s NOT here
Appreference. Setters don’t take an&mut App. The value lives in the spec; consumers read it through their typed handle. Renderers run side-effect cascades (relativenumber⇒number,foldmethod⇒ recompute folds,ui.*⇒ refresh derived theme styles) in their own post-set hook, polling the parsed:setform.- Other crates’ options. Options owned elsewhere are declared
with the same
options!macro in the owning crate and join the registry throughOPTION_DECLSat boot — e.g. theui.separator/ui.statusline_*_fgfamily inlattice_host::ui::theme_options. Runtime-only options (plugins) useConfigRegistry::register.
§Event-bus integration (DESIGN.md §5.10 + §5.12)
The registry optionally publishes [lattice_protocol::Event::OptionChanged]
on every successful set so consumers can react to typed-option
changes without polling. Wire it via
ConfigRegistry::set_event_publisher – the closure receives
the Event and delegates to the consumer’s bus. The crate is
agnostic to which bus (avoids a dep on lattice-runtime); the
App today calls event_bus.publish(event) from inside the
closure.
Events fire on:
- typed
set::<T>(handle, value)writes - cmdline
parse_and_set_command(":set foo=bar")(Assign) - cmdline
:set nofoo(Negate) - cmdline
:set fooboolean toggle (NameOnly on bool option)
Events do NOT fire on :set foo? (Query) or on validation /
parse failures.
Re-exports§
pub use completion::OptionsGenerator;pub use core_options::COMPLETION_SOURCE_SNIPPET_DEFAULT_PRIORITY;pub use core_options::AutoWrapOption;pub use core_options::ClipboardEnabled;pub use core_options::CommandLineExpandHeight;pub use core_options::CompletionAutoInsertSingle;pub use core_options::CompletionExtraCommitChars;pub use core_options::CompletionGhostText;pub use core_options::CompletionSourceBufferWordsPriority;pub use core_options::CompletionSourceLspPriority;pub use core_options::CompletionSourcePathPriority;pub use core_options::CompletionSourceSnippetPriority;pub use core_options::CompletionSourceTreeSitterPriority;pub use core_options::CursorLine;pub use core_options::DiagnosticsInlineOption;pub use core_options::DiagnosticsMinSeverityOption;pub use core_options::ElectricIndent;pub use core_options::ExpandTab;pub use core_options::FoldEnable;pub use core_options::FoldMethodOption;pub use core_options::FormatIndentChain;pub use core_options::FormatOnSave;pub use core_options::FormatPrg;pub use core_options::FormatReflowChain;pub use core_options::FormatReformatChain;pub use core_options::HelpAproposDisplay;pub use core_options::HelpDescribeDisplay;pub use core_options::HelpListDisplay;pub use core_options::HelpTopicDisplay;pub use core_options::HoverDisplay;pub use core_options::IgnoreCase;pub use core_options::IndentMethodOption;pub use core_options::LspLogDisplay;pub use core_options::LspStatusDisplay;pub use core_options::MessagesDisplay;pub use core_options::MessagesFilter;pub use core_options::ModelineCenter;pub use core_options::ModelineLeft;pub use core_options::ModelinePadding;pub use core_options::ModelineRight;pub use core_options::ModelineSeparator;pub use core_options::MouseEnabled;pub use core_options::NoFile;pub use core_options::Number;pub use core_options::PickerResultDisplay;pub use core_options::ProjectRootMarkers;pub use core_options::ReadOnly;pub use core_options::RelativeNumber;pub use core_options::Scroll;pub use core_options::Scrollbind;pub use core_options::Scrolloff;pub use core_options::Shiftwidth;pub use core_options::Sidescroll;pub use core_options::Sidescrolloff;pub use core_options::SignColumnOption;pub use core_options::SignatureDisplay;pub use core_options::StartOfLine;pub use core_options::TablineShowOption;pub use core_options::Tabstop;pub use core_options::TerminalEscExits;pub use core_options::TerminalScrollbackLines;pub use core_options::TextWidth;pub use core_options::TransientMaxRows;pub use core_options::Whitespace;pub use core_options::WhitespaceEol;pub use core_options::WhitespaceLeading;pub use core_options::WhitespaceSpace;pub use core_options::WhitespaceTab;pub use core_options::WhitespaceTrailing;pub use core_options::Wrap;pub use group::Ai;pub use group::Appearance;pub use group::Completion;pub use group::Diagnostics;pub use group::Display;pub use group::Editing;pub use group::Editor;pub use group::Filetree;pub use group::GROUP_DECLS;pub use group::Help;pub use group::Lsp;pub use group::Magit;pub use group::Messages;pub use group::Modeline;pub use group::Mouse;pub use group::Notifications;pub use group::Oil;pub use group::OptionGroup;pub use group::OptionGroupMetadata;pub use group::Pane;pub use group::Picker;pub use group::Plugin;pub use group::Project;pub use group::Search;pub use group::Snippet;pub use group::Tabline;pub use group::Terminal;pub use group::Window;pub use group::ends_with_mode_suffix;pub use loader::LoadMessage;pub use loader::LoadMessageLevel;pub use loader::LoadOutcome;pub use loader::cache_home;pub use loader::cache_home_from;pub use loader::config_home;pub use loader::default_user_config_path;pub use loader::load_default_paths;pub use loader::load_file;pub use loader::lookup_dotted_path;pub use loader::migrate_path;pub use loader::project_config_path;pub use option_decl::OPTION_DECLS;pub use schema::ConfigSchema;pub use schema::ConfigValue;pub use schema::ScalarKind;pub use schema::SchemaError;pub use schema::SchemaField;pub use overrides::OptionOverride;pub use overrides::OptionOverrideSet;pub use overrides::OverridePriority;
Modules§
- completion
OptionsGenerator— completion source for:set <Tab>.- core_
options - Renderer-agnostic options. M.2.0b migrates these from the
pre-typed-keys imperative
Option::builder()form to the macro-driven declarative form (Design B + D from themode-architecture.mddiscussion). - group
- Option groups: the user-facing organization unit for
:customize <name>(mode-architecture.md§6.7.1.1). - loader
- Static config-file loader (DESIGN.md §5.12; first slice of the TOML surface called out in the design doc’s “TOML covers static option overrides only” line).
- option
- Typed
Option<T>spec + theOptionHandle<T>consumers use for hot-path reads. - overrides
- Layered option overrides (M.2.1).
- schema
- TC.1:
ConfigSchema/ConfigValue— what an option’s value is shaped like, as data, plus schema-checked validation that reports a path. TC.1 — what an option’s value is shaped like, as data.
Macros§
- groups
- Declarative group declaration block. See
lattice_config::OptionGroupandlattice_config::groups!for the surface contract. - options
- Declarative option declaration block. See the trait doc on
lattice_config::OptionDecland the macro doc onlattice_config::options!for the surface contract. - overrides
- Construct a typed
OptionOverrideSetfor aMode::options()return.
Structs§
- Config
Registry - Process-shared registry.
- Option
Decl Metadata - Metadata captured at macro expansion for one option. The
registerfunction pointer is monomorphised at the call site so the registry boot path can register every option without pulling each<T>into a generic over the slice. - Pane
Buffer History Size - How many buffers one pane remembers in its back/forward trail
(
<C-6>/<C-7>,:history pane-buffers). - Pane
Zoom Indicator - ZP.4: where the zoom marker shows while a pane is zoomed
(
<C-w>z/:zoom-pane). - Plugin
Trace Level Option - Global default plugin boundary-trace verbosity.
off/error/warn/info(default) /debug/trace.infoand below carry only crash/lifecycle signal — no per-call traces (the keystroke hot path stays free). Raise todebugto trace every host↔guest call; per-plugin overrides live in the:pluginsview (T). - Resolved
Options - Cached snapshot of the resolved value for every option a
buffer reads. Built by the
crate::Resolver; invalidated on mode toggle, option write, or modal-state transition; recomputed eagerly on invalidation per the v1 invalidation policy (mode-architecture.md§6.3.1). - Resolver
- Walks layered overrides and emits a fresh
ResolvedOptions. - Root
Markers - The ordered marker set a project root is recognised by.
- Start
Maximized - Maximize the window on launch (fill the work area, keep the menu bar — not native fullscreen). GPUI peer only; ignored by the TUI.
- Window
Decorations Option - OS window chrome (GPUI only; ignored by the terminal UI). One of:
full(default) — system titlebar + window controls.none— borderless: no titlebar or controls, like alacrittydecorations = none/ kitty / emacsundecorated. On macOS anonewindow is non-resizable by any means — even Raycast/yabai can’t move or resize it; it opens at a fixed size.transparent— frameless-looking but still resizable: a transparent titlebar with the traffic-light buttons hidden. Edge-resize works and window managers (Raycast/yabai) can drive it; rounded corners + shadow remain. The macOS-friendly frameless option. Applied at window creation; a change takes effect on the next launch.
Enums§
- Config
Error - What the registry’s fallible operations can fail with. Kept
separate from raw
Stringerrors so callers can echo the canonical message without re-stringifying. - Decorations
ui.window.decorations— OS window chrome.- Diagnostics
Inline ui.diagnostics.inline— where the inline (end-of-line virtual-text) diagnostic summary renders.- Diagnostics
Severity ui.diagnostics.inline-min-severity— the least-severe level a diagnostic must be to appear in the inline summary. A diagnostic is included when its severity is as severe or more severe than this (i.e. its rank ≤ this rank).- Expand
Height command-line.expand-height— how tall the expanded:band grows.- Modeline
Zone - A modeline zone’s configured layout: descriptor-driven (
Auto) or an explicit ordered element-id list (Ids). - Option
Origin - The layer that supplied the winning value in a resolution cycle.
- Parsed
Set - One
:setargument, classified by syntax alone. - Plugin
Trace Level plugin.trace-level— the global default plugin boundary-trace verbosity. Ordered least→most verbose; a record is kept when its level ≤ this gate.info(the default) drops per-call traces — authors opt a plugin up todebug/trace(globally here, or per-plugin from the:pluginsview).- Sign
Column signcolumn— whether to reserve the gutter sign columns.
Statics§
- OPTION_
DECLS - Distributed slice of every option declared anywhere in the
workspace. Each
options!macro invocation submits a&'static OptionDeclMetadataelement here; the registry’s startup loader walks the slice to register each option and validate cross-crate display-name uniqueness.
Traits§
- Erased
Option - Type-erased operations every typed
Option<T>supports. The registry storesArc<dyn ErasedOption>in aVecindexed by the privateidxfield ofcrate::option::OptionHandle;parse_and_set_by_namedrives this trait when the user types:set name=value. - HasGroup
- Group binding declared by
OptionDecldeclarations. Each option belongs to exactly onecrate::OptionGroup(selected per declaration block in the macro, with optional per-option override). Stored on the metadata record so:customize <name>can prefix-match. - Option
Decl - Compile-time declaration of one option. Each option type is a
unique unit struct (typically generated by the
crate::options!macro) implementing this trait. - Option
Type - Surface contract for any value a typed
crate::option::Optioncan hold. Implementors describe how their type round-trips through the user-facing:set foo=valuesyntax.
Functions§
- parse_
set - Classify one
:setargument (without the:setprefix). - plugin_
option_ groups - Runtime-registered options that have no compile-time declaration — i.e. plugin options — grouped by their dotted namespace.
Type Aliases§
- Event
Publisher - Sink the registry calls after every successful set so consumers
can react to typed-option changes through the §5.10 event bus.
Stored as a
Box<dyn Fn>solattice-configdoesn’t depend onlattice-runtime’sEventBusdirectly – the App wiresevent_bus.publish(event)as the closure body at boot.