π― Use case
This file lives under βvim/β, which covers Vim-style modal editing integrations. On the API surface it exposes Operator, FindType, TextObjScope, VimState, and CommandState (and more) β mainly types, interfaces, or factory objects. What the file header says: Vim Mode State Machine Types This file defines the complete state machine for vim input handling. The types ARE the documentation - reading them tells you how the system works. State Diagram: ``` VimState ββββββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββββ β I.
Generated from folder role, exports, dependency roots, and inline comments β not hand-reviewed for every path.
π§ Inline summary
Vim Mode State Machine Types This file defines the complete state machine for vim input handling. The types ARE the documentation - reading them tells you how the system works. State Diagram: ``` VimState ββββββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββββ β INSERT β NORMAL β β (tracks insertedText) β (CommandState machine) β β β β β β idle βββ¬β[d/c/y]βββΊ operator β β β ββ[1-9]βββββΊ count β β β ββ[fFtT]ββββΊ find β β β ββ[g]βββββββΊ g β β β ββ[r]βββββββΊ replace β β β ββ[><]ββββββΊ indent β β β β β β operator ββ¬β[motion]βββΊ execute β β β ββ[0-9]βββββΊ operatorCountβ
π€ Exports (heuristic)
OperatorFindTypeTextObjScopeVimStateCommandStatePersistentStateRecordedChangeOPERATORSisOperatorKeySIMPLE_MOTIONSFIND_KEYSTEXT_OBJ_SCOPESisTextObjScopeKeyTEXT_OBJ_TYPESMAX_VIM_COUNTcreateInitialVimStatecreateInitialPersistentState
π₯οΈ Source preview
/**
* Vim Mode State Machine Types
*
* This file defines the complete state machine for vim input handling.
* The types ARE the documentation - reading them tells you how the system works.
*
* State Diagram:
* ```
* VimState
* ββββββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββββ
* β INSERT β NORMAL β
* β (tracks insertedText) β (CommandState machine) β
* β β β
* β β idle βββ¬β[d/c/y]βββΊ operator β
* β β ββ[1-9]βββββΊ count β
* β β ββ[fFtT]ββββΊ find β
* β β ββ[g]βββββββΊ g β
* β β ββ[r]βββββββΊ replace β
* β β ββ[><]ββββββΊ indent β
* β β β
* β β operator ββ¬β[motion]βββΊ execute β
* β β ββ[0-9]βββββΊ operatorCountβ
* β β ββ[ia]ββββββΊ operatorTextObj
* β β ββ[fFtT]ββββΊ operatorFind β
* ββββββββββββββββββββββββββββββββ΄βββββββββββββββββββββββββββββββββββββββ
* ```
*/
// ============================================================================
// Core Types
// ============================================================================
export type Operator = 'delete' | 'change' | 'yank'
export type FindType = 'f' | 'F' | 't' | 'T'
export type TextObjScope = 'inner' | 'around'
// ============================================================================
// State Machine Types
// ============================================================================
/**
* Complete vim state. Mode determines what data is tracked.
*
* INSERT mode: Track text being typed (for dot-repeat)
* NORMAL mode: Track command being parsed (state machine)
*/
export type VimState =
| { mode: 'INSERT'; insertedText: string }
| { mode: 'NORMAL'; command: CommandState }
/**
* Command state machine for NORMAL mode.
*
* Each state knows exactly what input it's waiting for.
* TypeScript ensures exhaustive handling in switches.
*/
export type CommandState =
| { type: 'idle' }
| { type: 'count'; digits: string }
| { type: 'operator'; op: Operator; count: number }
| { type: 'operatorCount'; op: Operator; count: number; digits: string }
| { type: 'operatorFind'; op: Operator; count: number; find: FindType }
| {
type: 'operatorTextObj'
op: Operator
count: number
scope: TextObjScope
}
| { type: 'find'; find: FindType; count: number }
| { type: 'g'; count: number }
| { type: 'operatorG'; op: Operator; count: number }
| { type: 'replace'; count: number }
| { type: 'indent'; dir: '>' | '<'; count: number }
/**
* Persistent state that survives across commands.
* This is the "memory" of vim - what gets recalled for repeats and pastes.
*/
export type PersistentState = {
lastChange: RecordedChange | null
lastFind: { type: FindType; char: string } | null
register: string
registerIsLinewise: boolean
}
/**
* Recorded change for dot-repeat.
* Captures everything needed to replay a command.
*/
export type RecordedChange =
| { type: 'insert'; text: string }
| {
type: 'operator'
op: Operator
motion: string
count: number
}
| {
type: 'operatorTextObj'
op: Operator
objType: string
scope: TextObjScope
count: number
}
| {
type: 'operatorFind'
op: Operator
find: FindType
char: string
count: number
}
| { type: 'replace'; char: string; count: number }
| { type: 'x'; count: number }
| { type: 'toggleCase'; count: number }
| { type: 'indent'; dir: '>' | '<'; count: number }
| { type: 'openLine'; direction: 'above' | 'below' }
| { type: 'join'; count: number }
// ============================================================================
// Key Groups - Named constants, no magic strings
// ============================================================================
export const OPERATORS = {
d: 'delete',
c: 'change',
y: 'yank',
} as const satisfies Record<string, Operator>
export function isOperatorKey(key: string): key is keyof typeof OPERATORS {
return key in OPERATORS
}
export const SIMPLE_MOTIONS = new Set([
'h',
'l',
'j',
'k', // Basic movement
'w',
'b',
'e',
'W',
'B',
'E', // Word motions
'0',
'^',
'$', // Line positions
])
export const FIND_KEYS = new Set(['f', 'F', 't', 'T'])
export const TEXT_OBJ_SCOPES = {
i: 'inner',
a: 'around',
} as const satisfies Record<string, TextObjScope>
export function isTextObjScopeKey(
key: string,
): key is keyof typeof TEXT_OBJ_SCOPES {
return key in TEXT_OBJ_SCOPES
}
export const TEXT_OBJ_TYPES = new Set([
'w',
'W', // Word/WORD
'"',
"'",
'`', // Quotes
'(',
')',
'b', // Parens
'[',
']', // Brackets
'{',
'}',
'B', // Braces
'<',
'>', // Angle brackets
])
export const MAX_VIM_COUNT = 10000
// ============================================================================
// State Factories
// ============================================================================
export function createInitialVimState(): VimState {
return { mode: 'INSERT', insertedText: '' }
}
export function createInitialPersistentState(): PersistentState {
return {
lastChange: null,
lastFind: null,
register: '',
registerIsLinewise: false,
}
}