MingaEditor.State.TabBar (Minga v0.1.0)

Copy Markdown View Source

Ordered list of open tabs with an active tab pointer.

The tab bar is the primary navigation structure. Each tab (file or agent) carries a context snapshot of per-tab editor state. Buffer processes live in a shared pool, not inside individual tabs.

Invariants

  • There is always at least one tab.
  • active_id always refers to an existing tab.
  • Tab ids are unique and monotonically increasing.

Summary

Types

t()

Tab bar state.

Functions

Accepts a concrete tab only at its existing stable identity.

Accepts a concrete workspace only at its existing stable identity.

Returns the active tab.

Returns the index of the active tab (0-based).

Returns the active workspace.

Returns the active workspace id, derived from the active tab.

Adds a new tab after the active tab and makes it active.

Adds an agent workspace and returns {updated_tab_bar, workspace}.

Adds a file identity to the identified workspace.

Returns true if any tab has its attention flag set.

Returns every live buffer pid represented by tab snapshots.

Clears attention for the identified tab without changing tab identity or order.

Clears replayed catch-up events for the identified workspace.

Clears session state from the identified workspace.

Returns the number of tabs.

Returns the progressive disclosure tier (0-3) based on agent workspace count.

Drops snapshotted extension-owned feature state from every tab context.

Drops snapshotted feature state owned by a source from every tab context.

Returns all tabs matching the given kind.

Returns the first tab matching the given kind, or nil.

Returns the remote agent tab for a server/session id pair.

Returns the agent tab whose session matches the given pid, or nil.

Finds the file tab in a workspace that represents the given file reference.

Returns an agent tab that has no session assigned, or nil.

Returns the workspace matching a remote server/session id pair.

Returns the workspace matching the given session pid, or nil.

Returns the tab with the given id, or nil.

Returns the workspace with the given id, or nil.

Returns true if any agent workspaces exist.

Returns true if a tab with the given id exists.

Inserts a new tab next to the active tab without switching to it.

Keeps only the tab with the given id. Returns unchanged when the tab is not present.

Returns the most recently used tab of the given kind that is NOT the active tab. Useful for "switch back to previous file/agent" commands.

Moves the active tab one visible slot left within its workspace.

Moves the active tab one visible slot right within its workspace.

Moves the tab with the given id one visible slot left within its workspace.

Moves the tab with the given id one visible slot right within its workspace.

Moves a tab to a different workspace.

Creates a tab bar with a single initial tab and the manual workspace.

