Repository navigation
Expand file tree
/
Copy pathstate.ts
More file actions
97 lines (90 loc) · 2.99 KB
/
Copy pathstate.ts
File metadata and controls
97 lines (90 loc) · 2.99 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
/**
* Vim state machine - tracks current mode, pending operations, and repeat info.
*/
export type VimMode = "normal" | "insert" | "replace" | "visual" | "visual-line" | "command-line" | "operator-pending";
export interface RecordedChange {
/** The keys that triggered this change */
keys: string[];
/** Text inserted during insert mode (for dot-repeat) */
insertedText: string;
}
export interface VimState {
mode: VimMode;
/** Numeric prefix accumulator (0 = none) */
count: number;
/** Pending operator: 'd', 'c', 'y', '>', '<', etc. */
pendingOperator: string | null;
/** Count supplied before the pending operator (multiplied by motion count). */
pendingOperatorCount: number;
/** Current register ('"' = default) */
register: string;
/** Last recorded change for dot-repeat */
lastChange: RecordedChange | null;
/** Anchor position for visual mode */
visualAnchor: { line: number; col: number } | null;
/** Whether we're accumulating digits for a count */
countStarted: boolean;
/** Pending character motion: 'f', 'F', 't', 'T', or 'r' (waiting for next char) */
pendingCharMotion: string | null;
/** Whether we're waiting for the second key after 'g' (e.g., gg) */
pendingG: boolean;
/** Pending text object prefix: 'i' or 'a' (waiting for object key like w, ", (, etc.) */
pendingTextObjectPrefix: string | null;
/** Whether we're waiting for a register name after `"` */
pendingRegister: boolean;
/** Whether we're replaying a dot-repeat (suppress recording) */
isReplaying: boolean;
/** Remaining copies for a counted `O` insertion. */
openLineRepeatCount: number;
}
export function createInitialState(): VimState {
return {
mode: "insert",
count: 0,
pendingOperator: null,
pendingOperatorCount: 1,
register: '"',
lastChange: null,
visualAnchor: null,
countStarted: false,
pendingCharMotion: null,
pendingG: false,
pendingTextObjectPrefix: null,
pendingRegister: false,
isReplaying: false,
openLineRepeatCount: 1,
};
}
export function resetOperatorState(state: VimState): void {
state.count = 0;
state.countStarted = false;
state.pendingOperator = null;
state.pendingOperatorCount = 1;
state.pendingCharMotion = null;
state.pendingG = false;
state.pendingTextObjectPrefix = null;
state.pendingRegister = false;
state.register = '"';
}
export function hasPendingCommand(state: VimState): boolean {
return (
state.countStarted ||
state.pendingOperator !== null ||
state.pendingCharMotion !== null ||
state.pendingG ||
state.pendingTextObjectPrefix !== null ||
state.pendingRegister ||
state.register !== '"'
);
}
export function modeDisplayName(mode: VimMode): string {
switch (mode) {
case "normal": return "NORMAL";
case "insert": return "INSERT";
case "replace": return "REPLACE";
case "visual": return "VISUAL";
case "visual-line": return "V-LINE";
case "command-line": return "COMMAND";
case "operator-pending": return "OP-PENDING";
}
}