MingaEditor.ChangeRecorder (Minga v0.1.0)

Copy Markdown View Source

Records editing changes as raw key sequences for dot repeat.

A pure functional module — no GenServer. The struct is embedded in MingaEditor.State and threaded through the editor's key dispatch.

Recording lifecycle

  1. A change begins (insert mode entry, operator key, single-key edit) → start_recording/1 clears the key buffer and sets recording: true.
  2. Each key event during the change → record_key/2 appends to the buffer.
  3. The change ends (Escape back to Normal, or operator completes) → stop_recording/1 copies the buffer into last_change.

During replay (replaying: true), the editor suppresses recording so the replayed keys don't overwrite the stored change.

Summary

Types

A key event: {codepoint, modifiers}.

t()

Functions

Buffers a key as a potential part of a future change (e.g., count digits, r prefix).

Cancels the current recording without saving.

Clears pending keys without saving them.

Returns the stored last-change key sequence, or nil if none.

Returns a fresh recorder with no recorded change.

Appends a key to the current recording.

Returns true if currently recording a change.

Replaces the count prefix in a recorded key sequence.

Returns true if currently replaying a change.

Begins recording a new change. Promotes any pending keys into the recording.

Begins recording only if not already recording. Preserves existing keys.

Sets the replaying flag. Recording is suppressed during replay.

Finalizes the current recording into last_change.

Clears the replaying flag.

Types

key()

@type key() :: {non_neg_integer(), non_neg_integer()}

A key event: {codepoint, modifiers}.

t()

@type t() :: %MingaEditor.ChangeRecorder{
  keys: [key()],
  last_change: [key()] | nil,
  pending_keys: [key()],
  recording: boolean(),
  replaying: boolean()
}

Functions

buffer_pending_key(rec, key)

@spec buffer_pending_key(t(), key()) :: t()

Buffers a key as a potential part of a future change (e.g., count digits, r prefix).

cancel_recording(rec)

@spec cancel_recording(t()) :: t()

Cancels the current recording without saving.

Discards the key buffer and stops recording. last_change is preserved.

clear_pending(rec)

@spec clear_pending(t()) :: t()

Clears pending keys without saving them.

get_last_change(change_recorder)

@spec get_last_change(t()) :: [key()] | nil

Returns the stored last-change key sequence, or nil if none.

new()

@spec new() :: t()

Returns a fresh recorder with no recorded change.

record_key(rec, key)

@spec record_key(t(), key()) :: t()

Appends a key to the current recording.

No-op if not currently recording.

recording?(change_recorder)

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

Returns true if currently recording a change.

replace_count(keys, new_count)

@spec replace_count([key()], non_neg_integer() | nil) :: [key()]

Replaces the count prefix in a recorded key sequence.

Strips any leading digit keys (the original count) and prepends digit keys for the new count. If new_count is nil or 1, returns the sequence with the original count stripped.

replaying?(change_recorder)

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

Returns true if currently replaying a change.

start_recording(rec)

@spec start_recording(t()) :: t()

Begins recording a new change. Promotes any pending keys into the recording.

start_recording_if_not(rec)

@spec start_recording_if_not(t()) :: t()

Begins recording only if not already recording. Preserves existing keys.

start_replay(rec)

@spec start_replay(t()) :: t()

Sets the replaying flag. Recording is suppressed during replay.

stop_recording(rec)

@spec stop_recording(t()) :: t()

Finalizes the current recording into last_change.

The key buffer is moved to last_change and recording stops.

stop_replay(rec)

@spec stop_replay(t()) :: t()

Clears the replaying flag.