escriba-mode 0.1.10

Modal state machine for escriba — Normal/Insert/Visual/VisualLine/Command + pending-operator + pending-count state.
Documentation

escriba-mode — modal state machine, typed as a sum so illegal mode field combinations are unrepresentable.

Phase 1: vim-ish Normal/Insert/Visual/VisualLine/Command. The earlier design was a product type — { mode, pending_count, pending_operator, minibuffer } — where nonsense like mode: Insert carrying a pending_operator: Some(Delete) was constructible and only kept sane by a runtime guard inside enter(). Per the org-level ★★ UNREPRESENTABILITY rule, the fix is structural: model the per-mode state as a SUM so each mode carries ONLY the data that is valid in that mode.

  • Normal carries the pending count (5dd) + pending operator (the d in dw) — these exist NOWHERE else.
  • Insert / VisualLine carry nothing.
  • Visual carries nothing in phase 1 (a future anchor: Position lands here, in the one variant where a visual anchor is meaningful).
  • Command carries ONLY the accumulating minibuffer line.

There is no way to construct a Command without dropping the pending operator, or an Insert that still holds a count — the type system refuses it. The only way to change mode is the typed transition methods (enter_* / enter / escape), so the per-mode invariant is enforced by construction at every transition, not re-checked by a guard.

Typestate destination: a future revision can promote this to a phantom-typestate Modal<P> where illegal transitions (not just illegal field combos) are E0599 compile errors. That is a larger ripple across the keymap-dispatch and runtime borrow sites; this sum type is the pragmatic first tier — illegal field combinations are already truly-unrepresentable, and the transition surface is sealed behind methods so the typestate promotion is a later, localized change.