MingaEditor.Window (Minga v0.1.0)

Copy Markdown View Source

A window is a viewport into a buffer.

Each window holds a reference to a buffer process and its own independent viewport (scroll position and dimensions). Multiple windows can reference the same buffer; edits in one are visible in all.

render_cache contains only bounded input-domain observations. Durable render state is owned by MingaEditor.Renderer.State.

Summary

Types

Unique identifier for a window.

t()

Functions

Returns the editor-owned authoritative-scroll request counter (#2652).

Folds all available ranges.

Folds the range containing the given buffer line.

Folds the outermost range containing the given buffer line and every nested range.

Returns true if this window has any active folds.

Records that an authoritative BEAM-initiated viewport jump must discard any frontend-held local scroll offset, even if the committed top is unchanged (#2652).

Records the committed viewport top of a frontend-reported free-scroll (#2661).

Creates a new window with the given id, buffer, and viewport dimensions.

Creates a new window with the given id, buffer, viewport dimensions, and cursor position.

Creates a new semantic agent chat window.

Creates a new window showing the zero-buffers launchpad surface (#2689).

Finds the next textobject position of the given type after (row, col).

Commits bounded viewport/cursor input metadata from a synchronous render.

Returns true if this window is a popup (has popup metadata attached).

Finds the previous textobject position of the given type before (row, col).

Records a wheel/trackpad scroll event so the render pipeline can tell a scroll gesture is in progress.

Remembers the buffer cursor last observed while this window was active.

Updates the viewport dimensions for this window, marking all lines dirty.

Scrolls the window horizontally by display columns.

Scrolls the window's viewport by delta lines and updates pinned state.

Sets the window cursor.

Updates the document symbols available for this window.

Updates the available fold ranges (from a provider). Preserves existing folds that still exist in the new ranges.

Sets whether the window should stay pinned to the bottom while content streams.

Updates textobject positions available for this window.

Stores the computed viewport for this window.

Switches the window from the launchpad back to a buffer.

Switches the window to the zero-buffers launchpad surface (#2689).

Toggles the fold at the given buffer line using the window's available fold ranges.

Unfolds all folds.

Unfolds the range containing the given buffer line.

Unfolds any folds that contain the given lines (used by search auto-unfold).

Unfolds every active fold inside the outermost range containing the given buffer line.

Types

id()

@type id() :: pos_integer()

Unique identifier for a window.

t()

@type t() :: %MingaEditor.Window{
  authoritative_scroll_seq: non_neg_integer(),
  content: MingaEditor.Window.Content.t(),
  cursor: Minga.Buffer.position(),
  document_symbols: [Minga.Language.Symbol.t()],
  fold_map: MingaEditor.FoldMap.t(),
  fold_ranges: [Minga.Editing.Fold.Range.t()],
  id: id(),
  pinned: boolean(),
  popup_meta: MingaEditor.UI.Popup.Active.t() | nil,
  render_cache: MingaEditor.Window.RenderCache.t(),
  scroll_detach_cursor: Minga.Buffer.position() | nil,
  scroll_echo_top: integer() | nil,
  scroll_velocity: MingaEditor.Window.ScrollVelocity.t(),
  textobject_positions: %{
    required(atom()) => [{non_neg_integer(), non_neg_integer()}]
  },
  viewport: MingaEditor.Viewport.t()
}

Functions

authoritative_scroll_seq(window)

@spec authoritative_scroll_seq(t()) :: non_neg_integer()

Returns the editor-owned authoritative-scroll request counter (#2652).

fold_all(window)

@spec fold_all(t()) :: t()

Folds all available ranges.

fold_at(window, line)

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

Folds the range containing the given buffer line.

fold_recursive_at(window, line)

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

Folds the outermost range containing the given buffer line and every nested range.

has_folds?(window)

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

Returns true if this window has any active folds.

mark_authoritative_scroll(window)

@spec mark_authoritative_scroll(t()) :: t()

Records that an authoritative BEAM-initiated viewport jump must discard any frontend-held local scroll offset, even if the committed top is unchanged (#2652).

Command handlers call this on the live window (editor process): at dispatch for the always-authoritative viewport commands, and from the success branches of failable jumps (search hits, mark jumps, bracket match, LSP goto). The MingaEditor.Commands @authoritative_scroll_commands comment documents the policy and is the source of truth for the command set. It is an editor-owned, top-level Window field (never in the render cache), a monotonic request counter incremented once per authoritative jump. Like scroll_echo_top, only the editor writes it, on the live window, so the async render writeback (which copies back only the render cache) cannot clobber it.

settle_scroll_seq/1 consumes it: the render cache remembers the last request count it settled against and advances scroll_seq whenever this counter moved past that baseline. Because the baseline (in the render cache) is overwritten to the observed counter every settle rather than the counter being cleared here, a single increment produces exactly one bump per rendered lineage and cannot latch (see MingaEditor.Window.RenderCache.settle_scroll_seq/4). This closes the same-top gap that the settle-time top comparison alone cannot see (a zz while already centered, a search hit already on screen).

mark_scroll_echo(window, echo_top)

@spec mark_scroll_echo(t(), integer()) :: t()

Records the committed viewport top of a frontend-reported free-scroll (#2661).

Set by the mouse-wheel/trackpad input path to the top it just committed. It is an editor-owned, top-level Window field (never in the render cache) so the async render writeback cannot clobber a newer value: only the input path ever writes it, on the live window. It is deliberately sticky — never cleared. A later wheel overwrites it; settle_scroll_seq/1 treats a viewport top equal to this value as an echo of the frontend's own report, so it does not advance scroll_seq (the "echo-loop guard": no re-anchor storm during a wheel/trackpad scroll gesture).

new(id, buffer, rows, cols)

@spec new(id(), pid(), pos_integer(), pos_integer()) :: t()

Creates a new window with the given id, buffer, and viewport dimensions.

new(id, buffer, rows, cols, cursor)

@spec new(id(), pid(), pos_integer(), pos_integer(), Minga.Buffer.position()) :: t()

Creates a new window with the given id, buffer, viewport dimensions, and cursor position.

new_agent_chat(id, rows, cols)

@spec new_agent_chat(id(), pos_integer(), pos_integer()) :: t()

Creates a new semantic agent chat window.

new_empty_state(id, rows, cols)

@spec new_empty_state(id(), pos_integer(), pos_integer()) :: t()

Creates a new window showing the zero-buffers launchpad surface (#2689).

next_textobject(window, type, arg)

@spec next_textobject(t(), atom(), {non_neg_integer(), non_neg_integer()}) ::
  {non_neg_integer(), non_neg_integer()} | nil

Finds the next textobject position of the given type after (row, col).

observe_render(window, viewport, buffer_version)

@spec observe_render(t(), MingaEditor.Viewport.t(), non_neg_integer()) :: t()

Commits bounded viewport/cursor input metadata from a synchronous render.

popup?(window)

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

Returns true if this window is a popup (has popup metadata attached).

prev_textobject(window, type, arg)

@spec prev_textobject(t(), atom(), {non_neg_integer(), non_neg_integer()}) ::
  {non_neg_integer(), non_neg_integer()} | nil

Finds the previous textobject position of the given type before (row, col).

record_scroll_event(window, now_ms, cursor_pos)

@spec record_scroll_event(t(), integer(), Minga.Buffer.position()) :: t()

Records a wheel/trackpad scroll event so the render pipeline can tell a scroll gesture is in progress.

Advances the scroll-rate estimator (scroll_follow_cursor?/3 reads its tier to suppress cursor re-anchoring mid-gesture) and marks scroll_detach_cursor at the cursor position at gesture start, so the viewport stays put until the cursor actually moves.

remember_cursor(window, cursor)

@spec remember_cursor(t(), Minga.Buffer.position()) :: t()

Remembers the buffer cursor last observed while this window was active.

resize(window, rows, cols)

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

Updates the viewport dimensions for this window, marking all lines dirty.

scroll_follow_cursor?(window, cursor_pos, now_ms)

@spec scroll_follow_cursor?(t(), Minga.Buffer.position(), integer()) ::
  {t(), boolean()}

scroll_horizontal(window, delta)

@spec scroll_horizontal(t(), integer()) :: t()

Scrolls the window horizontally by display columns.

scroll_velocity_tier(window, now_ms)

@spec scroll_velocity_tier(t(), integer()) :: MingaEditor.Window.ScrollVelocity.tier()

scroll_viewport(window, delta, total_lines)

@spec scroll_viewport(t(), integer(), non_neg_integer()) :: t()

Scrolls the window's viewport by delta lines and updates pinned state.

Scrolling up always unpins. Scrolling down re-pins only when the viewport reaches the bottom. total_lines is the buffer's line count.

Returns the updated window.

set_cursor(window, cursor)

@spec set_cursor(t(), Minga.Buffer.position()) :: t()

Sets the window cursor.

set_document_symbols(window, symbols)

@spec set_document_symbols(t(), [Minga.Language.Symbol.t()]) :: t()

Updates the document symbols available for this window.

set_fold_ranges(window, new_ranges)

@spec set_fold_ranges(t(), [Minga.Editing.Fold.Range.t()]) :: t()

Updates the available fold ranges (from a provider). Preserves existing folds that still exist in the new ranges.

set_pinned(window, pinned?)

@spec set_pinned(t(), boolean()) :: t()

Sets whether the window should stay pinned to the bottom while content streams.

set_textobject_positions(window, positions)

@spec set_textobject_positions(t(), map()) :: t()

Updates textobject positions available for this window.

set_viewport(window, viewport)

@spec set_viewport(t(), MingaEditor.Viewport.t()) :: t()

Stores the computed viewport for this window.

show_buffer(window, buffer)

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

Switches the window from the launchpad back to a buffer.

show_empty_state(window)

@spec show_empty_state(t()) :: t()

Switches the window to the zero-buffers launchpad surface (#2689).

The window stays open (the window tree never drops its last leaf); only its content changes, mirroring how agent chat panes host non-buffer content. Any cached buffer rendering is invalidated.

toggle_fold(window, line)

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

Toggles the fold at the given buffer line using the window's available fold ranges.

unfold_all(window)

@spec unfold_all(t()) :: t()

Unfolds all folds.

unfold_at(window, line)

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

Unfolds the range containing the given buffer line.

unfold_containing(window, lines)

@spec unfold_containing(t(), [non_neg_integer()]) :: t()

Unfolds any folds that contain the given lines (used by search auto-unfold).

unfold_recursive_at(window, line)

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

Unfolds every active fold inside the outermost range containing the given buffer line.