Core editing context that exists regardless of presentation.
A workspace is the editing state that gets saved/restored when switching tabs. It works identically whether rendered as a tab in the traditional editor, a card on The Board, or running headless without any UI.
This struct formalizes the @per_tab_fields boundary from
MingaEditor.State: every field here is snapshotted per tab and
restored on tab switch.
Summary
Functions
Returns the active window struct, or nil.
Returns the list of field names (for snapshot/restore compatibility).
Invalidates render caches for all windows.
Restores a flat tab context into a workspace. Empty contexts are ignored by this pure helper; EditorState handles brand-new tab defaults because those need editor dimensions.
Returns the appropriate keymap scope for the active window's content type.
Derives the keymap scope from a window's content type.
Updates the agent UI state.
Replaces the buffers sub-struct.
Updates the document highlights from LSP.
Replaces the editing (VimState) sub-struct.
Updates the highlighting sub-struct.
Updates the injection ranges map.
Sets the keymap scope.
Updates the LSP pending requests map.
Updates the mouse sub-struct.
Updates the search sub-struct.
Sets the viewport dimensions.
Replaces the windows sub-struct.
Returns true if the workspace has more than one window.
Switches to the buffer at idx, making it active for the current window.
Syncs the active window's buffer reference with buffers.active.
Converts a workspace into a flat-map tab context suitable for storing
on a MingaEditor.State.Tab and later restoring via
restore_tab_context/2.
Transitions the editing model to a new mode.
Updates the editing (VimState) sub-struct.
Updates the highlighting sub-struct via a mapper function.
Updates the search sub-struct via a mapper function.
Updates the window struct for the given window id via a mapper function.
Types
@type document_highlight() :: Minga.LSP.DocumentHighlight.t()
A document highlight range from the LSP server.
@type t() :: %MingaEditor.Workspace.State{ agent_ui: MingaEditor.Agent.UIState.t(), buffers: MingaEditor.State.Buffers.t(), document_highlights: [document_highlight()] | nil, editing: MingaEditor.VimState.t(), file_tree: MingaEditor.State.FileTree.t(), highlight: MingaEditor.State.Highlighting.t(), injection_ranges: %{ required(pid()) => [Minga.Language.Highlight.InjectionRange.t()] }, keymap_scope: Minga.Keymap.Scope.scope_name(), lsp_pending: %{required(reference()) => atom() | tuple()}, mouse: MingaEditor.State.Mouse.t(), search: MingaEditor.State.Search.t(), viewport: MingaEditor.Viewport.t(), windows: MingaEditor.State.Windows.t() }
Functions
@spec active_window_struct(t()) :: MingaEditor.Window.t() | nil
Returns the active window struct, or nil.
@spec field_names() :: [atom()]
Returns the list of field names (for snapshot/restore compatibility).
Invalidates render caches for all windows.
Call when the screen layout changes (file tree toggle, agent panel toggle) because cached draws contain baked-in absolute coordinates that become wrong when column offsets shift.
Restores a flat tab context into a workspace. Empty contexts are ignored by this pure helper; EditorState handles brand-new tab defaults because those need editor dimensions.
Returns the appropriate keymap scope for the active window's content type.
@spec scope_for_content( MingaEditor.Window.Content.t(), Minga.Keymap.Scope.scope_name() ) :: Minga.Keymap.Scope.scope_name()
Derives the keymap scope from a window's content type.
Agent chat windows always use :agent scope. Buffer windows use
:editor when coming from :agent scope, and preserve the current
scope otherwise.
@spec set_agent_ui(t(), MingaEditor.Agent.UIState.t()) :: t()
Updates the agent UI state.
@spec set_buffers(t(), MingaEditor.State.Buffers.t()) :: t()
Replaces the buffers sub-struct.
@spec set_document_highlights(t(), [document_highlight()] | nil) :: t()
Updates the document highlights from LSP.
@spec set_editing(t(), MingaEditor.VimState.t()) :: t()
Replaces the editing (VimState) sub-struct.
@spec set_highlight(t(), MingaEditor.State.Highlighting.t()) :: t()
Updates the highlighting sub-struct.
@spec set_injection_ranges(t(), %{ required(pid()) => [Minga.Language.Highlight.InjectionRange.t()] }) :: t()
Updates the injection ranges map.
@spec set_keymap_scope(t(), Minga.Keymap.Scope.scope_name()) :: t()
Sets the keymap scope.
Updates the LSP pending requests map.
@spec set_mouse(t(), MingaEditor.State.Mouse.t()) :: t()
Updates the mouse sub-struct.
@spec set_search(t(), MingaEditor.State.Search.t()) :: t()
Updates the search sub-struct.
@spec set_viewport(t(), MingaEditor.Viewport.t()) :: t()
Sets the viewport dimensions.
@spec set_windows(t(), MingaEditor.State.Windows.t()) :: t()
Replaces the windows sub-struct.
Returns true if the workspace has more than one window.
@spec switch_buffer(t(), non_neg_integer()) :: t()
Switches to the buffer at idx, making it active for the current window.
Pure workspace operation: updates Buffers and syncs the active window.
Syncs the active window's buffer reference with buffers.active.
Call after any operation that changes buffers.active to keep the
window tree consistent. No-op when windows aren't initialized.
Converts a workspace into a flat-map tab context suitable for storing
on a MingaEditor.State.Tab and later restoring via
restore_tab_context/2.
The single chokepoint for snapshots. Beyond the Map.from_struct/1
conversion, this normalises editing so the snapshotted vim state is a
valid resting state — not a transient mid-transition pair where
mode_state belongs to the leaving mode (see VimState.normalize/1).
Use this everywhere the editor captures state.workspace into a tab
context.
Transitions the editing model to a new mode.
@spec update_editing(t(), (MingaEditor.VimState.t() -> MingaEditor.VimState.t())) :: t()
Updates the editing (VimState) sub-struct.
@spec update_highlight(t(), (MingaEditor.State.Highlighting.t() -> MingaEditor.State.Highlighting.t())) :: t()
Updates the highlighting sub-struct via a mapper function.
@spec update_search(t(), (MingaEditor.State.Search.t() -> MingaEditor.State.Search.t())) :: t()
Updates the search sub-struct via a mapper function.
@spec update_window(t(), MingaEditor.Window.id(), (MingaEditor.Window.t() -> MingaEditor.Window.t())) :: t()
Updates the window struct for the given window id via a mapper function.