pub struct EditingState {Show 14 fields
pub mode_stack: ModeStack,
pub pending_keys: KeySequence,
pub windows: WindowLayout,
pub viewport: Viewport,
pub selection: Option<ClientSelection>,
pub extensions: ExtensionMap,
pub compositor: Option<Box<dyn RootCompositor>>,
pub tabs: TabPageSet,
pub registers: RegisterBank,
pub clipboard_history: HistoryRing,
pub local_marks: MarkBank,
pub jumplist: Jumplist,
pub active_buffer: Option<BufferId>,
pub terminal_size: (u16, u16),
}Expand description
Editing state for a client.
Contains all per-client state needed for editing operations. All clients have this state - it’s not just for “owners” anymore.
§Multi-Client Isolation (#471)
Each client owns their own WindowLayout with independent cursors.
This ensures Client A’s cursor/mode doesn’t affect Client B.
Buffers are still shared (all clients see same text content).
§Client Model Mapping (#480)
This struct maps to ClientViewState in the common client model.
Only a subset is transmitted:
EditingState field | ClientViewState field | Transform |
|---|---|---|
mode_stack | mode | .current().name() |
windows | cursor: Position | .focused().cursor |
windows | buffer_id | .focused().buffer_id |
selection | selection | .to_driver_selection() |
Per-client editing state (#471, #477).
Contains all client-specific state including mode, windows, viewport, selection, and module extensions. Each client has independent state to prevent cross-client interference (e.g., Client A’s pending count affecting Client B’s motions).
Fields§
§mode_stack: ModeStackMode stack (current mode on top).
pending_keys: KeySequenceKeys accumulated but not yet processed.
windows: WindowLayoutPer-client window layout with independent cursors (#471).
Each window contains its own cursor position. This replaces
the old shared session.windows that caused multi-client bugs.
viewport: ViewportViewport (visible area).
selection: Option<ClientSelection>Active selection (for visual mode).
extensions: ExtensionMapPer-client module extensions (#477).
Type-erased storage for module state like VimSessionState,
SearchState, CmdlineState. Each client has independent
extensions to prevent state leakage between clients.
§Why Per-Client
Without isolation, Client A pressing 5 (pending_count=5) would
cause Client B’s j to move 5 lines instead of 1. This field
ensures complete module state isolation.
compositor: Option<Box<dyn RootCompositor>>Per-client compositor for window layout (#474).
Each client owns their own compositor, cloned from the shared template at join time. This ensures window IDs are consistent between the compositor (geometry) and per-client windows (cursor/viewport).
Before this field, the shared compositor and per-client windows used independent ID namespaces, causing cross-namespace mismatches in notifications and state queries.
tabs: TabPageSetPer-client tab pages (#401).
Manages tab page lifecycle. Each tab can have its own window layout
and compositor. Currently starts with a single default tab.
Future work will integrate with windows and compositor fields
so that active_tab().windows() becomes the source of truth.
registers: RegisterBankPer-client register storage (#515).
Each client owns their own registers (unnamed "", named a-z/A-Z).
System clipboard (+, *) remains shared via ClipboardProvider.
This prevents Client A’s "ayy from overwriting Client B’s register ‘a’.
clipboard_history: HistoryRingPer-client clipboard history ring (#515).
Tracks yank/delete history for numbered registers 0-9.
Each client has independent history so Client A’s deletes don’t
shift Client B’s numbered registers.
local_marks: MarkBankPer-client local marks (a-z, per-client special marks) (#515).
Each client owns their own local marks. Global marks (A-Z) remain
shared in KernelContext.global_marks.
jumplist: JumplistPer-client jump list for Ctrl-O / Ctrl-I navigation (#654).
Each client owns their own jump list. Jump positions are recorded on cursor movements across buffer boundaries or large jumps.
active_buffer: Option<BufferId>Per-client active buffer (#471).
Each client tracks which buffer they are viewing independently. New clients are initialized with the first kernel buffer (scratch).
terminal_size: (u16, u16)Per-client terminal dimensions (width, height) (#471).
Each client has independent terminal size. Initialized to VT100 default (80, 24); updated when the client sends a resize RPC.
Implementations§
Source§impl EditingState
impl EditingState
Sourcepub fn with_mode_stack(mode_stack: ModeStack) -> Self
pub fn with_mode_stack(mode_stack: ModeStack) -> Self
Create editing state with a specific mode stack.
Sourcepub fn with_mode_stack_and_window(mode_stack: ModeStack, window: Window) -> Self
pub fn with_mode_stack_and_window(mode_stack: ModeStack, window: Window) -> Self
Create editing state with mode stack and initial window.
Used when a client joins a session that already has buffers.
Sourcepub fn current_mode(&self) -> &ModeId
pub fn current_mode(&self) -> &ModeId
Get the current mode ID.
Sourcepub fn clear_pending_keys(&mut self)
pub fn clear_pending_keys(&mut self)
Clear pending keys.
Sourcepub fn client_context(&mut self) -> ClientContext<'_>
pub fn client_context(&mut self) -> ClientContext<'_>
Borrow the 7 per-client mutable fields as a [ClientContext].
This bundles the fields that SessionRuntime needs, avoiding
7-argument parameter lists throughout the session execution chain.
Trait Implementations§
Source§impl Clone for EditingState
impl Clone for EditingState
Source§impl Debug for EditingState
impl Debug for EditingState
Auto Trait Implementations§
impl Freeze for EditingState
impl !RefUnwindSafe for EditingState
impl Send for EditingState
impl Sync for EditingState
impl Unpin for EditingState
impl UnsafeUnpin for EditingState
impl !UnwindSafe for EditingState
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoRequest<T> for T
impl<T> IntoRequest<T> for T
Source§fn into_request(self) -> Request<T>
fn into_request(self) -> Request<T>
T in a tonic::Request