Expand description
What a CommandInvocation produced once executed.
Effect is the host boundary: every evaluator, ex-command, mode
action handler and WASM plugin describes what it wants done as an
Effect value, and the host (lattice-host’s handle_effect, then the
renderer peers for the few renderer-coupled arms) applies it. Producers
never hold &mut Editor; that is what makes built-ins, modes and plugins
peers, and what lets macros, dot-repeat and the async inbound path replay
the same values.
Effect::None is for read-only or selection-only commands. Effect::Edits
carries the AppliedEdits that the dispatcher applied to the document
(suitable for Event::DocumentChanged). Effect::SelectionChange carries
the new selection set (suitable for Event::SelectionsChanged). Effects
compose; a single command can yield multiple via Effect::Many.
§Coordinates
Every Position here is 0-based
(line, byte) – a UTF-8 byte offset within the line, not a char or
UTF-16 column – and every protocol Range is half-open. The one
exception is Utf16Pos, which exists precisely to carry an
unconverted LSP column.
§Which buffer
Unless a variant names a buffer (target, view, a BufferId, a
path or a synthetic name), it acts on the focused buffer / active
pane at apply time. That is right for a chord-time effect and wrong
for an async one; see Effect::CursorMoveIn and
Effect::ApplyEdit for the addressed forms.
§Where each variant is applied
Most arms run host-side in lattice_host::dispatch::handle_effect,
synchronously and in order. A minority are peer-applied (the TUI’s
apply_effect_app_arms and the GPUI peer): QuitEditor, OpenBuffer,
OpenBufferAt, OpenInTarget, Global, the picker / prompt /
transient / popup / file-tree / oil openers, most Lsp* commands. A
peer-applied effect runs after every host-applied effect of the same
batch, and is dropped on the off-keystroke inbound path (which applies
host-side only) – which is why host-applied twins such as
Effect::OpenBufferAtColumn exist.
Ex-command effects (SaveBuffer, QuitEditor, OpenBuffer, SetOption,
ClearSearchHighlight, Echo, EchoRegisters, EchoMarks, Substitute,
Global) carry the typed intent of an ex-command. The host applies them
using its own state (registers, marks, view options, document loader);
the closure inside the registry only needs to package args into the
correct effect, which is what makes plugin- and built-in ex-commands
peers (DESIGN.md §5.2.1, §5.2.4).
Structs§
- Utf16
Pos - BC.8c: a UTF-16 code-unit column on a given line. LSP’s default
position encoding counts UTF-16 code units, not bytes; converting to
Lattice’s byte offset (
lattice_protocol::Position.byte) needs the target line’s text, which only exists after the file is open. SoEffect::OpenBufferAtColumncarries this unconverted column for the host to resolve post-open. Plainu32s — nolsp_typesleak.
Enums§
- Echo
Level - Severity tier for
Effect::Echo. The host’s echo-area renderer maps these to its own colour scheme. - Effect
- What a command asks the host to do. See the module docs for the coordinate convention, which buffer an un-addressed variant acts on, and which variants are host- vs. peer-applied.
- File
Anchor - Where in a target file an
Effect::WriteToFilelands. - LspRequest
- L7 (lsp-architecture.md §16): which LSP navigation request a
mode-owned nav chord (
K/gd/gD/gy/gI/gr/gx) wants the host to fire. Pure data — nolsp_types, nolattice-lspdependency — so it can ride inside the host-ownedEffect::Lspboundary.lsp-mode’saction_handlers()closure returnsEffect::Lsp(LspRequest::X); the host’seditor.lsp_requestdispatcher maps each arm onto the existing (unchanged) async request substrate (lsp_hover_request/lsp_nav_request/lsp_references_request/do_lsp_follow_link_at_cursor). The handler carries no position — the substrate reads liveEditorcursor/scroll, so the popup/jump anchors to the symbol the chord fired on. - Quit
Scope - Scope for
Effect::QuitEditor. Mirrors vim’s:q(close the active pane; quit only when it is the last one) vs.:qa(quit the editor regardless of how many panes / tabs are open).:qand:qastay distinct commands (separate registrations + aliases);QuitScopeis the one axis on which they differ, so the shared shutdown + dirty guard stays in a singleEditor::do_quit. - Substitute
Scope - Scope for
Effect::Substitute. Mirrors vim’s:s/.../.../(current line) vs.:%s/.../.../(whole buffer). - Yank
Kind - How a yank captured its content. Drives paste behavior:
charwise yanks land at the cursor, linewise yanks land on the next
line below, blockwise yanks paste each ‘\n’-separated row at the
same column on consecutive lines (vim’s
Ctrl-Vselection theny).