Vim-specific editing model state.
Groups the modal FSM state, registers, marks, and recording state
that are specific to vim-style editing. This substruct on EditorState
creates the swap boundary for alternative editing models (CUA, #306):
replace state.workspace.editing with a different struct to change the editing model.
Fields
mode— current vim mode (:normal, :insert, :visual, etc.)mode_state— mode-specific state (pending operator, search input, etc.)reg— named registers and active register selectionmarks— buffer-local marks (outer key is buffer pid, inner is mark name)last_jump_pos— cursor position before the last jumplast_find_char— last f/F/t/T char for;and,repeatchange_recorder— tracks changes for dot repeatmacro_recorder— tracks macro recording state
Summary
Types
Stored last find-char motion for ; and , repeat.
Buffer-local marks: outer key is buffer pid, inner key is mark name.
Functions
Returns a new VimState with default values.
Sets the marks map for a specific buffer.
Updates the change recorder state.
Records the last f/F/t/T char for ; and , repeat.
Records the cursor position before a jump.
Updates the macro recorder state.
Replaces the entire marks map.
Updates mode_state without changing the mode.
Updates the register state.
Transitions to a new mode, returning an updated VimState.
Types
@type last_find_char() :: {Minga.Mode.State.find_direction(), String.t()} | nil
Stored last find-char motion for ; and , repeat.
@type marks() :: %{ required(pid()) => %{required(String.t()) => Minga.Buffer.position()} }
Buffer-local marks: outer key is buffer pid, inner key is mark name.
@type t() :: %MingaEditor.VimState{ change_recorder: MingaEditor.ChangeRecorder.t(), last_find_char: last_find_char(), last_jump_pos: Minga.Buffer.position() | nil, macro_recorder: MingaEditor.MacroRecorder.t(), marks: marks(), mode: Minga.Mode.mode(), mode_state: Minga.Mode.state(), reg: MingaEditor.State.Registers.t() }
Functions
@spec new() :: t()
Returns a new VimState with default values.
@spec set_buffer_marks(t(), pid(), %{required(String.t()) => Minga.Buffer.position()}) :: t()
Sets the marks map for a specific buffer.
@spec set_change_recorder(t(), MingaEditor.ChangeRecorder.t()) :: t()
Updates the change recorder state.
@spec set_last_find_char(t(), last_find_char()) :: t()
Records the last f/F/t/T char for ; and , repeat.
@spec set_last_jump_pos(t(), Minga.Buffer.position() | nil) :: t()
Records the cursor position before a jump.
@spec set_macro_recorder(t(), MingaEditor.MacroRecorder.t()) :: t()
Updates the macro recorder state.
Replaces the entire marks map.
@spec set_mode_state(t(), Minga.Mode.state()) :: t()
Updates mode_state without changing the mode.
@spec set_registers(t(), MingaEditor.State.Registers.t()) :: t()
Updates the register state.
@spec transition(t(), Minga.Mode.mode(), Minga.Mode.state() | nil) :: t()
Transitions to a new mode, returning an updated VimState.
This is the single gate function for all mode changes. Every mode
transition in the codebase must go through this function (or the
EditorState.transition_mode/3 convenience wrapper). A custom Credo
check enforces this by flagging raw mode: writes on the vim struct.
When mode_state is nil, sensible defaults are used:
:normal,:insert→Mode.initial_state():command→%CommandState{}:eval→%EvalState{}:replace→%ReplaceState{}
Modes that require context (:visual, :search, :search_prompt,
:substitute_confirm, :extension_confirm, :operator_pending)
must be given an explicit mode_state.