vim-sim 1.0.2
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/LICENSE +21 -0
- package/README.md +507 -0
- package/dist/index.d.ts +1380 -0
- package/dist/index.js +6928 -0
- package/dist/index.js.map +1 -0
- package/docs/ADVANCED-FEATURES-COMPLETE.md +547 -0
- package/docs/ADVANCED-FEATURES.md +460 -0
- package/docs/DEPLOYMENT-READY.md +194 -0
- package/docs/FINAL-SUMMARY.md +318 -0
- package/docs/IMPLEMENTATION-SUMMARY.md +298 -0
- package/docs/PARAGRAPH-MOTIONS-FIX.md +238 -0
- package/docs/QUICK-FIXES-SUMMARY.md +184 -0
- package/docs/QUICK-START-ADVANCED.md +260 -0
- package/docs/TEST-ANALYSIS-SUMMARY.md +213 -0
- package/docs/TEST-FAILURES-ANALYSIS.md +373 -0
- package/docs/TODO-COMPLETION-SUMMARY.md +326 -0
- package/package.json +79 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Cole Foster
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,507 @@
|
|
|
1
|
+
# vim-sim
|
|
2
|
+
|
|
3
|
+
[](https://github.com/colefoster/vim-sim/actions/workflows/ci.yml)
|
|
4
|
+
[](https://www.npmjs.com/package/vim-sim)
|
|
5
|
+
[](https://opensource.org/licenses/MIT)
|
|
6
|
+
[](https://www.typescriptlang.org/)
|
|
7
|
+
[](https://github.com/colefoster/vim-sim)
|
|
8
|
+
|
|
9
|
+
A complete, production-ready Vim editor simulation engine for Node.js. Implements the full Vim editing experience with 85%+ test coverage, including motions, operators, visual mode, text objects, macros, marks, undo/redo tree, spell checking, and more.
|
|
10
|
+
|
|
11
|
+
## Features
|
|
12
|
+
|
|
13
|
+
### Core Editing
|
|
14
|
+
- ✅ **All Basic Motions**: `h`, `j`, `k`, `l`, `w`, `b`, `e`, `W`, `B`, `E`, `0`, `$`, `^`, `gg`, `G`, `{`, `}`, `(`, `)`, `%`
|
|
15
|
+
- ✅ **Find & Till**: `f`, `F`, `t`, `T`, `;`, `,`
|
|
16
|
+
- ✅ **Operators**: `d`, `c`, `y`, `>`, `<`, `=`, `g~`, `gu`, `gU`
|
|
17
|
+
- ✅ **Visual Mode**: Character (`v`), Line (`V`), and Block (`<C-v>`) with all operators
|
|
18
|
+
- ✅ **Text Objects**: `iw`, `aw`, `i"`, `a"`, `i'`, `a'`, `i(`, `a(`, `i{`, `a{`, `i[`, `a[`, `it`, `at`, `ip`, `ap`, `is`, `as`
|
|
19
|
+
- ✅ **Insert Mode**: `i`, `I`, `a`, `A`, `o`, `O`, `s`, `S`, `c` commands
|
|
20
|
+
- ✅ **Replace & Change**: `r`, `R`, `~`, `J`, `gJ`
|
|
21
|
+
|
|
22
|
+
### Advanced Features
|
|
23
|
+
- ✅ **Undo/Redo Tree**: Full vim-style undo tree with branches (`u`, `<C-r>`, `g-`, `g+`)
|
|
24
|
+
- ✅ **Macros**: Record (`q`) and playback (`@`) with count support
|
|
25
|
+
- ✅ **Marks**: Local and global marks (`m`, `'`, `` ` ``)
|
|
26
|
+
- ✅ **Jump List**: `<C-o>`, `<C-i>` navigation
|
|
27
|
+
- ✅ **Registers**: Named, numbered, and special registers
|
|
28
|
+
- ✅ **Spell Checking**: Real-time with custom dictionaries
|
|
29
|
+
- ✅ **Completion**: Keyword, line, file, and omni completion
|
|
30
|
+
- ✅ **Folds**: Code folding support
|
|
31
|
+
- ✅ **Multiple Windows**: Split, navigate, and resize
|
|
32
|
+
- ✅ **Multiple Buffers**: File management and buffer navigation
|
|
33
|
+
|
|
34
|
+
### Text Formatting
|
|
35
|
+
- ✅ **Auto-indentation**: Smart indentation based on braces
|
|
36
|
+
- ✅ **Text Wrapping**: Format text with `gq`, `gw`
|
|
37
|
+
- ✅ **Alignment**: Column alignment support
|
|
38
|
+
- ✅ **Comment Toggling**: Smart comment handling
|
|
39
|
+
- ✅ **Digraphs**: 150+ special characters
|
|
40
|
+
|
|
41
|
+
## Installation
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
npm install vim-sim
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Quick Start
|
|
48
|
+
|
|
49
|
+
```typescript
|
|
50
|
+
import { Session } from 'vim-sim';
|
|
51
|
+
|
|
52
|
+
// Create a new vim session
|
|
53
|
+
const session = new Session();
|
|
54
|
+
|
|
55
|
+
// Load some text
|
|
56
|
+
session.handleKey(':');
|
|
57
|
+
session.handleKey('e');
|
|
58
|
+
session.handleKey(' ');
|
|
59
|
+
session.handleKey('f');
|
|
60
|
+
session.handleKey('i');
|
|
61
|
+
session.handleKey('l');
|
|
62
|
+
session.handleKey('e');
|
|
63
|
+
session.handleKey('.');
|
|
64
|
+
session.handleKey('t');
|
|
65
|
+
session.handleKey('x');
|
|
66
|
+
session.handleKey('t');
|
|
67
|
+
session.handleKey('Enter');
|
|
68
|
+
|
|
69
|
+
// Or set buffer content directly
|
|
70
|
+
import { State, Buffer, Cursor, Mode } from 'vim-sim';
|
|
71
|
+
|
|
72
|
+
const state = new State(
|
|
73
|
+
new Buffer('Hello, World!\nVim simulation is awesome!'),
|
|
74
|
+
new Cursor(0, 0),
|
|
75
|
+
null,
|
|
76
|
+
Mode.NORMAL
|
|
77
|
+
);
|
|
78
|
+
session.setState(state);
|
|
79
|
+
|
|
80
|
+
// Execute vim commands
|
|
81
|
+
session.handleKey('w'); // Move to next word
|
|
82
|
+
session.handleKey('d'); // Start delete operator
|
|
83
|
+
session.handleKey('w'); // Delete word
|
|
84
|
+
|
|
85
|
+
// Get the current state
|
|
86
|
+
const currentState = session.getState();
|
|
87
|
+
console.log(currentState.buffer.content); // "Hello, is awesome!"
|
|
88
|
+
console.log(currentState.cursor.line); // 0
|
|
89
|
+
console.log(currentState.cursor.column); // 7
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## API Documentation
|
|
93
|
+
|
|
94
|
+
### Session
|
|
95
|
+
|
|
96
|
+
The main entry point for vim simulation. Manages state and command execution.
|
|
97
|
+
|
|
98
|
+
```typescript
|
|
99
|
+
class Session {
|
|
100
|
+
constructor(config?: Partial<VimConfig>)
|
|
101
|
+
|
|
102
|
+
// Handle a single keypress
|
|
103
|
+
handleKey(key: string): void
|
|
104
|
+
|
|
105
|
+
// Get current editor state
|
|
106
|
+
getState(): State
|
|
107
|
+
|
|
108
|
+
// Set editor state
|
|
109
|
+
setState(state: State): void
|
|
110
|
+
|
|
111
|
+
// Get command history
|
|
112
|
+
getHistory(): CommandHistoryEntry[]
|
|
113
|
+
}
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
**Example:**
|
|
117
|
+
```typescript
|
|
118
|
+
const session = new Session({
|
|
119
|
+
tabSize: 4,
|
|
120
|
+
expandTab: true,
|
|
121
|
+
autoIndent: true
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
session.handleKey('i'); // Enter insert mode
|
|
125
|
+
session.handleKey('H');
|
|
126
|
+
session.handleKey('e');
|
|
127
|
+
session.handleKey('l');
|
|
128
|
+
session.handleKey('l');
|
|
129
|
+
session.handleKey('o');
|
|
130
|
+
session.handleKey('Escape'); // Back to normal mode
|
|
131
|
+
session.handleKey('0'); // Go to start of line
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### State
|
|
135
|
+
|
|
136
|
+
Represents the complete editor state at a point in time.
|
|
137
|
+
|
|
138
|
+
```typescript
|
|
139
|
+
class State {
|
|
140
|
+
constructor(
|
|
141
|
+
buffer: Buffer,
|
|
142
|
+
cursor: Cursor,
|
|
143
|
+
selection: Range | null,
|
|
144
|
+
mode: Mode,
|
|
145
|
+
// ... other optional parameters
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
readonly buffer: Buffer
|
|
149
|
+
readonly cursor: Cursor
|
|
150
|
+
readonly selection: Range | null
|
|
151
|
+
readonly mode: Mode
|
|
152
|
+
readonly desiredColumn: number | null
|
|
153
|
+
// ... many more properties
|
|
154
|
+
}
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### Buffer
|
|
158
|
+
|
|
159
|
+
Represents the text content being edited.
|
|
160
|
+
|
|
161
|
+
```typescript
|
|
162
|
+
class Buffer {
|
|
163
|
+
constructor(content: string = '')
|
|
164
|
+
|
|
165
|
+
readonly content: string
|
|
166
|
+
|
|
167
|
+
getLineCount(): number
|
|
168
|
+
getLine(index: number): string
|
|
169
|
+
getLines(): string[]
|
|
170
|
+
}
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
**Example:**
|
|
174
|
+
```typescript
|
|
175
|
+
const buffer = new Buffer('Line 1\nLine 2\nLine 3');
|
|
176
|
+
console.log(buffer.getLineCount()); // 3
|
|
177
|
+
console.log(buffer.getLine(1)); // "Line 2"
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
### Cursor
|
|
181
|
+
|
|
182
|
+
Represents cursor position (0-indexed).
|
|
183
|
+
|
|
184
|
+
```typescript
|
|
185
|
+
class Cursor {
|
|
186
|
+
constructor(line: number, column: number)
|
|
187
|
+
|
|
188
|
+
readonly line: number
|
|
189
|
+
readonly column: number
|
|
190
|
+
}
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
### Mode
|
|
194
|
+
|
|
195
|
+
Vim editing modes.
|
|
196
|
+
|
|
197
|
+
```typescript
|
|
198
|
+
enum Mode {
|
|
199
|
+
NORMAL = 'normal',
|
|
200
|
+
INSERT = 'insert',
|
|
201
|
+
VISUAL = 'visual',
|
|
202
|
+
VISUAL_LINE = 'visual_line',
|
|
203
|
+
VISUAL_BLOCK = 'visual_block',
|
|
204
|
+
COMMAND_LINE = 'command_line',
|
|
205
|
+
REPLACE = 'replace'
|
|
206
|
+
}
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
## Usage Examples
|
|
210
|
+
|
|
211
|
+
### Basic Text Editing
|
|
212
|
+
|
|
213
|
+
```typescript
|
|
214
|
+
import { Session, Buffer, State, Cursor, Mode } from 'vim-sim';
|
|
215
|
+
|
|
216
|
+
const session = new Session();
|
|
217
|
+
|
|
218
|
+
// Start with some text
|
|
219
|
+
session.setState(new State(
|
|
220
|
+
new Buffer('The quick brown fox\njumps over\nthe lazy dog'),
|
|
221
|
+
new Cursor(0, 0),
|
|
222
|
+
null,
|
|
223
|
+
Mode.NORMAL
|
|
224
|
+
));
|
|
225
|
+
|
|
226
|
+
// Delete a word: dw
|
|
227
|
+
session.handleKey('d');
|
|
228
|
+
session.handleKey('w');
|
|
229
|
+
|
|
230
|
+
console.log(session.getState().buffer.content);
|
|
231
|
+
// "quick brown fox\njumps over\nthe lazy dog"
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
### Visual Mode Selection
|
|
235
|
+
|
|
236
|
+
```typescript
|
|
237
|
+
const session = new Session();
|
|
238
|
+
session.setState(new State(
|
|
239
|
+
new Buffer('Hello World'),
|
|
240
|
+
new Cursor(0, 0),
|
|
241
|
+
null,
|
|
242
|
+
Mode.NORMAL
|
|
243
|
+
));
|
|
244
|
+
|
|
245
|
+
// Visual select and delete: vlllld
|
|
246
|
+
session.handleKey('v'); // Enter visual mode
|
|
247
|
+
session.handleKey('l'); // Extend selection
|
|
248
|
+
session.handleKey('l');
|
|
249
|
+
session.handleKey('l');
|
|
250
|
+
session.handleKey('l');
|
|
251
|
+
session.handleKey('d'); // Delete selection
|
|
252
|
+
|
|
253
|
+
console.log(session.getState().buffer.content); // " World"
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
### Using Text Objects
|
|
257
|
+
|
|
258
|
+
```typescript
|
|
259
|
+
const session = new Session();
|
|
260
|
+
session.setState(new State(
|
|
261
|
+
new Buffer('function test(arg) { return arg; }'),
|
|
262
|
+
new Cursor(0, 20), // Inside the parentheses
|
|
263
|
+
null,
|
|
264
|
+
Mode.NORMAL
|
|
265
|
+
));
|
|
266
|
+
|
|
267
|
+
// Delete inside parentheses: di(
|
|
268
|
+
session.handleKey('d');
|
|
269
|
+
session.handleKey('i');
|
|
270
|
+
session.handleKey('(');
|
|
271
|
+
|
|
272
|
+
console.log(session.getState().buffer.content);
|
|
273
|
+
// "function test() { return arg; }"
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
### Macros
|
|
277
|
+
|
|
278
|
+
```typescript
|
|
279
|
+
const session = new Session();
|
|
280
|
+
session.setState(new State(
|
|
281
|
+
new Buffer('line1\nline2\nline3'),
|
|
282
|
+
new Cursor(0, 0),
|
|
283
|
+
null,
|
|
284
|
+
Mode.NORMAL
|
|
285
|
+
));
|
|
286
|
+
|
|
287
|
+
// Record macro: qaIHello <Esc>jq
|
|
288
|
+
session.handleKey('q');
|
|
289
|
+
session.handleKey('a');
|
|
290
|
+
session.handleKey('I');
|
|
291
|
+
session.handleKey('H');
|
|
292
|
+
session.handleKey('e');
|
|
293
|
+
session.handleKey('l');
|
|
294
|
+
session.handleKey('l');
|
|
295
|
+
session.handleKey('o');
|
|
296
|
+
session.handleKey(' ');
|
|
297
|
+
session.handleKey('Escape');
|
|
298
|
+
session.handleKey('j');
|
|
299
|
+
session.handleKey('q');
|
|
300
|
+
|
|
301
|
+
// Replay macro twice: 2@a
|
|
302
|
+
session.handleKey('2');
|
|
303
|
+
session.handleKey('@');
|
|
304
|
+
session.handleKey('a');
|
|
305
|
+
|
|
306
|
+
console.log(session.getState().buffer.content);
|
|
307
|
+
// "Hello line1\nHello line2\nHello line3"
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
### Undo/Redo Tree
|
|
311
|
+
|
|
312
|
+
```typescript
|
|
313
|
+
const session = new Session();
|
|
314
|
+
const state = new State(
|
|
315
|
+
new Buffer('original text'),
|
|
316
|
+
new Cursor(0, 0),
|
|
317
|
+
null,
|
|
318
|
+
Mode.NORMAL
|
|
319
|
+
);
|
|
320
|
+
session.setState(state);
|
|
321
|
+
|
|
322
|
+
// Make some changes
|
|
323
|
+
session.handleKey('c');
|
|
324
|
+
session.handleKey('w');
|
|
325
|
+
session.handleKey('n');
|
|
326
|
+
session.handleKey('e');
|
|
327
|
+
session.handleKey('w');
|
|
328
|
+
session.handleKey('Escape');
|
|
329
|
+
|
|
330
|
+
// Undo: u
|
|
331
|
+
session.handleKey('u');
|
|
332
|
+
console.log(session.getState().buffer.content); // "original text"
|
|
333
|
+
|
|
334
|
+
// Redo: <C-r>
|
|
335
|
+
session.handleKey('<C-r>');
|
|
336
|
+
console.log(session.getState().buffer.content); // "new text"
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
### Working with Registers
|
|
340
|
+
|
|
341
|
+
```typescript
|
|
342
|
+
const session = new Session();
|
|
343
|
+
session.setState(new State(
|
|
344
|
+
new Buffer('Copy this text\nPaste here'),
|
|
345
|
+
new Cursor(0, 0),
|
|
346
|
+
null,
|
|
347
|
+
Mode.NORMAL
|
|
348
|
+
));
|
|
349
|
+
|
|
350
|
+
// Yank to register 'a': "ayy
|
|
351
|
+
session.handleKey('"');
|
|
352
|
+
session.handleKey('a');
|
|
353
|
+
session.handleKey('y');
|
|
354
|
+
session.handleKey('y');
|
|
355
|
+
|
|
356
|
+
// Move and paste: jp
|
|
357
|
+
session.handleKey('j');
|
|
358
|
+
session.handleKey('"');
|
|
359
|
+
session.handleKey('a');
|
|
360
|
+
session.handleKey('p');
|
|
361
|
+
|
|
362
|
+
console.log(session.getState().buffer.content);
|
|
363
|
+
// "Copy this text\nPaste here\nCopy this text"
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
## Advanced Usage
|
|
367
|
+
|
|
368
|
+
### Custom Configuration
|
|
369
|
+
|
|
370
|
+
```typescript
|
|
371
|
+
import { Session, ConfigManager } from 'vim-sim';
|
|
372
|
+
|
|
373
|
+
const session = new Session({
|
|
374
|
+
tabSize: 2,
|
|
375
|
+
expandTab: true,
|
|
376
|
+
autoIndent: true,
|
|
377
|
+
smartIndent: true,
|
|
378
|
+
textWidth: 80,
|
|
379
|
+
wrap: true,
|
|
380
|
+
spell: true
|
|
381
|
+
});
|
|
382
|
+
|
|
383
|
+
// Or update config after creation
|
|
384
|
+
const config = session.getState().configManager;
|
|
385
|
+
// Access config values as needed
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
### Spell Checking
|
|
389
|
+
|
|
390
|
+
```typescript
|
|
391
|
+
const session = new Session();
|
|
392
|
+
const state = session.getState();
|
|
393
|
+
|
|
394
|
+
// Enable spell checking
|
|
395
|
+
state.spellChecker.enable();
|
|
396
|
+
|
|
397
|
+
// Add custom words
|
|
398
|
+
state.spellChecker.addGoodWord('vim-sim');
|
|
399
|
+
|
|
400
|
+
// Check a word
|
|
401
|
+
const isCorrect = state.spellChecker.isCorrect('hello');
|
|
402
|
+
|
|
403
|
+
// Get suggestions
|
|
404
|
+
const suggestions = state.spellChecker.suggest('wrold');
|
|
405
|
+
console.log(suggestions); // ['world']
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
### Window Management
|
|
409
|
+
|
|
410
|
+
```typescript
|
|
411
|
+
const session = new Session();
|
|
412
|
+
const state = session.getState();
|
|
413
|
+
|
|
414
|
+
// Split window horizontally: <C-w>s
|
|
415
|
+
// Split window vertically: <C-w>v
|
|
416
|
+
// Navigate windows: <C-w>h/j/k/l
|
|
417
|
+
// Close window: <C-w>c
|
|
418
|
+
|
|
419
|
+
// Access window manager directly
|
|
420
|
+
const windowManager = state.windowManager;
|
|
421
|
+
const activeWindow = windowManager.getActiveWindow();
|
|
422
|
+
```
|
|
423
|
+
|
|
424
|
+
## TypeScript Support
|
|
425
|
+
|
|
426
|
+
This package is written in TypeScript and provides full type definitions.
|
|
427
|
+
|
|
428
|
+
```typescript
|
|
429
|
+
import type { State, Buffer, Cursor, Mode, Range, Command } from 'vim-sim';
|
|
430
|
+
|
|
431
|
+
function processVimState(state: State): void {
|
|
432
|
+
const { buffer, cursor, mode, selection } = state;
|
|
433
|
+
|
|
434
|
+
if (mode === Mode.VISUAL && selection) {
|
|
435
|
+
console.log(`Selected from ${selection.start} to ${selection.end}`);
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
```
|
|
439
|
+
|
|
440
|
+
## Testing
|
|
441
|
+
|
|
442
|
+
The vim-sim package has 85%+ test coverage with over 1700 passing tests.
|
|
443
|
+
|
|
444
|
+
```bash
|
|
445
|
+
# Run tests
|
|
446
|
+
npm test
|
|
447
|
+
|
|
448
|
+
# Run tests in watch mode
|
|
449
|
+
npm run test:watch
|
|
450
|
+
|
|
451
|
+
# Type check
|
|
452
|
+
npm run typecheck
|
|
453
|
+
```
|
|
454
|
+
|
|
455
|
+
## Performance
|
|
456
|
+
|
|
457
|
+
- **Immutable State**: All state updates return new state objects
|
|
458
|
+
- **Efficient Algorithms**: O(1) undo/redo, efficient text manipulation
|
|
459
|
+
- **Small Bundle**: Tree-shakeable ES modules
|
|
460
|
+
- **No DOM Dependencies**: Pure Node.js/TypeScript implementation
|
|
461
|
+
|
|
462
|
+
## Browser Support
|
|
463
|
+
|
|
464
|
+
While designed for Node.js, vim-sim works in browsers with a bundler:
|
|
465
|
+
|
|
466
|
+
```bash
|
|
467
|
+
npm install vim-sim
|
|
468
|
+
```
|
|
469
|
+
|
|
470
|
+
```typescript
|
|
471
|
+
import { Session } from 'vim-sim';
|
|
472
|
+
|
|
473
|
+
const session = new Session();
|
|
474
|
+
// Use in your web application
|
|
475
|
+
```
|
|
476
|
+
|
|
477
|
+
## Comparison with Other Vim Implementations
|
|
478
|
+
|
|
479
|
+
| Feature | vim-sim | CodeMirror Vim | Monaco Vim |
|
|
480
|
+
|---------|---------|----------------|------------|
|
|
481
|
+
| Standalone | ✅ | ❌ (requires CodeMirror) | ❌ (requires Monaco) |
|
|
482
|
+
| Node.js API | ✅ | ❌ | ❌ |
|
|
483
|
+
| Undo Tree | ✅ | ❌ | ❌ |
|
|
484
|
+
| Full Text Objects | ✅ | Partial | Partial |
|
|
485
|
+
| Macros | ✅ | ✅ | ❌ |
|
|
486
|
+
| Marks & Jumps | ✅ | Partial | Partial |
|
|
487
|
+
| Spell Checking | ✅ | ❌ | ❌ |
|
|
488
|
+
| TypeScript | ✅ | Partial | ✅ |
|
|
489
|
+
|
|
490
|
+
## Contributing
|
|
491
|
+
|
|
492
|
+
Contributions are welcome! Please read our [contributing guidelines](CONTRIBUTING.md) first.
|
|
493
|
+
|
|
494
|
+
## License
|
|
495
|
+
|
|
496
|
+
MIT © Cole Foster
|
|
497
|
+
|
|
498
|
+
## Documentation
|
|
499
|
+
|
|
500
|
+
For more detailed documentation, see:
|
|
501
|
+
- [API Documentation](docs/API.md)
|
|
502
|
+
- [Test Analysis](docs/TEST-ANALYSIS-SUMMARY.md)
|
|
503
|
+
- [Feature Documentation](docs/FINAL-SUMMARY.md)
|
|
504
|
+
|
|
505
|
+
## Acknowledgments
|
|
506
|
+
|
|
507
|
+
This project implements Vim's behavior as closely as possible to the original Vim editor by Bram Moolenaar.
|