Creates a tab bar with no tabs, for a zero-buffers launchpad startup (#2689).

Switches to the next visible file tab in the active workspace, wrapping around.

Switches to the next agent workspace, wrapping around. No-op if no agent workspaces exist.

Cycles to the next tab of the given kind, wrapping around. If the active tab is already of that kind, jumps to the next one. If the active tab is a different kind, jumps to the first of the requested kind. Returns unchanged if no tabs of that kind exist.

Pins the tab with the given id. Returns unchanged when the tab is missing.

Switches to the previous visible file tab in the active workspace, wrapping around.

Switches to the previous agent workspace, wrapping around. No-op if no agent workspaces exist.

Rebinds every matching file tab and workspace reference to one logical file identity.

Refreshes a restarted session identity and status on the identified tab.

Returns remote workspaces for a server.

Removes the tab with the given id.

Removes every file tab, leaving agent tabs (if any) in place.

Removes a workspace and migrates its tabs to the manual workspace (group_id 0).

Removes a file identity from the identified workspace.

Renames the identified workspace.

Reorders a visible file tab within its workspace by zero-based visible index.

Replaces restored workspaces and recalculates the next workspace id.

Retargets one tab and its workspace to a concrete file identity.

Retargets one file identity in the identified workspace.

Removes a dead buffer pid from every tab and workspace projection.

Sets the attention flag on the tab matching the given session pid.

Updates all workspaces and projected tabs for a remote server to the given connection status.

Records an agent status on the identified tab.

Records attention for the identified tab without changing tab identity or order.

Records remote connection status on the identified tab.

Records a remote session identity on the identified tab.

Binds or clears the session owned by the identified tab.

Selects the active file identity in the identified workspace.

Records agent status on the identified workspace.

Records the agent UI projection on the identified workspace.

Sets the icon of the identified workspace.

Records pending durable catch-up events on the identified workspace.

Records project-view state on the identified workspace.

Records remote connection status on the identified workspace.

Records review state on the identified workspace.

Binds or clears the identified workspace session.

Snapshots the outgoing tab and activates an existing target tab atomically.

Switches the active tab to the one with the given id.

Switches to the given workspace by activating its first visible tab.

Synchronizes any agent-tab projection from workspace-owned lifecycle and remote metadata.

Returns the tab at the given 1-based position index, or nil.

Returns all tabs belonging to the given workspace.

Toggles the pinned state of the active tab.

Unpins the tab with the given id. Returns unchanged when the tab is missing.

Updates the context of the tab with the given id.

Updates the label of the tab with the given id.

Returns visible file tabs for the active workspace.

Returns visible file tabs for the given workspace id. Agent chat tabs are excluded.

Returns visible content tabs for the active workspace.

Returns visible content tabs for the given workspace id. Agent workspaces show their agent tab first, followed by file tabs.

Types

t()

@type t() :: %MingaEditor.State.TabBar{
  active_id: MingaEditor.State.Tab.id(),
  next_id: MingaEditor.State.Tab.id(),
  next_workspace_id: pos_integer(),
  tabs: [MingaEditor.State.Tab.t()],
  workspaces: [MingaEditor.State.Workspace.t()]
}

Tab bar state.

Functions

accept_tab(tab_bar, accepted)

@spec accept_tab(t(), MingaEditor.State.Tab.t()) :: t()

Accepts a concrete tab only at its existing stable identity.

accept_workspace(tab_bar, accepted)

@spec accept_workspace(t(), MingaEditor.State.Workspace.t()) :: t()

Accepts a concrete workspace only at its existing stable identity.

active(tab_bar)

@spec active(t()) :: MingaEditor.State.Tab.t() | nil

Returns the active tab.

active_index(tab_bar)

@spec active_index(t()) :: non_neg_integer()

Returns the index of the active tab (0-based).

active_workspace(tb)

@spec active_workspace(t()) :: MingaEditor.State.Workspace.t() | nil

Returns the active workspace.

Derived from the active tab's group_id, not stored separately. The active workspace is always the workspace of the tab you're looking at.

active_workspace_id(tb)

@spec active_workspace_id(t()) :: non_neg_integer()

Returns the active workspace id, derived from the active tab.

add(tb, kind, label \\ "")

Adds a new tab after the active tab and makes it active.

Returns {updated_tab_bar, new_tab} so the caller can use the tab's id.

add_workspace(tb, label, session \\ nil)

@spec add_workspace(t(), String.t(), pid() | nil) ::
  {t(), MingaEditor.State.Workspace.t()}

Adds an agent workspace and returns {updated_tab_bar, workspace}.

The workspace is appended to the workspaces list. The session pid is stored so we can track which agent owns the workspace.

add_workspace_file(tab_bar, workspace_id, file_ref)

@spec add_workspace_file(t(), non_neg_integer(), Minga.Project.FileRef.t()) :: t()

Adds a file identity to the identified workspace.

any_attention?(tab_bar)

@spec any_attention?(t()) :: boolean()

Returns true if any tab has its attention flag set.

buffer_pids(tab_bar)

@spec buffer_pids(t()) :: [pid()]

Returns every live buffer pid represented by tab snapshots.

clear_attention(tab_bar, tab_id)

@spec clear_attention(t(), MingaEditor.State.Tab.id()) :: t()

Clears attention for the identified tab without changing tab identity or order.

clear_workspace_catchup_events(tab_bar, workspace_id)

@spec clear_workspace_catchup_events(t(), non_neg_integer()) :: t()

Clears replayed catch-up events for the identified workspace.

clear_workspace_session(tab_bar, workspace_id)

@spec clear_workspace_session(t(), non_neg_integer()) :: t()

Clears session state from the identified workspace.

count(tab_bar)

@spec count(t()) :: pos_integer()

Returns the number of tabs.

disclosure_tier(tb)

@spec disclosure_tier(t()) :: 0 | 1 | 2 | 3

Returns the progressive disclosure tier (0-3) based on agent workspace count.

drop_extension_feature_state_sources(tb)

@spec drop_extension_feature_state_sources(t()) :: t()

Drops snapshotted extension-owned feature state from every tab context.

drop_feature_state_source(tb, source)

@spec drop_feature_state_source(t(), MingaEditor.FeatureState.source()) :: t()

Drops snapshotted feature state owned by a source from every tab context.

filter_by_kind(tab_bar, kind)

@spec filter_by_kind(t(), MingaEditor.State.Tab.kind()) :: [MingaEditor.State.Tab.t()]

Returns all tabs matching the given kind.

find_by_kind(tab_bar, kind)

@spec find_by_kind(t(), MingaEditor.State.Tab.kind()) ::
  MingaEditor.State.Tab.t() | nil

Returns the first tab matching the given kind, or nil.

find_by_remote_session(tab_bar, server_name, session_id)

@spec find_by_remote_session(t(), String.t(), String.t()) ::
  MingaEditor.State.Tab.t() | nil

Returns the remote agent tab for a server/session id pair.

find_by_session(tab_bar, session_pid)

@spec find_by_session(t(), pid()) :: MingaEditor.State.Tab.t() | nil

Returns the agent tab whose session matches the given pid, or nil.

find_file_tab_in_workspace(tb, workspace_id, file_ref)

@spec find_file_tab_in_workspace(t(), non_neg_integer(), Minga.Project.FileRef.t()) ::
  MingaEditor.State.Tab.t() | nil

Finds the file tab in a workspace that represents the given file reference.

find_sessionless_agent(tab_bar)

@spec find_sessionless_agent(t()) :: MingaEditor.State.Tab.t() | nil

Returns an agent tab that has no session assigned, or nil.

Used by start_agent_session to find the correct tab to bind a new session to, avoiding ambiguity when multiple agent tabs exist. Falls back to the active tab if it's an agent tab.

find_workspace_by_remote_session(tab_bar, server_name, session_id)

@spec find_workspace_by_remote_session(t(), String.t(), String.t()) ::
  MingaEditor.State.Workspace.t() | nil

Returns the workspace matching a remote server/session id pair.

find_workspace_by_session(tab_bar, session_pid)

@spec find_workspace_by_session(t(), pid()) :: MingaEditor.State.Workspace.t() | nil

Returns the workspace matching the given session pid, or nil.

get(tab_bar, id)

Returns the tab with the given id, or nil.

get_workspace(tab_bar, id)

@spec get_workspace(t(), non_neg_integer()) :: MingaEditor.State.Workspace.t() | nil

Returns the workspace with the given id, or nil.

has_agent_workspaces?(tb)

@spec has_agent_workspaces?(t()) :: boolean()

Returns true if any agent workspaces exist.

has_tab?(tab_bar, id)

@spec has_tab?(t(), MingaEditor.State.Tab.id()) :: boolean()

Returns true if a tab with the given id exists.

insert(tb, kind, label \\ "")

Inserts a new tab next to the active tab without switching to it.

Returns {updated_tab_bar, new_tab}. The caller is responsible for calling switch_to/2 or EditorState.switch_tab/2 to activate it. This is the primitive that add/3 and EditorState.add_buffer/2 build on.

keep_only(tb, id)

@spec keep_only(t(), MingaEditor.State.Tab.id()) :: t()

Keeps only the tab with the given id. Returns unchanged when the tab is not present.

most_recent_of_kind(tab_bar, kind)

@spec most_recent_of_kind(t(), MingaEditor.State.Tab.kind()) ::
  MingaEditor.State.Tab.t() | nil

Returns the most recently used tab of the given kind that is NOT the active tab. Useful for "switch back to previous file/agent" commands.

Tabs are searched right-to-left from the active position (wrapping), so the nearest neighbor of the requested kind is returned.

move_active_tab_left(tb)

@spec move_active_tab_left(t()) :: t()

Moves the active tab one visible slot left within its workspace.

move_active_tab_right(tb)

@spec move_active_tab_right(t()) :: t()

Moves the active tab one visible slot right within its workspace.

move_tab_left(tb, id)

@spec move_tab_left(t(), MingaEditor.State.Tab.id()) :: t()

Moves the tab with the given id one visible slot left within its workspace.

move_tab_right(tb, id)

@spec move_tab_right(t(), MingaEditor.State.Tab.id()) :: t()

Moves the tab with the given id one visible slot right within its workspace.

move_tab_to_workspace(tb, tab_id, workspace_id)

@spec move_tab_to_workspace(t(), MingaEditor.State.Tab.id(), non_neg_integer()) :: t()

Moves a tab to a different workspace.

new(tab, project_root \\ nil)

@spec new(MingaEditor.State.Tab.t(), String.t() | nil) :: t()

Creates a tab bar with a single initial tab and the manual workspace.

new_empty(project_root \\ nil)

@spec new_empty(String.t() | nil) :: t()

Creates a tab bar with no tabs, for a zero-buffers launchpad startup (#2689).

active_id keeps its dangling default (1) — active/1 returns nil for an empty bar — so next_id starts at 2 to guarantee no restored or added tab ever collides with the dangling active id.

next(tb)

@spec next(t()) :: t()

Switches to the next visible file tab in the active workspace, wrapping around.

next_agent_workspace(tb)

@spec next_agent_workspace(t()) :: t()

Switches to the next agent workspace, wrapping around. No-op if no agent workspaces exist.

next_of_kind(tb, kind)

@spec next_of_kind(t(), MingaEditor.State.Tab.kind()) :: t()

Cycles to the next tab of the given kind, wrapping around. If the active tab is already of that kind, jumps to the next one. If the active tab is a different kind, jumps to the first of the requested kind. Returns unchanged if no tabs of that kind exist.

pin_tab(tb, id)

@spec pin_tab(t(), MingaEditor.State.Tab.id()) :: t()

Pins the tab with the given id. Returns unchanged when the tab is missing.

prev(tb)

@spec prev(t()) :: t()

Switches to the previous visible file tab in the active workspace, wrapping around.

prev_agent_workspace(tb)

@spec prev_agent_workspace(t()) :: t()

Switches to the previous agent workspace, wrapping around. No-op if no agent workspaces exist.

rebind_buffer_file(tab_bar, buffer_pid, file_ref)

@spec rebind_buffer_file(t(), pid(), Minga.Project.FileRef.t()) :: t()

Rebinds every matching file tab and workspace reference to one logical file identity.

refresh_tab_session(tab_bar, tab_id, old_pid, new_pid, status)

@spec refresh_tab_session(
  t(),
  MingaEditor.State.Tab.id(),
  pid(),
  pid(),
  MingaEditor.State.Tab.agent_status()
) :: t()

Refreshes a restarted session identity and status on the identified tab.

remote_workspaces_for_server(tab_bar, server_name)

@spec remote_workspaces_for_server(t(), String.t()) :: [
  MingaEditor.State.Workspace.t()
]

Returns remote workspaces for a server.

remove(tb, id)

@spec remove(t(), MingaEditor.State.Tab.id()) :: {:ok, t()} | :last_tab

Removes the tab with the given id.

If the removed tab was active, switches to the nearest neighbor (prefer right, then left). Returns {:ok, updated_tab_bar} or :last_tab if this is the only tab (can't remove the last one).

remove_file_tabs(tb)

@spec remove_file_tabs(t()) :: t()

Removes every file tab, leaving agent tabs (if any) in place.

Used when the workspace enters the zero-buffers launchpad (#2689): the file tab strip collapses instead of keeping phantom tabs. remove/2 keeps its can't-remove-last contract for every other caller. When the active tab was removed, the first remaining tab becomes active; active/1 tolerates an empty bar (returns nil).

remove_workspace(tb, workspace_id)

@spec remove_workspace(t(), non_neg_integer()) :: t()

Removes a workspace and migrates its tabs to the manual workspace (group_id 0).

Cannot remove the manual workspace.

remove_workspace_file(tab_bar, workspace_id, file_ref)

@spec remove_workspace_file(t(), non_neg_integer(), Minga.Project.FileRef.t()) :: t()

Removes a file identity from the identified workspace.

rename_workspace(tab_bar, workspace_id, name)

@spec rename_workspace(t(), non_neg_integer(), String.t()) :: t()

Renames the identified workspace.

reorder_tab(tb, id, new_index)

@spec reorder_tab(t(), MingaEditor.State.Tab.id(), non_neg_integer()) :: t()

Reorders a visible file tab within its workspace by zero-based visible index.

restore_workspaces(tb, workspaces, project_root)

@spec restore_workspaces(t(), [MingaEditor.State.Workspace.t()], String.t() | nil) ::
  t()

Replaces restored workspaces and recalculates the next workspace id.

retarget_tab_file(tab_bar, tab_id, file_ref, active?)

@spec retarget_tab_file(
  t(),
  MingaEditor.State.Tab.id(),
  Minga.Project.FileRef.t(),
  boolean()
) :: t()

Retargets one tab and its workspace to a concrete file identity.

retarget_workspace_file(tab_bar, workspace_id, old_file_ref, file_ref, active?)

@spec retarget_workspace_file(
  t(),
  non_neg_integer(),
  Minga.Project.FileRef.t() | nil,
  Minga.Project.FileRef.t(),
  boolean()
) :: t()

Retargets one file identity in the identified workspace.

scrub_dead_buffer(tb, pid)

@spec scrub_dead_buffer(t(), pid()) :: t()

Removes a dead buffer pid from every tab and workspace projection.

set_attention_by_session(tb, session_pid, value)

@spec set_attention_by_session(t(), pid(), boolean()) :: t()

Sets the attention flag on the tab matching the given session pid.

set_remote_connection_status(tb, server_name, status)

@spec set_remote_connection_status(
  t(),
  String.t(),
  MingaEditor.State.Tab.connection_status()
) :: t()

Updates all workspaces and projected tabs for a remote server to the given connection status.

set_tab_agent_status(tab_bar, tab_id, status)

@spec set_tab_agent_status(
  t(),
  MingaEditor.State.Tab.id(),
  MingaEditor.State.Tab.agent_status()
) :: t()

Records an agent status on the identified tab.

set_tab_attention(tab_bar, tab_id, attention?)

@spec set_tab_attention(t(), MingaEditor.State.Tab.id(), boolean()) :: t()

Records attention for the identified tab without changing tab identity or order.

set_tab_connection_status(tab_bar, tab_id, status)

@spec set_tab_connection_status(
  t(),
  MingaEditor.State.Tab.id(),
  MingaEditor.State.Tab.connection_status()
) :: t()

Records remote connection status on the identified tab.

set_tab_remote_session(tab_bar, tab_id, server_name, session_id, remote_pid)

@spec set_tab_remote_session(
  t(),
  MingaEditor.State.Tab.id(),
  String.t(),
  String.t(),
  pid()
) :: t()

Records a remote session identity on the identified tab.

set_tab_session(tab_bar, tab_id, session)

@spec set_tab_session(t(), MingaEditor.State.Tab.id(), pid() | nil) :: t()

Binds or clears the session owned by the identified tab.

set_workspace_active_file(tab_bar, workspace_id, file_ref)

@spec set_workspace_active_file(
  t(),
  non_neg_integer(),
  Minga.Project.FileRef.t() | nil
) :: t()

Selects the active file identity in the identified workspace.

set_workspace_agent_status(tab_bar, workspace_id, status)

@spec set_workspace_agent_status(
  t(),
  non_neg_integer(),
  MingaEditor.State.Tab.agent_status()
) :: t()

Records agent status on the identified workspace.

set_workspace_agent_ui(tab_bar, workspace_id, agent_ui)

@spec set_workspace_agent_ui(t(), non_neg_integer(), MingaEditor.Agent.UIState.t()) ::
  t()

Records the agent UI projection on the identified workspace.

set_workspace_icon(tab_bar, workspace_id, icon)

@spec set_workspace_icon(t(), non_neg_integer(), String.t()) :: t()

Sets the icon of the identified workspace.

set_workspace_pending_catchup_events(tab_bar, workspace_id, events)

@spec set_workspace_pending_catchup_events(t(), non_neg_integer(), [term()]) :: t()

Records pending durable catch-up events on the identified workspace.

set_workspace_project_view(tab_bar, workspace_id, project_view)

@spec set_workspace_project_view(t(), non_neg_integer(), term()) :: t()

Records project-view state on the identified workspace.

set_workspace_remote_connection_status(tab_bar, workspace_id, status)

@spec set_workspace_remote_connection_status(
  t(),
  non_neg_integer(),
  MingaEditor.State.Tab.connection_status()
) :: t()

Records remote connection status on the identified workspace.

set_workspace_review(tab_bar, workspace_id, review)

@spec set_workspace_review(
  t(),
  non_neg_integer(),
  MingaEditor.State.WorkspaceReview.t()
) :: t()

Records review state on the identified workspace.

set_workspace_session(tab_bar, workspace_id, session)

@spec set_workspace_session(t(), non_neg_integer(), pid() | nil) :: t()

Binds or clears the identified workspace session.

snapshot_and_switch(tab_bar, current_id, context, target_id)

Snapshots the outgoing tab and activates an existing target tab atomically.

switch_to(tb, id)

@spec switch_to(t(), MingaEditor.State.Tab.id()) :: t()

Switches the active tab to the one with the given id.

switch_to_workspace(tb, workspace_id)

@spec switch_to_workspace(t(), non_neg_integer()) :: t()

Switches to the given workspace by activating its first visible tab.

Returns unchanged if the workspace doesn't exist or has no visible tabs.

sync_workspace_agent_tab_projection(tb, workspace_id)

@spec sync_workspace_agent_tab_projection(t(), non_neg_integer()) :: t()
@spec sync_workspace_agent_tab_projection(t(), MingaEditor.State.Workspace.t()) :: t()

Synchronizes any agent-tab projection from workspace-owned lifecycle and remote metadata.

tab_at(arg1, index)

@spec tab_at(t(), pos_integer()) :: MingaEditor.State.Tab.t() | nil

Returns the tab at the given 1-based position index, or nil.

tabs_in_workspace(tab_bar, workspace_id)

@spec tabs_in_workspace(t(), non_neg_integer()) :: [MingaEditor.State.Tab.t()]

Returns all tabs belonging to the given workspace.

toggle_active_pin(tb)

@spec toggle_active_pin(t()) :: t()

Toggles the pinned state of the active tab.

unpin_tab(tb, id)

@spec unpin_tab(t(), MingaEditor.State.Tab.id()) :: t()

Unpins the tab with the given id. Returns unchanged when the tab is missing.

update_context(tb, id, context)

Updates the context of the tab with the given id.

update_label(tb, id, label)

@spec update_label(t(), MingaEditor.State.Tab.id(), String.t()) :: t()

Updates the label of the tab with the given id.

visible_file_tabs(tb)

@spec visible_file_tabs(t()) :: [MingaEditor.State.Tab.t()]

Returns visible file tabs for the active workspace.

visible_file_tabs(tab_bar, workspace_id)

@spec visible_file_tabs(t(), non_neg_integer()) :: [MingaEditor.State.Tab.t()]

Returns visible file tabs for the given workspace id. Agent chat tabs are excluded.

visible_workspace_tabs(tb)

@spec visible_workspace_tabs(t()) :: [MingaEditor.State.Tab.t()]

Returns visible content tabs for the active workspace.

visible_workspace_tabs(tb, workspace_id)

@spec visible_workspace_tabs(t(), non_neg_integer()) :: [MingaEditor.State.Tab.t()]

Returns visible content tabs for the given workspace id. Agent workspaces show their agent tab first, followed by file tabs.