@vemjs/core 0.1.0

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/CHANGELOG.md ADDED
@@ -0,0 +1,69 @@
1
+ # @vemjs/core
2
+
3
+ ## 0.2.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 3fa4848: feat(lsp): implement JSON-RPC 2.0 client, document sync, diagnostics & completion
8
+
9
+ - Add `JsonRpcClient` — JSON-RPC 2.0 engine over WebSocket with pending-Map request/response correlation and notification dispatch
10
+ - Add `LSPClient` — full LSP lifecycle (initialize handshake, textDocument/didOpen, didChange, didClose, completion, hover, publishDiagnostics bridging)
11
+ - Add `Diagnostic` / `DiagnosticSeverity` types to `@vemjs/core`
12
+ - Add `VemEditorState.setDiagnostics()`, `getDiagnostics()`, `onPublishDiagnostics()` API
13
+ - Add `VemEditorState.getText()` public buffer content accessor
14
+
15
+ ### Patch Changes
16
+
17
+ - 0498765: chore: release infrastructure, package metadata, and documentation scaffolding
18
+
19
+ This changeset covers all release preparation work for the initial 0.1.0 publish:
20
+
21
+ **Package metadata** — Added `license`, `repository`, `keywords`, and `publishConfig` fields to
22
+ all four packages so they display correctly on npmjs.com with proper source links, license badges,
23
+ and searchable tags.
24
+
25
+ **CI/CD pipeline** — Rewrote `.github/workflows/ci.yml` and `release.yml`:
26
+
27
+ - `quality` job: build → test → lint (oxlint) → dead-code scan (knip) on every PR and push
28
+ - `publish` job: automatic `changeset publish` to npm on every merge to `main` via
29
+ `changesets/action@v1` using the `NPM_TOKEN` org secret
30
+
31
+ **Changesets** — Initialized `.changeset/` with a `config.json` configured for public access and
32
+ patch-level internal dependency updates, enabling a fully automated release flow.
33
+
34
+ **Tooling** — Added `knip.config.ts` (dead-code detection), `oxlintrc.json` (TypeScript-aware
35
+ lint rules), `.lintstagedrc.json` (auto-fix staged files on commit), and updated root
36
+ `package.json` scripts: `build`, `test`, `lint`, `knip`, `changeset`, `version-packages`,
37
+ `release`.
38
+
39
+ **Dependabot** — Configured weekly npm dependency scanning with dev/prod groups and
40
+ `@vectojs/*` major-version pin to avoid upstream breaking changes.
41
+
42
+ **Repository** — Updated root `README.md` with CI/npm/license badges and package table.
43
+ Updated `SECURITY.md` with all four `@vemjs/*` packages and coordinated-disclosure guidance.
44
+ Added GitHub topics (vim, editor, typescript, vectojs, canvas, modal-editing, lsp) and branch
45
+ protection requiring the `quality` status check before merging to `main`.
46
+
47
+ **Build hygiene** — Cleaned all `dist/` directories and rebuilt from source to ensure no
48
+ test artefacts are included in published tarballs. Verified `knip` reports zero issues.
49
+
50
+ ## 0.2.0 (unreleased)
51
+
52
+ ### Minor Changes
53
+
54
+ - Add `Diagnostic` / `DiagnosticSeverity` types
55
+ - Add `VemEditorState.setDiagnostics()`, `getDiagnostics()`, `onPublishDiagnostics()` for LSP diagnostic bridging
56
+ - Add `VemEditorState.getText()` public buffer content accessor
57
+
58
+ ## 0.1.0
59
+
60
+ ### Features
61
+
62
+ - Full Vim state machine: NORMAL / INSERT / VISUAL / COMMAND modes
63
+ - Cursor motions: `h j k l w b e W B E 0 ^ $ gg G`
64
+ - Operators: `d y c` + counts + text objects (`iw aw i" a"` etc.)
65
+ - `x`, `r`, `~`, `J`, yank/paste registers, `u` / `<C-r>` undo-redo
66
+ - `VimBuffer` with reactive `onChange` callbacks
67
+ - Plugin event hooks: `onDidOpenBuffer`, `onDidChangeBuffer`, `onDidChangeMode`
68
+ - Custom keybinding registration with chord prefix-match + Vim keystroke replay fallback
69
+ - `ConfigLoader` for dynamic ESM config file loading
package/README.md ADDED
@@ -0,0 +1,173 @@
1
+ # @vemjs/core
2
+
3
+ [![npm version](https://img.shields.io/npm/v/@vemjs/core.svg)](https://www.npmjs.com/package/@vemjs/core)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
5
+
6
+ The pure TypeScript, zero-dependency core state machine and Vim keybinding parser engine for the **Vem Editor**. It handles buffers, undo/redo states, custom keybindings, visual selections, and coordinates with Language Server Protocol (LSP) diagnostics.
7
+
8
+ ## Features
9
+
10
+ - **Pure Modal Editing Engine**: Fully decoupled state tracking for `NORMAL`, `INSERT`, `VISUAL`, and `COMMAND` modes.
11
+ - **Vim Parser & Motions**: Native parsing of Vim keyboard sequences. Supports counts, motion combinations (e.g. `2w`, `3j`), operators (`d`, `y`, `c`), and text objects (`iw`, `aw`, `i"`, `a"`, etc.).
12
+ - **Line-oriented Vim Buffer**: High-performance buffer with transaction tracking and a deep undo/redo stack (`UndoManager`).
13
+ - **Reactive Hooks**: Event triggers for buffer changes, mode switches, commands, and diagnostics to seamlessly integrate plugins and renderers.
14
+ - **Diagnostic Collection**: Structured APIs for storing, querying, and subscribing to compilation and linting diagnostics (errors, warnings, hints).
15
+ - **Extensible Configuration**: ESM-native configuration loading (`ConfigLoader`) for registering settings and keybindings.
16
+
17
+ ## Installation
18
+
19
+ ```bash
20
+ bun add @vemjs/core
21
+ # or via npm
22
+ npm install @vemjs/core
23
+ ```
24
+
25
+ ## Quick Start
26
+
27
+ Initialize the editor state machine and feed it keystrokes programmatically:
28
+
29
+ ```typescript
30
+ import { VemEditorState } from '@vemjs/core';
31
+
32
+ // Create a state machine preloaded with text
33
+ const editor = new VemEditorState('const greeting = "Hello World";\nconsole.log(greeting);\n');
34
+
35
+ // Subscribe to buffer changes
36
+ editor.onDidChangeBuffer(() => {
37
+ console.log('Buffer updated! Current text:\n', editor.getText());
38
+ });
39
+
40
+ // Subscribe to mode changes
41
+ editor.onDidChangeMode((mode) => {
42
+ console.log(`Switched to mode: ${mode}`);
43
+ });
44
+
45
+ // Currently in NORMAL mode; send keys to move cursor and insert text
46
+ editor.input('j'); // Move down to line 2
47
+ editor.input('$'); // Move cursor to end of line
48
+ editor.input('i'); // Transition to INSERT mode
49
+ editor.input(' '); // Type space
50
+ editor.input('/'); // Type comment character
51
+ editor.input('/'); // Type comment character
52
+ editor.input(' '); // Type space
53
+ editor.input('P'); // Type P
54
+ editor.input('r'); // Type r
55
+ editor.input('i'); // Type i
56
+ editor.input('n'); // Type n
57
+ editor.input('t'); // Type t
58
+ editor.input('<Esc>'); // Back to NORMAL mode
59
+ ```
60
+
61
+ ## API Reference
62
+
63
+ ### `VemEditorState`
64
+
65
+ The central state machine coordinator.
66
+
67
+ - `constructor(initialText?: string)`: Creates a new editor state.
68
+ - `input(key: string): void`: Processes a keypress string (e.g., `'a'`, `'h'`, `'<Esc>'`, `'<C-r>'`).
69
+ - `getMode(): EditorMode`: Returns the current active mode.
70
+ - `getText(): string`: Returns the complete content of the buffer.
71
+ - `getCursor(): Position`: Returns current cursor position `{ line: number, character: number }`.
72
+ - `getDiagnostics(): Diagnostic[]`: Gets current collection of diagnostics.
73
+ - `setDiagnostics(diagnostics: Diagnostic[]): void`: Replaces current diagnostics and notifies subscribers.
74
+ - `registerKeybinding(mode: EditorMode, keys: string, commandName: string)`: Binds a key sequence to a named command.
75
+ - `onDidChangeBuffer(cb: () => void): void`: Fires whenever the text inside the buffer changes.
76
+ - `onDidOpenBuffer(cb: () => void): void`: Fires when a new buffer opens.
77
+ - `onDidChangeMode(cb: (mode: EditorMode) => void): void`: Fires on editor mode switches.
78
+ - `onPublishDiagnostics(cb: (diagnostics: Diagnostic[]) => void): void`: Fires when new diagnostics are published.
79
+
80
+ ### `VimBuffer`
81
+
82
+ Encapsulates buffer rows. Accessible via `editorState.getBuffer()`.
83
+
84
+ - `getText(): string`: Get entire text.
85
+ - `setText(text: string): void`: Overwrite text.
86
+ - `getLine(lineIndex: number): string`: Get single line content.
87
+ - `getLinesCount(): number`: Get total lines.
88
+
89
+ ---
90
+
91
+ ## Vim Keybinding Reference
92
+
93
+ | Key | Mode | Description |
94
+ | ------------------ | ------ | ------------------------------------------------------------ |
95
+ | `h`, `j`, `k`, `l` | NORMAL | Move cursor Left, Down, Up, Right |
96
+ | `w`, `b`, `e` | NORMAL | Move forward/backward/end-of-word |
97
+ | `0`, `$` | NORMAL | Move to start/end of line |
98
+ | `gg`, `G` | NORMAL | Move to first/last line |
99
+ | `i`, `a` | NORMAL | Enter INSERT mode (before/after cursor) |
100
+ | `v` | NORMAL | Enter VISUAL mode (character selection) |
101
+ | `:` | NORMAL | Enter COMMAND mode |
102
+ | `d` | NORMAL | Delete operator (e.g., `dw` deletes word, `dd` deletes line) |
103
+ | `y` | NORMAL | Yank (copy) operator |
104
+ | `p` | NORMAL | Paste text from yank register |
105
+ | `u`, `<C-r>` | NORMAL | Undo / Redo |
106
+ | `<Esc>` | ANY | Return to NORMAL mode |
107
+
108
+ ---
109
+
110
+ ## Diagnostics API
111
+
112
+ Diagnostics are mapped to the standard LSP diagnostic severity levels:
113
+
114
+ ```typescript
115
+ import { VemEditorState, type Diagnostic } from '@vemjs/core';
116
+
117
+ const editor = new VemEditorState('let x: number = "hello";');
118
+
119
+ editor.onPublishDiagnostics((diagnostics) => {
120
+ console.log(`Received ${diagnostics.length} diagnostics.`);
121
+ for (const diag of diagnostics) {
122
+ console.log(`[${diag.severity.toUpperCase()}] Line ${diag.line}: ${diag.message}`);
123
+ }
124
+ });
125
+
126
+ // Setting diagnostics (typically done by @vemjs/lsp-client)
127
+ const errors: Diagnostic[] = [
128
+ {
129
+ line: 0,
130
+ startCharacter: 16,
131
+ endCharacter: 23,
132
+ severity: 'error',
133
+ message: "Type 'string' is not assignable to type 'number'.",
134
+ source: 'typescript-lsp',
135
+ },
136
+ ];
137
+
138
+ editor.setDiagnostics(errors);
139
+ ```
140
+
141
+ ## Architecture
142
+
143
+ The following diagram illustrates the relationship between `@vemjs/core` and the other packages:
144
+
145
+ ```mermaid
146
+ graph TD
147
+ subgraph Core Engine [@vemjs/core]
148
+ VemEditorState --> VimBuffer
149
+ VemEditorState --> UndoManager
150
+ end
151
+
152
+ subgraph Renderer [@vemjs/renderer-vecto]
153
+ VectoRenderer --> VemEditorState
154
+ VemEditorEntity --> VemEditorState
155
+ end
156
+
157
+ subgraph LSP Layer [@vemjs/lsp-client]
158
+ LSPClient --> VemEditorState
159
+ JsonRpcClient --> WebSocket
160
+ end
161
+
162
+ subgraph Plugins [@vemjs/plugin-api]
163
+ PluginRegistry --> VemEditorState
164
+ end
165
+ ```
166
+
167
+ ## Contributing
168
+
169
+ Please review [CONTRIBUTING.md](../../CONTRIBUTING.md) for details on our workflow and engineering guidelines.
170
+
171
+ ## License
172
+
173
+ This package is licensed under the MIT License - see the LICENSE file for details.
@@ -0,0 +1,16 @@
1
+ import type { VemEditorState } from './editor';
2
+ export interface VemConfig {
3
+ plugins?: any[];
4
+ keybindings?: Array<{
5
+ mode: any;
6
+ keys: string;
7
+ command: string;
8
+ }>;
9
+ }
10
+ export declare class ConfigLoader {
11
+ private editorState;
12
+ constructor(editorState: VemEditorState);
13
+ loadConfigFromObject(config: VemConfig, registry: any): Promise<void>;
14
+ loadConfigFromFile(configPath: string, registry: any): Promise<void>;
15
+ }
16
+ //# sourceMappingURL=ConfigLoader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ConfigLoader.d.ts","sourceRoot":"","sources":["../src/ConfigLoader.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAE/C,MAAM,WAAW,SAAS;IACxB,OAAO,CAAC,EAAE,GAAG,EAAE,CAAC;IAChB,WAAW,CAAC,EAAE,KAAK,CAAC;QAClB,IAAI,EAAE,GAAG,CAAC;QACV,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC,CAAC;CACJ;AAED,qBAAa,YAAY;IACvB,OAAO,CAAC,WAAW,CAAiB;gBAExB,WAAW,EAAE,cAAc;IAI1B,oBAAoB,CAAC,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC;IAcrE,kBAAkB,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC;CAUlF"}
@@ -0,0 +1,30 @@
1
+ export class ConfigLoader {
2
+ editorState;
3
+ constructor(editorState) {
4
+ this.editorState = editorState;
5
+ }
6
+ async loadConfigFromObject(config, registry) {
7
+ if (config.keybindings) {
8
+ for (const kb of config.keybindings) {
9
+ this.editorState.registerKeybinding(kb.mode, kb.keys, kb.command);
10
+ }
11
+ }
12
+ if (config.plugins) {
13
+ for (const plugin of config.plugins) {
14
+ registry.register(plugin);
15
+ }
16
+ }
17
+ }
18
+ async loadConfigFromFile(configPath, registry) {
19
+ try {
20
+ const configModule = await import(configPath);
21
+ const config = configModule.default || configModule;
22
+ await this.loadConfigFromObject(config, registry);
23
+ console.log(`Config loaded from [${configPath}].`);
24
+ }
25
+ catch (err) {
26
+ console.error(`Failed to load config from [${configPath}]:`, err);
27
+ }
28
+ }
29
+ }
30
+ //# sourceMappingURL=ConfigLoader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ConfigLoader.js","sourceRoot":"","sources":["../src/ConfigLoader.ts"],"names":[],"mappings":"AAWA,MAAM,OAAO,YAAY;IACf,WAAW,CAAiB;IAEpC,YAAY,WAA2B;QACrC,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC;IACjC,CAAC;IAEM,KAAK,CAAC,oBAAoB,CAAC,MAAiB,EAAE,QAAa;QAChE,IAAI,MAAM,CAAC,WAAW,EAAE,CAAC;YACvB,KAAK,MAAM,EAAE,IAAI,MAAM,CAAC,WAAW,EAAE,CAAC;gBACpC,IAAI,CAAC,WAAW,CAAC,kBAAkB,CAAC,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC;YACpE,CAAC;QACH,CAAC;QAED,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACnB,KAAK,MAAM,MAAM,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;gBACpC,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;YAC5B,CAAC;QACH,CAAC;IACH,CAAC;IAEM,KAAK,CAAC,kBAAkB,CAAC,UAAkB,EAAE,QAAa;QAC/D,IAAI,CAAC;YACH,MAAM,YAAY,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC,CAAC;YAC9C,MAAM,MAAM,GAAc,YAAY,CAAC,OAAO,IAAI,YAAY,CAAC;YAC/D,MAAM,IAAI,CAAC,oBAAoB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;YAClD,OAAO,CAAC,GAAG,CAAC,uBAAuB,UAAU,IAAI,CAAC,CAAC;QACrD,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,+BAA+B,UAAU,IAAI,EAAE,GAAG,CAAC,CAAC;QACpE,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,26 @@
1
+ import type { Position } from './index';
2
+ export declare class VimBuffer {
3
+ private lines;
4
+ private changeCallbacks;
5
+ constructor(initialText?: string);
6
+ onChange(callback: () => void): void;
7
+ private triggerChange;
8
+ getLines(): string[];
9
+ setLines(lines: string[]): void;
10
+ getLine(lineIdx: number): string;
11
+ getLineCount(): number;
12
+ insertText(pos: Position, text: string): Position;
13
+ deleteRange(start: Position, end: Position): void;
14
+ deleteLines(startLineIdx: number, endLineIdx: number): string[];
15
+ insertLine(lineIdx: number, text: string): void;
16
+ setLine(lineIdx: number, text: string): void;
17
+ getText(): string;
18
+ }
19
+ export declare class UndoManager {
20
+ private undoStack;
21
+ private redoStack;
22
+ push(lines: string[]): void;
23
+ undo(currentLines: string[]): string[] | null;
24
+ redo(currentLines: string[]): string[] | null;
25
+ }
26
+ //# sourceMappingURL=buffer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"buffer.d.ts","sourceRoot":"","sources":["../src/buffer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAExC,qBAAa,SAAS;IACpB,OAAO,CAAC,KAAK,CAAkB;IAC/B,OAAO,CAAC,eAAe,CAAsB;gBAEjC,WAAW,CAAC,EAAE,MAAM;IASzB,QAAQ,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,IAAI;IAI3C,OAAO,CAAC,aAAa;IAMd,QAAQ,IAAI,MAAM,EAAE;IAIpB,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI;IAQ/B,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM;IAOhC,YAAY,IAAI,MAAM;IAItB,UAAU,CAAC,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,GAAG,QAAQ;IA2BjD,WAAW,CAAC,KAAK,EAAE,QAAQ,EAAE,GAAG,EAAE,QAAQ,GAAG,IAAI;IA2BjD,WAAW,CAAC,YAAY,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE;IAW/D,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAK/C,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAO5C,OAAO,IAAI,MAAM;CAGzB;AAED,qBAAa,WAAW;IACtB,OAAO,CAAC,SAAS,CAAkB;IACnC,OAAO,CAAC,SAAS,CAAkB;IAE5B,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI;IAK3B,IAAI,CAAC,YAAY,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,GAAG,IAAI;IAM7C,IAAI,CAAC,YAAY,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,GAAG,IAAI;CAKrD"}
package/dist/buffer.js ADDED
@@ -0,0 +1,130 @@
1
+ export class VimBuffer {
2
+ lines = [''];
3
+ changeCallbacks = [];
4
+ constructor(initialText) {
5
+ if (initialText !== undefined) {
6
+ this.lines = initialText.split(/\r?\n/);
7
+ if (this.lines.length === 0) {
8
+ this.lines = [''];
9
+ }
10
+ }
11
+ }
12
+ onChange(callback) {
13
+ this.changeCallbacks.push(callback);
14
+ }
15
+ triggerChange() {
16
+ for (const cb of this.changeCallbacks) {
17
+ cb();
18
+ }
19
+ }
20
+ getLines() {
21
+ return [...this.lines];
22
+ }
23
+ setLines(lines) {
24
+ this.lines = [...lines];
25
+ if (this.lines.length === 0) {
26
+ this.lines = [''];
27
+ }
28
+ this.triggerChange();
29
+ }
30
+ getLine(lineIdx) {
31
+ if (lineIdx < 0 || lineIdx >= this.lines.length) {
32
+ return '';
33
+ }
34
+ return this.lines[lineIdx];
35
+ }
36
+ getLineCount() {
37
+ return this.lines.length;
38
+ }
39
+ insertText(pos, text) {
40
+ const line = this.getLine(pos.line);
41
+ const before = line.substring(0, pos.character);
42
+ const after = line.substring(pos.character);
43
+ const insertedLines = text.split(/\r?\n/);
44
+ if (insertedLines.length === 1) {
45
+ this.lines[pos.line] = before + insertedLines[0] + after;
46
+ this.triggerChange();
47
+ return {
48
+ line: pos.line,
49
+ character: pos.character + insertedLines[0].length,
50
+ };
51
+ }
52
+ else {
53
+ this.lines[pos.line] = before + insertedLines[0];
54
+ const middleLines = insertedLines.slice(1, insertedLines.length - 1);
55
+ const lastLine = insertedLines[insertedLines.length - 1] + after;
56
+ this.lines.splice(pos.line + 1, 0, ...middleLines, lastLine);
57
+ this.triggerChange();
58
+ return {
59
+ line: pos.line + insertedLines.length - 1,
60
+ character: insertedLines[insertedLines.length - 1].length,
61
+ };
62
+ }
63
+ }
64
+ deleteRange(start, end) {
65
+ let s = { ...start };
66
+ let e = { ...end };
67
+ // Ensure start is before end
68
+ if (s.line > e.line || (s.line === e.line && s.character > e.character)) {
69
+ const temp = s;
70
+ s = e;
71
+ e = temp;
72
+ }
73
+ const startLine = this.getLine(s.line);
74
+ const endLine = this.getLine(e.line);
75
+ const before = startLine.substring(0, s.character);
76
+ const after = endLine.substring(e.character);
77
+ this.lines[s.line] = before + after;
78
+ if (e.line > s.line) {
79
+ this.lines.splice(s.line + 1, e.line - s.line);
80
+ }
81
+ if (this.lines.length === 0) {
82
+ this.lines = [''];
83
+ }
84
+ this.triggerChange();
85
+ }
86
+ deleteLines(startLineIdx, endLineIdx) {
87
+ const min = Math.max(0, Math.min(startLineIdx, endLineIdx));
88
+ const max = Math.min(this.lines.length - 1, Math.max(startLineIdx, endLineIdx));
89
+ const deleted = this.lines.splice(min, max - min + 1);
90
+ if (this.lines.length === 0) {
91
+ this.lines = [''];
92
+ }
93
+ this.triggerChange();
94
+ return deleted;
95
+ }
96
+ insertLine(lineIdx, text) {
97
+ this.lines.splice(lineIdx, 0, text);
98
+ this.triggerChange();
99
+ }
100
+ setLine(lineIdx, text) {
101
+ if (lineIdx >= 0 && lineIdx < this.lines.length) {
102
+ this.lines[lineIdx] = text;
103
+ this.triggerChange();
104
+ }
105
+ }
106
+ getText() {
107
+ return this.lines.join('\n');
108
+ }
109
+ }
110
+ export class UndoManager {
111
+ undoStack = [];
112
+ redoStack = [];
113
+ push(lines) {
114
+ this.undoStack.push([...lines]);
115
+ this.redoStack = [];
116
+ }
117
+ undo(currentLines) {
118
+ if (this.undoStack.length === 0)
119
+ return null;
120
+ this.redoStack.push([...currentLines]);
121
+ return this.undoStack.pop() || null;
122
+ }
123
+ redo(currentLines) {
124
+ if (this.redoStack.length === 0)
125
+ return null;
126
+ this.undoStack.push([...currentLines]);
127
+ return this.redoStack.pop() || null;
128
+ }
129
+ }
130
+ //# sourceMappingURL=buffer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"buffer.js","sourceRoot":"","sources":["../src/buffer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,98 @@
1
+ import type { Position, EditorMode } from './index';
2
+ import { VimBuffer } from './buffer';
3
+ export interface RegisterContent {
4
+ text: string;
5
+ type: 'char' | 'line' | 'block';
6
+ }
7
+ export type DiagnosticSeverity = 'error' | 'warning' | 'info' | 'hint';
8
+ export interface Diagnostic {
9
+ /** Zero-based line number */
10
+ line: number;
11
+ /** Zero-based start character */
12
+ startCharacter: number;
13
+ /** Zero-based end character */
14
+ endCharacter: number;
15
+ severity: DiagnosticSeverity;
16
+ message: string;
17
+ /** Optional: source language server name, e.g. 'tsserver' */
18
+ source?: string;
19
+ }
20
+ export type VisualType = 'char' | 'line' | 'block';
21
+ export interface VisualSelection {
22
+ type: VisualType;
23
+ anchor: Position;
24
+ active: Position;
25
+ }
26
+ export declare class VemEditorState {
27
+ private mode;
28
+ private cursor;
29
+ private desiredCol;
30
+ private buffer;
31
+ private undoManager;
32
+ private register;
33
+ private pendingKeys;
34
+ private visualSelection;
35
+ private isInsertMutated;
36
+ private changeCallbacks;
37
+ private commandText;
38
+ private saveCallbacks;
39
+ private quitCallbacks;
40
+ private splitCallbacks;
41
+ private customKeybindings;
42
+ private didOpenBufferCallbacks;
43
+ private changeBufferCallbacks;
44
+ private changeModeCallbacks;
45
+ private pluginCommandCallbacks;
46
+ private diagnostics;
47
+ private publishDiagnosticsCallbacks;
48
+ constructor(initialText?: string);
49
+ onChange(callback: () => void): void;
50
+ private triggerChange;
51
+ onSave(callback: () => void): void;
52
+ onQuit(callback: () => void): void;
53
+ onSplit(callback: (direction: 'horizontal' | 'vertical') => void): void;
54
+ private triggerSave;
55
+ private triggerQuit;
56
+ private triggerSplit;
57
+ registerKeybinding(mode: EditorMode, keys: string, commandName: string): void;
58
+ onDidOpenBuffer(callback: () => void): void;
59
+ onDidChangeBuffer(callback: () => void): void;
60
+ onDidChangeMode(callback: (mode: EditorMode) => void): void;
61
+ onExecutePluginCommand(callback: (commandName: string) => void): void;
62
+ onPublishDiagnostics(callback: (diagnostics: Diagnostic[]) => void): void;
63
+ setDiagnostics(diagnostics: Diagnostic[]): void;
64
+ getDiagnostics(): Diagnostic[];
65
+ private triggerDidOpenBuffer;
66
+ private triggerChangeBuffer;
67
+ private triggerChangeMode;
68
+ private executePluginCommand;
69
+ getMode(): EditorMode;
70
+ getText(): string;
71
+ setMode(mode: EditorMode): void;
72
+ getCursor(): Position;
73
+ getBuffer(): VimBuffer;
74
+ getPendingKeys(): string[];
75
+ getVisualSelection(): VisualSelection | null;
76
+ getRegister(): RegisterContent | null;
77
+ getCommandText(): string;
78
+ handleKey(key: string): void;
79
+ private handleKeyStandard;
80
+ private handleCharInputInInsert;
81
+ private handleBackspaceInInsert;
82
+ private handleEnterInInsert;
83
+ private executeCommand;
84
+ private executeCommandLineText;
85
+ private executeVisualCommand;
86
+ private moveCursorByMotion;
87
+ private executeOperatorCommand;
88
+ private operateOnVisualSelection;
89
+ private moveToFirstNonWhitespace;
90
+ private moveCursorRightForInsert;
91
+ private moveToEndOfLine;
92
+ private deleteCharUnderCursor;
93
+ private paste;
94
+ private saveStateForUndo;
95
+ undo(): void;
96
+ redo(): void;
97
+ }
98
+ //# sourceMappingURL=editor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"editor.d.ts","sourceRoot":"","sources":["../src/editor.ts"],"names":[],"mappings":"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"}