Skip to main content

Module app_effect

Module app_effect 

Source
Expand description

AppEffect – the typed App-side effects produced by free-form CommandKind::Action registrations.

Background: the keymap-bound Action enum in lattice-ui-tui historically encoded the App’s response to non-grammar chords (<Esc>, o, <C-w>v, …). Slice 8.i (see docs/dev/notes/8i-approach.md) retires the per-binding Action bridge and routes those chords through the unified dispatcher’s CommandKind::Action branch instead. Action-kind registry entries return Effect::AppAction(AppEffect); the App’s apply_effect then matches on the inner AppEffect variant.

Why a sibling type to Effect rather than a flat extension:

  • Effect’s existing variants describe core / dispatcher-native work (Edits, SelectionChange, Yank, EnterMode, Substitute, …) and ex-command-emitted App work (SaveBuffer, OpenBuffer, LspRestart, …). Both are produced by code paths that resolve a typed grammar concern into a typed effect.
  • AppEffect is for chord bindings that historically had no grammar concept attached – <Esc> exits Visual, <C-w>v splits a pane, o opens a line below. Treating those as first-class “free-form actions” keeps the dispatcher contract (“everything returns Effect”) honest without fusing two conceptually different surfaces into one giant enum.

Applied host-side by Editor::apply_app_effect (reached from the crate::Effect::AppAction arm of handle_effect), so every variant acts on the focused buffer / active pane at apply time unless it names a buffer. Several variants are now fallback shells: the chord is owned by a mode whose ActionHandlerRegistry closure intercepts it before the arm runs, and the arm is a no-op kept so the registered action id resolves. Those variants say so.

Enums§

AppEffect
Variants are added incrementally during slice 8.i as each historical Action variant is promoted from the legacy bind_legacy bridge to a typed CommandInvocation.
ErrorTarget
CM.2 (2026-07-22): which error entry a AppEffect::ErrorNav should resolve to. Carried in the AppEffect so the whole :cnext / :cprev / :cc / :cfirst / :clast / ]q / [q family shares a single host handler (Editor::do_error_nav). The error list is core substrate (like the jump ring), so a host AppEffect variant is the right carrier — not a provider-specific one.
HScroll
Manual horizontal-scroll commands (HS.2), the vim z{l,h,L,H,s,e} family. Carried by AppEffect::HorizontalScroll; the host handler mutates leftcol and keeps the cursor inside the new window. wrap-off only (no-op under wrap, like the cursor-follow clamp). See docs/dev/architecture/horizontal-scroll.md.
InsertLineEdit
App-side typed effect produced by a CommandKind::Action dispatch (DESIGN.md §5.2.1, see also docs/dev/notes/8i-approach.md).
PaneDirection
<C-w>h/j/k/l cardinal navigation. Geometry-aware: walks the tree to find the spatial neighbour of the active pane.
ScrollPos
Vim’s zz / zt / zb target positions: where in the viewport the cursor’s current line should sit after the scroll. App-side concept hosted alongside ViewportPos for the same dependency reason. Slice 8.i.2.c hoist.
ViewportPos
Vim’s H / M / L target positions: where in the visible viewport the cursor lands. App-side concept hosted here so AppEffect::JumpViewport(ViewportPos) can carry the typed payload without lattice-ui-tui having to dance through a dependency cycle. Slice 8.i.2.c hoist; the App’s previous crate::app::ViewportPos becomes a pub use re-export of this type.