@xortex/xcode 3.1.2 → 3.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/vim/types.ts ADDED
@@ -0,0 +1,199 @@
1
+ /**
2
+ * Vim Mode State Machine Types
3
+ *
4
+ * This file defines the complete state machine for vim input handling.
5
+ * The types ARE the documentation - reading them tells you how the system works.
6
+ *
7
+ * State Diagram:
8
+ * ```
9
+ * VimState
10
+ * ┌──────────────────────────────┬──────────────────────────────────────┐
11
+ * │ INSERT │ NORMAL │
12
+ * │ (tracks insertedText) │ (CommandState machine) │
13
+ * │ │ │
14
+ * │ │ idle ──┬─[d/c/y]──► operator │
15
+ * │ │ ├─[1-9]────► count │
16
+ * │ │ ├─[fFtT]───► find │
17
+ * │ │ ├─[g]──────► g │
18
+ * │ │ ├─[r]──────► replace │
19
+ * │ │ └─[><]─────► indent │
20
+ * │ │ │
21
+ * │ │ operator ─┬─[motion]──► execute │
22
+ * │ │ ├─[0-9]────► operatorCount│
23
+ * │ │ ├─[ia]─────► operatorTextObj
24
+ * │ │ └─[fFtT]───► operatorFind │
25
+ * └──────────────────────────────┴──────────────────────────────────────┘
26
+ * ```
27
+ */
28
+
29
+ // ============================================================================
30
+ // Core Types
31
+ // ============================================================================
32
+
33
+ export type Operator = 'delete' | 'change' | 'yank'
34
+
35
+ export type FindType = 'f' | 'F' | 't' | 'T'
36
+
37
+ export type TextObjScope = 'inner' | 'around'
38
+
39
+ // ============================================================================
40
+ // State Machine Types
41
+ // ============================================================================
42
+
43
+ /**
44
+ * Complete vim state. Mode determines what data is tracked.
45
+ *
46
+ * INSERT mode: Track text being typed (for dot-repeat)
47
+ * NORMAL mode: Track command being parsed (state machine)
48
+ */
49
+ export type VimState =
50
+ | { mode: 'INSERT'; insertedText: string }
51
+ | { mode: 'NORMAL'; command: CommandState }
52
+
53
+ /**
54
+ * Command state machine for NORMAL mode.
55
+ *
56
+ * Each state knows exactly what input it's waiting for.
57
+ * TypeScript ensures exhaustive handling in switches.
58
+ */
59
+ export type CommandState =
60
+ | { type: 'idle' }
61
+ | { type: 'count'; digits: string }
62
+ | { type: 'operator'; op: Operator; count: number }
63
+ | { type: 'operatorCount'; op: Operator; count: number; digits: string }
64
+ | { type: 'operatorFind'; op: Operator; count: number; find: FindType }
65
+ | {
66
+ type: 'operatorTextObj'
67
+ op: Operator
68
+ count: number
69
+ scope: TextObjScope
70
+ }
71
+ | { type: 'find'; find: FindType; count: number }
72
+ | { type: 'g'; count: number }
73
+ | { type: 'operatorG'; op: Operator; count: number }
74
+ | { type: 'replace'; count: number }
75
+ | { type: 'indent'; dir: '>' | '<'; count: number }
76
+
77
+ /**
78
+ * Persistent state that survives across commands.
79
+ * This is the "memory" of vim - what gets recalled for repeats and pastes.
80
+ */
81
+ export type PersistentState = {
82
+ lastChange: RecordedChange | null
83
+ lastFind: { type: FindType; char: string } | null
84
+ register: string
85
+ registerIsLinewise: boolean
86
+ }
87
+
88
+ /**
89
+ * Recorded change for dot-repeat.
90
+ * Captures everything needed to replay a command.
91
+ */
92
+ export type RecordedChange =
93
+ | { type: 'insert'; text: string }
94
+ | {
95
+ type: 'operator'
96
+ op: Operator
97
+ motion: string
98
+ count: number
99
+ }
100
+ | {
101
+ type: 'operatorTextObj'
102
+ op: Operator
103
+ objType: string
104
+ scope: TextObjScope
105
+ count: number
106
+ }
107
+ | {
108
+ type: 'operatorFind'
109
+ op: Operator
110
+ find: FindType
111
+ char: string
112
+ count: number
113
+ }
114
+ | { type: 'replace'; char: string; count: number }
115
+ | { type: 'x'; count: number }
116
+ | { type: 'toggleCase'; count: number }
117
+ | { type: 'indent'; dir: '>' | '<'; count: number }
118
+ | { type: 'openLine'; direction: 'above' | 'below' }
119
+ | { type: 'join'; count: number }
120
+
121
+ // ============================================================================
122
+ // Key Groups - Named constants, no magic strings
123
+ // ============================================================================
124
+
125
+ export const OPERATORS = {
126
+ d: 'delete',
127
+ c: 'change',
128
+ y: 'yank',
129
+ } as const satisfies Record<string, Operator>
130
+
131
+ export function isOperatorKey(key: string): key is keyof typeof OPERATORS {
132
+ return key in OPERATORS
133
+ }
134
+
135
+ export const SIMPLE_MOTIONS = new Set([
136
+ 'h',
137
+ 'l',
138
+ 'j',
139
+ 'k', // Basic movement
140
+ 'w',
141
+ 'b',
142
+ 'e',
143
+ 'W',
144
+ 'B',
145
+ 'E', // Word motions
146
+ '0',
147
+ '^',
148
+ '$', // Line positions
149
+ ])
150
+
151
+ export const FIND_KEYS = new Set(['f', 'F', 't', 'T'])
152
+
153
+ export const TEXT_OBJ_SCOPES = {
154
+ i: 'inner',
155
+ a: 'around',
156
+ } as const satisfies Record<string, TextObjScope>
157
+
158
+ export function isTextObjScopeKey(
159
+ key: string,
160
+ ): key is keyof typeof TEXT_OBJ_SCOPES {
161
+ return key in TEXT_OBJ_SCOPES
162
+ }
163
+
164
+ export const TEXT_OBJ_TYPES = new Set([
165
+ 'w',
166
+ 'W', // Word/WORD
167
+ '"',
168
+ "'",
169
+ '`', // Quotes
170
+ '(',
171
+ ')',
172
+ 'b', // Parens
173
+ '[',
174
+ ']', // Brackets
175
+ '{',
176
+ '}',
177
+ 'B', // Braces
178
+ '<',
179
+ '>', // Angle brackets
180
+ ])
181
+
182
+ export const MAX_VIM_COUNT = 10000
183
+
184
+ // ============================================================================
185
+ // State Factories
186
+ // ============================================================================
187
+
188
+ export function createInitialVimState(): VimState {
189
+ return { mode: 'INSERT', insertedText: '' }
190
+ }
191
+
192
+ export function createInitialPersistentState(): PersistentState {
193
+ return {
194
+ lastChange: null,
195
+ lastFind: null,
196
+ register: '',
197
+ registerIsLinewise: false,
198
+ }
199
+ }