types.ts
vim/types.ts
No strong subsystem tag
200
Lines
6332
Bytes
17
Exports
0
Imports
10
Keywords
What this is
This page documents one file from the repository and includes its full source so you can read it without leaving the docs site.
Beginner explanation
This file is one piece of the larger system. Its name, directory, imports, and exports show where it fits. Start by reading the exports and related files first.
How it is used
Start from the exports list and related files. Those are the easiest clues for where this file fits into the system.
Expert explanation
Architecturally, this file intersects with general runtime concerns. It contains 200 lines, 0 detected imports, and 17 detected exports.
Important relationships
Detected exports
OperatorFindTypeTextObjScopeVimStateCommandStatePersistentStateRecordedChangeOPERATORSisOperatorKeySIMPLE_MOTIONSFIND_KEYSTEXT_OBJ_SCOPESisTextObjScopeKeyTEXT_OBJ_TYPESMAX_VIM_COUNTcreateInitialVimStatecreateInitialPersistentState
Keywords
countoperatormodemachineinsertfindfindtypetypesnormaltextobjscope
Detected imports
- No import paths detected.
Source notes
This page embeds the full file contents. Small or leaf files are still indexed honestly instead of being over-explained.
Full source
/**
* 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,
}
}