@fresh-editor/fresh-editor 0.1.4

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.
Files changed (38) hide show
  1. package/.gitignore +2 -0
  2. package/LICENSE +117 -0
  3. package/README.md +54 -0
  4. package/binary-install.js +212 -0
  5. package/binary.js +126 -0
  6. package/install.js +4 -0
  7. package/npm-shrinkwrap.json +900 -0
  8. package/package.json +100 -0
  9. package/plugins/README.md +121 -0
  10. package/plugins/clangd_support.md +20 -0
  11. package/plugins/clangd_support.ts +323 -0
  12. package/plugins/color_highlighter.ts +302 -0
  13. package/plugins/diagnostics_panel.ts +308 -0
  14. package/plugins/examples/README.md +245 -0
  15. package/plugins/examples/async_demo.ts +165 -0
  16. package/plugins/examples/bookmarks.ts +329 -0
  17. package/plugins/examples/buffer_query_demo.ts +110 -0
  18. package/plugins/examples/git_grep.ts +262 -0
  19. package/plugins/examples/hello_world.ts +93 -0
  20. package/plugins/examples/virtual_buffer_demo.ts +116 -0
  21. package/plugins/find_references.ts +357 -0
  22. package/plugins/git_find_file.ts +298 -0
  23. package/plugins/git_grep.ts +188 -0
  24. package/plugins/git_log.ts +1283 -0
  25. package/plugins/lib/fresh.d.ts +849 -0
  26. package/plugins/lib/index.ts +24 -0
  27. package/plugins/lib/navigation-controller.ts +214 -0
  28. package/plugins/lib/panel-manager.ts +218 -0
  29. package/plugins/lib/types.ts +72 -0
  30. package/plugins/lib/virtual-buffer-factory.ts +158 -0
  31. package/plugins/manual_help.ts +243 -0
  32. package/plugins/markdown_compose.ts +1207 -0
  33. package/plugins/merge_conflict.ts +1811 -0
  34. package/plugins/path_complete.ts +163 -0
  35. package/plugins/search_replace.ts +481 -0
  36. package/plugins/todo_highlighter.ts +204 -0
  37. package/plugins/welcome.ts +74 -0
  38. package/run-fresh.js +4 -0
@@ -0,0 +1,849 @@
1
+ /**
2
+ * Fresh Editor TypeScript Plugin API
3
+ *
4
+ * This file provides type definitions for the Fresh editor's TypeScript plugin system.
5
+ * Plugins have access to the global `editor` object which provides methods to:
6
+ * - Query editor state (buffers, cursors, viewports)
7
+ * - Modify buffer content (insert, delete text)
8
+ * - Add visual decorations (overlays, highlighting)
9
+ * - Interact with the editor UI (status messages, prompts)
10
+ *
11
+ * Note: types/fresh.d.ts is auto-generated from this template and src/ts_runtime.rs
12
+ *
13
+ * ## Core Concepts
14
+ *
15
+ * ### Buffers
16
+ * A buffer holds text content and may or may not be associated with a file.
17
+ * Each buffer has a unique numeric ID that persists for the editor session.
18
+ * Buffers track their content, modification state, cursor positions, and path.
19
+ * All text operations (insert, delete, read) use byte offsets, not character indices.
20
+ *
21
+ * ### Splits
22
+ * A split is a viewport pane that displays a buffer. The editor can have multiple
23
+ * splits arranged in a tree layout. Each split shows exactly one buffer, but the
24
+ * same buffer can be displayed in multiple splits. Use split IDs to control which
25
+ * pane displays which buffer.
26
+ *
27
+ * ### Virtual Buffers
28
+ * Special buffers created by plugins to display structured data like search results,
29
+ * diagnostics, or git logs. Virtual buffers support text properties (metadata attached
30
+ * to text ranges) that plugins can query when the user selects a line. Unlike normal
31
+ * buffers, virtual buffers are typically read-only and not backed by files.
32
+ *
33
+ * ### Text Properties
34
+ * Metadata attached to text ranges in virtual buffers. Each entry has text content
35
+ * and a properties object with arbitrary key-value pairs. Use `getTextPropertiesAtCursor`
36
+ * to retrieve properties at the cursor position (e.g., to get file/line info for "go to").
37
+ *
38
+ * ### Overlays
39
+ * Visual decorations applied to buffer text without modifying content. Overlays can
40
+ * change text color and add underlines. Use overlay IDs to manage them; prefix IDs
41
+ * enable batch removal (e.g., "lint:" prefix for all linter highlights).
42
+ *
43
+ * ### Modes
44
+ * Keybinding contexts that determine how keypresses are interpreted. Each buffer has
45
+ * a mode (e.g., "normal", "insert", "special"). Custom modes can inherit from parents
46
+ * and define buffer-local keybindings. Virtual buffers typically use custom modes.
47
+ */
48
+
49
+ declare global {
50
+ /**
51
+ * Global editor API object available to all TypeScript plugins
52
+ */
53
+ const editor: EditorAPI;
54
+ }
55
+
56
+ /**
57
+ * Buffer identifier (unique numeric ID)
58
+ */
59
+ type BufferId = number;
60
+
61
+ /** View token wire format for view transforms */
62
+ interface ViewTokenWire {
63
+ /** Source byte offset (null for injected view-only content) */
64
+ source_offset: number | null;
65
+ /** Token kind: Text, Newline, Space, or Break */
66
+ kind: ViewTokenWireKind;
67
+ }
68
+
69
+ /** View token kind discriminated union */
70
+ type ViewTokenWireKind =
71
+ | { Text: string }
72
+ | "Newline"
73
+ | "Space"
74
+ | "Break";
75
+
76
+ /** Layout hints for compose mode */
77
+ interface LayoutHints {
78
+ /** Optional compose width for centering/wrapping */
79
+ compose_width?: number | null;
80
+ /** Optional column guides for tables */
81
+ column_guides?: number[] | null;
82
+ }
83
+
84
+ /** Result from spawnProcess */
85
+ interface SpawnResult {
86
+ /** Complete stdout as string. Newlines preserved; trailing newline included. */
87
+ stdout: string;
88
+ /** Complete stderr as string. Contains error messages and warnings. */
89
+ stderr: string;
90
+ /** Process exit code. 0 usually means success; -1 if process was killed. */
91
+ exit_code: number;
92
+ }
93
+
94
+ /** File stat information */
95
+ interface FileStat {
96
+ /** Whether the path exists */
97
+ exists: boolean;
98
+ /** Whether the path is a file */
99
+ is_file: boolean;
100
+ /** Whether the path is a directory */
101
+ is_dir: boolean;
102
+ /** File size in bytes */
103
+ size: number;
104
+ /** Whether the file is read-only */
105
+ readonly: boolean;
106
+ }
107
+
108
+ /** Buffer information */
109
+ interface BufferInfo {
110
+ /** Unique buffer ID */
111
+ id: number;
112
+ /** File path (empty string if no path) */
113
+ path: string;
114
+ /** Whether buffer has unsaved changes */
115
+ modified: boolean;
116
+ /** Buffer length in bytes */
117
+ length: number;
118
+ }
119
+
120
+ /** Selection range */
121
+ interface SelectionRange {
122
+ /** Start byte position */
123
+ start: number;
124
+ /** End byte position */
125
+ end: number;
126
+ }
127
+
128
+ /** Cursor information with optional selection */
129
+ interface CursorInfo {
130
+ /** Byte position of the cursor */
131
+ position: number;
132
+ /** Selection range if text is selected, null otherwise */
133
+ selection?: SelectionRange | null;
134
+ }
135
+
136
+ /** Viewport information */
137
+ interface ViewportInfo {
138
+ /** Byte offset of the top-left visible position */
139
+ top_byte: number;
140
+ /** Column offset for horizontal scrolling */
141
+ left_column: number;
142
+ /** Viewport width in columns */
143
+ width: number;
144
+ /** Viewport height in rows */
145
+ height: number;
146
+ }
147
+
148
+ /** Suggestion for prompt autocomplete */
149
+ interface PromptSuggestion {
150
+ /** Display text for the suggestion */
151
+ text: string;
152
+ /** Optional description shown alongside */
153
+ description?: string | null;
154
+ /** Optional value to use instead of text when selected */
155
+ value?: string | null;
156
+ /** Whether the suggestion is disabled */
157
+ disabled?: boolean | null;
158
+ /** Optional keybinding hint */
159
+ keybinding?: string | null;
160
+ }
161
+
162
+ /** Directory entry from readDir */
163
+ interface DirEntry {
164
+ /** Entry name only (not full path). Join with parent path to get absolute path. */
165
+ name: string;
166
+ /** True if entry is a regular file */
167
+ is_file: boolean;
168
+ /** True if entry is a directory. Note: symlinks report the target type. */
169
+ is_dir: boolean;
170
+ }
171
+
172
+ /** Entry for virtual buffer content with embedded metadata */
173
+ interface TextPropertyEntry {
174
+ /** Text to display. Include trailing newline for separate lines. */
175
+ text: string;
176
+ /** Arbitrary metadata queryable via getTextPropertiesAtCursor. */
177
+ properties: Record<string, unknown>;
178
+ }
179
+
180
+ /** Configuration for createVirtualBufferInSplit */
181
+ interface CreateVirtualBufferOptions {
182
+ /** Buffer name shown in status bar (convention: "*Name*") */
183
+ name: string;
184
+ /** Mode for keybindings; define with defineMode first */
185
+ mode: string;
186
+ /** Prevent text modifications */
187
+ read_only: boolean;
188
+ /** Content with embedded metadata */
189
+ entries: TextPropertyEntry[];
190
+ /** Split ratio (0.3 = new pane gets 30% of space) */
191
+ ratio: number;
192
+ /** Split direction: "horizontal" (below) or "vertical" (side-by-side). Default: horizontal */
193
+ direction?: string | null;
194
+ /** If set and panel exists, update content instead of creating new buffer */
195
+ panel_id?: string | null;
196
+ /** Show line numbers gutter (default: true) */
197
+ show_line_numbers?: boolean | null;
198
+ /** Show cursor in buffer (default: true) */
199
+ show_cursors?: boolean | null;
200
+ /** Disable all editing commands (default: false) */
201
+ editing_disabled?: boolean | null;
202
+ }
203
+
204
+ /** Options for creating a virtual buffer in an existing split */
205
+ interface CreateVirtualBufferInExistingSplitOptions {
206
+ /** Display name (e.g., "*Commit Details*") */
207
+ name: string;
208
+ /** Mode name for buffer-local keybindings */
209
+ mode: string;
210
+ /** Whether the buffer is read-only */
211
+ read_only: boolean;
212
+ /** Entries with text and embedded properties */
213
+ entries: TextPropertyEntry[];
214
+ /** Target split ID where the buffer should be displayed */
215
+ split_id: number;
216
+ /** Whether to show line numbers in the buffer (default true) */
217
+ show_line_numbers?: boolean | null;
218
+ /** Whether to show cursors in the buffer (default true) */
219
+ show_cursors?: boolean | null;
220
+ /** Whether editing is disabled for this buffer (default false) */
221
+ editing_disabled?: boolean | null;
222
+ }
223
+
224
+ /** Options for creating a virtual buffer in the current split as a new tab */
225
+ interface CreateVirtualBufferInCurrentSplitOptions {
226
+ /** Display name (e.g., "*Help*") */
227
+ name: string;
228
+ /** Mode name for buffer-local keybindings */
229
+ mode: string;
230
+ /** Whether the buffer is read-only */
231
+ read_only: boolean;
232
+ /** Entries with text and embedded properties */
233
+ entries: TextPropertyEntry[];
234
+ /** Whether to show line numbers in the buffer (default false for help/docs) */
235
+ show_line_numbers?: boolean | null;
236
+ /** Whether to show cursors in the buffer (default true) */
237
+ show_cursors?: boolean | null;
238
+ /** Whether editing is disabled for this buffer (default false) */
239
+ editing_disabled?: boolean | null;
240
+ }
241
+
242
+ /**
243
+ * Main editor API interface
244
+ */
245
+ interface EditorAPI {
246
+ // === Status and Logging ===
247
+ /**
248
+ * Display a transient message in the editor's status bar
249
+ *
250
+ * The message will be shown until the next status update or user action.
251
+ * Use for feedback on completed operations (e.g., "File saved", "2 matches found").
252
+ * @param message - Text to display; keep short (status bar has limited width)
253
+ */
254
+ setStatus(message: string): void;
255
+ /**
256
+ * Log a debug message to the editor's trace output
257
+ *
258
+ * Messages appear in stderr when running with RUST_LOG=debug.
259
+ * Useful for plugin development and troubleshooting.
260
+ * @param message - Debug message; include context like function name and relevant values
261
+ */
262
+ debug(message: string): void;
263
+
264
+ // === Buffer Queries ===
265
+ /**
266
+ * Get the buffer ID of the focused editor pane
267
+ *
268
+ * Returns 0 if no buffer is active (rare edge case).
269
+ * Use this ID with other buffer operations like insertText.
270
+ */
271
+ getActiveBufferId(): number;
272
+ /**
273
+ * Get the byte offset of the primary cursor in the active buffer
274
+ *
275
+ * Returns 0 if no cursor exists. For multi-cursor scenarios, use getAllCursors
276
+ * to get all cursor positions with selection info.
277
+ * Note: This is a byte offset, not a character index (UTF-8 matters).
278
+ */
279
+ getCursorPosition(): number;
280
+ /**
281
+ * Get the absolute file path for a buffer
282
+ *
283
+ * Returns empty string for unsaved buffers or virtual buffers.
284
+ * The path is always absolute. Use this to determine file type,
285
+ * construct related paths, or display to the user.
286
+ * @param buffer_id - Target buffer ID
287
+ */
288
+ getBufferPath(buffer_id: number): string;
289
+ /**
290
+ * Get the total byte length of a buffer's content
291
+ *
292
+ * Returns 0 if buffer doesn't exist.
293
+ * @param buffer_id - Target buffer ID
294
+ */
295
+ getBufferLength(buffer_id: number): number;
296
+ /**
297
+ * Check if a buffer has been modified since last save
298
+ *
299
+ * Returns false if buffer doesn't exist or has never been saved.
300
+ * Virtual buffers are never considered modified.
301
+ * @param buffer_id - Target buffer ID
302
+ */
303
+ isBufferModified(buffer_id: number): boolean;
304
+ /**
305
+ * Get the ID of the focused split pane
306
+ *
307
+ * Use with focusSplit, setSplitBuffer, or createVirtualBufferInExistingSplit
308
+ * to manage split layouts.
309
+ */
310
+ getActiveSplitId(): number;
311
+ /**
312
+ * Get the line number of the primary cursor (1-indexed)
313
+ *
314
+ * Line numbers start at 1. Returns 1 if no cursor exists.
315
+ * For byte offset use getCursorPosition instead.
316
+ */
317
+ getCursorLine(): number;
318
+ /**
319
+ * Get byte offsets of all cursors (multi-cursor support)
320
+ *
321
+ * Returns array of positions; empty if no cursors. Primary cursor
322
+ * is typically first. For selection info use getAllCursors instead.
323
+ */
324
+ getAllCursorPositions(): number[];
325
+
326
+ // === Buffer Info Queries ===
327
+ /**
328
+ * Get full information about a buffer
329
+ * @param buffer_id - Buffer ID
330
+ * @returns BufferInfo object or null if buffer not found
331
+ */
332
+ getBufferInfo(buffer_id: number): BufferInfo | null;
333
+ /**
334
+ * List all open buffers
335
+ * @returns Array of BufferInfo objects
336
+ */
337
+ listBuffers(): BufferInfo[];
338
+ /**
339
+ * Get primary cursor with selection info
340
+ * @returns CursorInfo object or null if no cursor
341
+ */
342
+ getPrimaryCursor(): CursorInfo | null;
343
+ /**
344
+ * Get all cursors (for multi-cursor support)
345
+ * @returns Array of CursorInfo objects
346
+ */
347
+ getAllCursors(): CursorInfo[];
348
+ /**
349
+ * Get viewport information
350
+ * @returns ViewportInfo object or null if no viewport
351
+ */
352
+ getViewport(): ViewportInfo | null;
353
+
354
+ // === Prompt Operations ===
355
+ /**
356
+ * Start an interactive prompt
357
+ * @param label - Label to display (e.g., "Git grep: ")
358
+ * @param prompt_type - Type identifier (e.g., "git-grep")
359
+ * @returns true if prompt was started successfully
360
+ */
361
+ startPrompt(label: string, prompt_type: string): boolean;
362
+ /**
363
+ * Set suggestions for the current prompt
364
+ * @param suggestions - Array of suggestions to display
365
+ * @returns true if suggestions were set successfully
366
+ */
367
+ setPromptSuggestions(suggestions: PromptSuggestion[]): boolean;
368
+
369
+ // === Buffer Mutations ===
370
+ /**
371
+ * Insert text at a byte position in a buffer
372
+ *
373
+ * Text is inserted before the byte at position. Position must be valid
374
+ * (0 to buffer length). Insertion shifts all text after position.
375
+ * Operation is asynchronous; returns true if command was sent successfully.
376
+ * @param buffer_id - Target buffer ID
377
+ * @param position - Byte offset where text will be inserted (must be at char boundary)
378
+ * @param text - UTF-8 text to insert
379
+ */
380
+ insertText(buffer_id: number, position: number, text: string): boolean;
381
+ /**
382
+ * Delete a byte range from a buffer
383
+ *
384
+ * Deletes bytes from start (inclusive) to end (exclusive).
385
+ * Both positions must be at valid UTF-8 char boundaries.
386
+ * Operation is asynchronous; returns true if command was sent successfully.
387
+ * @param buffer_id - Target buffer ID
388
+ * @param start - Start byte offset (inclusive)
389
+ * @param end - End byte offset (exclusive)
390
+ */
391
+ deleteRange(buffer_id: number, start: number, end: number): boolean;
392
+ /**
393
+ * Clear all overlays in a namespace
394
+ * @param buffer_id - The buffer ID
395
+ * @param namespace - The namespace to clear
396
+ * @returns true if successful
397
+ */
398
+ clearNamespace(buffer_id: number, namespace: string): boolean;
399
+ /**
400
+ * Enable/disable line numbers for a buffer
401
+ * @param buffer_id - The buffer ID
402
+ * @param enabled - Whether to show line numbers
403
+ * @returns true if successful
404
+ */
405
+ setLineNumbers(buffer_id: number, enabled: boolean): boolean;
406
+ /**
407
+ * Submit a transformed view stream for a viewport
408
+ * @param buffer_id - Buffer to apply the transform to
409
+ * @param start - Viewport start byte
410
+ * @param end - Viewport end byte
411
+ * @param tokens - Array of tokens with source offsets
412
+ * @param source_map - Array of source offsets (null for injected)
413
+ * @param layout_hints - Optional layout hints (compose width, column guides)
414
+ */
415
+ submitViewTransform(buffer_id: number, split_id?: number | null, start: number, end: number, tokens: ViewTokenWire[], layout_hints?: LayoutHints | null): boolean;
416
+ /**
417
+ * Clear view transform for a buffer/split (returns to normal rendering)
418
+ * @param buffer_id - Buffer ID
419
+ * @param split_id - Optional split ID (uses active split if not specified)
420
+ * @returns true if clear succeeded
421
+ */
422
+ clearViewTransform(buffer_id: number, split_id?: number | null): boolean;
423
+ /**
424
+ * Insert text at the current cursor position in the active buffer
425
+ * @param text - The text to insert
426
+ * @returns true if insertion succeeded
427
+ */
428
+ insertAtCursor(text: string): boolean;
429
+ /**
430
+ * Register a custom command that can be triggered by keybindings or the command palette
431
+ * @param name - Unique command name (e.g., "my_plugin_action")
432
+ * @param description - Human-readable description
433
+ * @param action - JavaScript function name to call when command is triggered
434
+ * @param contexts - Comma-separated list of contexts (e.g., "normal,prompt")
435
+ * @returns true if command was registered
436
+ */
437
+ registerCommand(name: string, description: string, action: string, contexts: string): boolean;
438
+ /**
439
+ * Unregister a custom command by name
440
+ * @param name - The name of the command to unregister
441
+ * @returns true if the command was successfully unregistered
442
+ */
443
+ unregisterCommand(name: string): boolean;
444
+ /**
445
+ * Open a file in the editor, optionally at a specific location
446
+ * @param path - File path to open
447
+ * @param line - Line number to jump to (0 for no jump)
448
+ * @param column - Column number to jump to (0 for no jump)
449
+ * @returns true if file was opened
450
+ */
451
+ openFile(path: string, line: number, column: number): boolean;
452
+ /**
453
+ * Open a file in a specific split pane
454
+ * @param split_id - The split ID to open the file in
455
+ * @param path - File path to open
456
+ * @param line - Line number to jump to (0 for no jump)
457
+ * @param column - Column number to jump to (0 for no jump)
458
+ * @returns true if file was opened
459
+ */
460
+ openFileInSplit(split_id: number, path: string, line: number, column: number): boolean;
461
+ /**
462
+ * Send an arbitrary LSP request and receive the raw JSON response
463
+ * @param language - Language ID (e.g., "cpp")
464
+ * @param method - Full LSP method (e.g., "textDocument/switchSourceHeader")
465
+ * @param params - Optional request payload
466
+ * @returns Promise resolving to the JSON response value
467
+ */
468
+ sendLspRequest(language: string, method: string, params?: unknown | null): Promise<unknown>;
469
+ /**
470
+ * Set the ratio of a split container
471
+ * @param split_id - ID of the split
472
+ * @param ratio - Ratio between 0.0 and 1.0 (0.5 = equal split)
473
+ * @returns true if the ratio was set successfully
474
+ */
475
+ setSplitRatio(split_id: number, ratio: number): boolean;
476
+ /**
477
+ * Distribute all visible splits evenly
478
+ * This adjusts the ratios of all container splits so each leaf split gets equal space
479
+ * @returns true if the command was sent successfully
480
+ */
481
+ distributeSplitsEvenly(): boolean;
482
+ /**
483
+ * Set cursor position in a buffer (also scrolls viewport to show cursor)
484
+ * @param buffer_id - ID of the buffer
485
+ * @param position - Byte offset position for the cursor
486
+ * @returns true if the command was sent successfully
487
+ */
488
+ setBufferCursor(buffer_id: number, position: number): boolean;
489
+
490
+ // === Async Operations ===
491
+ /**
492
+ * Run an external command and capture its output
493
+ *
494
+ * Waits for process to complete before returning. For long-running processes,
495
+ * consider if this will block your plugin. Output is captured completely;
496
+ * very large outputs may use significant memory.
497
+ * @param command - Program name (searched in PATH) or absolute path
498
+ * @param args - Command arguments (each array element is one argument)
499
+ * @param cwd - Working directory; null uses editor's cwd
500
+ * @example
501
+ * const result = await editor.spawnProcess("git", ["log", "--oneline", "-5"]);
502
+ * if (result.exit_code !== 0) {
503
+ * editor.setStatus(`git failed: ${result.stderr}`);
504
+ * }
505
+ */
506
+ spawnProcess(command: string, args: string[], cwd?: string | null): Promise<SpawnResult>;
507
+
508
+ // === Overlay Operations ===
509
+ /**
510
+ * Add a colored highlight overlay to text without modifying content
511
+ *
512
+ * Overlays are visual decorations that persist until explicitly removed.
513
+ * Add an overlay (visual decoration) to a buffer
514
+ * Use namespaces for easy batch removal (e.g., "spell", "todo").
515
+ * Multiple overlays can apply to the same range; colors blend.
516
+ * @param buffer_id - Target buffer ID
517
+ * @param namespace - Optional namespace for grouping (use clearNamespace for batch removal)
518
+ * @param start - Start byte offset
519
+ * @param end - End byte offset
520
+ * @param r - Red (0-255)
521
+ * @param g - Green (0-255)
522
+ * @param b - Blue (0-255)
523
+ * @param underline - Add underline decoration
524
+ * @param bold - Use bold text
525
+ * @param italic - Use italic text
526
+ * @returns true if overlay was added
527
+ */
528
+ addOverlay(buffer_id: number, namespace: string, start: number, end: number, r: number, g: number, b: number, underline: boolean, bold: boolean, italic: boolean): boolean;
529
+ /**
530
+ * Remove a specific overlay by its handle
531
+ * @param buffer_id - The buffer ID
532
+ * @param handle - The overlay handle to remove
533
+ * @returns true if overlay was removed
534
+ */
535
+ removeOverlay(buffer_id: number, handle: string): boolean;
536
+ /**
537
+ * Clear all overlays that overlap with a byte range
538
+ * @param buffer_id - The buffer ID
539
+ * @param start - Start byte position (inclusive)
540
+ * @param end - End byte position (exclusive)
541
+ * @returns true if successful
542
+ */
543
+ clearOverlaysInRange(buffer_id: number, start: number, end: number): boolean;
544
+ /**
545
+ * Remove all overlays from a buffer
546
+ * @param buffer_id - The buffer ID
547
+ * @returns true if overlays were cleared
548
+ */
549
+ clearAllOverlays(buffer_id: number): boolean;
550
+ /**
551
+ * Add virtual text (inline decoration) at a position
552
+ * @param buffer_id - The buffer ID
553
+ * @param virtual_text_id - Unique identifier for this virtual text
554
+ * @param position - Byte position to insert at
555
+ * @param text - The virtual text to display
556
+ * @param r - Red color component (0-255)
557
+ * @param g - Green color component (0-255)
558
+ * @param b - Blue color component (0-255)
559
+ * @param before - Whether to insert before (true) or after (false) the position
560
+ * @returns true if virtual text was added
561
+ */
562
+ addVirtualText(buffer_id: number, virtual_text_id: string, position: number, text: string, r: number, g: number, b: number, before: boolean): boolean;
563
+ /**
564
+ * Remove virtual text by ID
565
+ * @param buffer_id - The buffer ID
566
+ * @param virtual_text_id - The virtual text ID to remove
567
+ * @returns true if virtual text was removed
568
+ */
569
+ removeVirtualText(buffer_id: number, virtual_text_id: string): boolean;
570
+ /**
571
+ * Remove all virtual texts with IDs starting with a prefix
572
+ * @param buffer_id - The buffer ID
573
+ * @param prefix - The prefix to match virtual text IDs against
574
+ * @returns true if any virtual texts were removed
575
+ */
576
+ removeVirtualTextsByPrefix(buffer_id: number, prefix: string): boolean;
577
+ /**
578
+ * Remove all virtual texts from a buffer
579
+ * @param buffer_id - The buffer ID
580
+ * @returns true if virtual texts were cleared
581
+ */
582
+ clearVirtualTexts(buffer_id: number): boolean;
583
+ /**
584
+ * Force a refresh of line display for a buffer
585
+ * @param buffer_id - The buffer ID
586
+ * @returns true if refresh was triggered
587
+ */
588
+ refreshLines(buffer_id: number): boolean;
589
+
590
+ // === File System Operations ===
591
+ /**
592
+ * Read entire file contents as UTF-8 string
593
+ *
594
+ * Throws if file doesn't exist, isn't readable, or isn't valid UTF-8.
595
+ * For binary files, this will fail. For large files, consider memory usage.
596
+ * @param path - File path (absolute or relative to cwd)
597
+ */
598
+ readFile(path: string): Promise<string>;
599
+ /**
600
+ * Write string content to a file, creating or overwriting
601
+ *
602
+ * Creates parent directories if they don't exist (behavior may vary).
603
+ * Replaces file contents entirely; use readFile + modify + writeFile for edits.
604
+ * @param path - Destination path (absolute or relative to cwd)
605
+ * @param content - UTF-8 string to write
606
+ */
607
+ writeFile(path: string, content: string): Promise<[]>;
608
+ /**
609
+ * Check if a path exists (file, directory, or symlink)
610
+ *
611
+ * Does not follow symlinks; returns true for broken symlinks.
612
+ * Use fileStat for more detailed information.
613
+ * @param path - Path to check (absolute or relative to cwd)
614
+ */
615
+ fileExists(path: string): boolean;
616
+ /**
617
+ * Get metadata about a file or directory
618
+ *
619
+ * Follows symlinks. Returns exists=false for non-existent paths
620
+ * rather than throwing. Size is in bytes; directories may report 0.
621
+ * @param path - Path to stat (absolute or relative to cwd)
622
+ */
623
+ fileStat(path: string): FileStat;
624
+ /**
625
+ * List directory contents
626
+ *
627
+ * Returns unsorted entries with type info. Entry names are relative
628
+ * to the directory (use pathJoin to construct full paths).
629
+ * Throws on permission errors or if path is not a directory.
630
+ * @param path - Directory path (absolute or relative to cwd)
631
+ * @example
632
+ * const entries = editor.readDir("/home/user");
633
+ * for (const e of entries) {
634
+ * const fullPath = editor.pathJoin("/home/user", e.name);
635
+ * }
636
+ */
637
+ readDir(path: string): DirEntry[];
638
+
639
+ // === Environment Operations ===
640
+ /**
641
+ * Get an environment variable
642
+ * @param name - Name of environment variable
643
+ * @returns Value if set, null if not set
644
+ */
645
+ getEnv(name: string): string;
646
+ /**
647
+ * Get the editor's current working directory
648
+ *
649
+ * Returns the editor's working directory (set when the editor was started).
650
+ * Use as base for resolving relative paths and spawning processes.
651
+ * Note: This returns the editor's stored working_dir, not process CWD,
652
+ * which is important for test isolation.
653
+ */
654
+ getCwd(): string;
655
+
656
+ // === Path Operations ===
657
+ /**
658
+ * Join path segments using the OS path separator
659
+ *
660
+ * Handles empty segments and normalizes separators.
661
+ * If a segment is absolute, previous segments are discarded.
662
+ * @param parts - Path segments to join
663
+ * @example
664
+ * pathJoin("/home", "user", "file.txt") // "/home/user/file.txt"
665
+ * pathJoin("relative", "/absolute") // "/absolute"
666
+ */
667
+ pathJoin(parts: string[]): string;
668
+ /**
669
+ * Get the parent directory of a path
670
+ *
671
+ * Returns empty string for root paths or paths without parent.
672
+ * Does not resolve symlinks or check existence.
673
+ * @param path - File or directory path
674
+ * @example
675
+ * pathDirname("/home/user/file.txt") // "/home/user"
676
+ * pathDirname("/") // ""
677
+ */
678
+ pathDirname(path: string): string;
679
+ /**
680
+ * Get the final component of a path
681
+ *
682
+ * Returns empty string for root paths.
683
+ * Does not strip file extension; use pathExtname for that.
684
+ * @param path - File or directory path
685
+ * @example
686
+ * pathBasename("/home/user/file.txt") // "file.txt"
687
+ * pathBasename("/home/user/") // "user"
688
+ */
689
+ pathBasename(path: string): string;
690
+ /**
691
+ * Get the file extension including the dot
692
+ *
693
+ * Returns empty string if no extension. Only returns the last extension
694
+ * for files like "archive.tar.gz" (returns ".gz").
695
+ * @param path - File path
696
+ * @example
697
+ * pathExtname("file.txt") // ".txt"
698
+ * pathExtname("archive.tar.gz") // ".gz"
699
+ * pathExtname("Makefile") // ""
700
+ */
701
+ pathExtname(path: string): string;
702
+ /**
703
+ * Check if a path is absolute
704
+ *
705
+ * On Unix: starts with "/". On Windows: starts with drive letter or UNC path.
706
+ * @param path - Path to check
707
+ */
708
+ pathIsAbsolute(path: string): boolean;
709
+
710
+ // === Event/Hook Operations ===
711
+ /**
712
+ * Subscribe to an editor event
713
+ *
714
+ * Handler must be a global function name (not a closure).
715
+ * Multiple handlers can be registered for the same event.
716
+ * Events: "buffer_save", "cursor_moved", "buffer_modified", etc.
717
+ * @param event_name - Event to subscribe to
718
+ * @param handler_name - Name of globalThis function to call with event data
719
+ * @example
720
+ * globalThis.onSave = (data) => {
721
+ * editor.setStatus(`Saved: ${data.path}`);
722
+ * };
723
+ * editor.on("buffer_save", "onSave");
724
+ */
725
+ on(event_name: string, handler_name: string): boolean;
726
+ /**
727
+ * Unregister an event handler
728
+ * @param event_name - Name of the event
729
+ * @param handler_name - Name of the handler to remove
730
+ * @returns true if handler was found and removed
731
+ */
732
+ off(event_name: string, handler_name: string): boolean;
733
+ /**
734
+ * Get list of registered handlers for an event
735
+ * @param event_name - Name of the event
736
+ * @returns Array of handler function names
737
+ */
738
+ getHandlers(event_name: string): string[];
739
+
740
+ // === Virtual Buffer Operations ===
741
+ /**
742
+ * Create a virtual buffer in a new horizontal split below current pane
743
+ *
744
+ * Use for results panels, diagnostics, logs, etc. The panel_id enables
745
+ * idempotent updates: if a panel with that ID exists, its content is replaced
746
+ * instead of creating a new split. Define the mode with defineMode first.
747
+ * @param options - Buffer configuration
748
+ * @example
749
+ * // First define the mode with keybindings
750
+ * editor.defineMode("search-results", "special", [
751
+ * ["Return", "search_goto"],
752
+ * ["q", "close_buffer"]
753
+ * ], true);
754
+ *
755
+ * // Then create the buffer
756
+ * const id = await editor.createVirtualBufferInSplit({
757
+ * name: "*Search*",
758
+ * mode: "search-results",
759
+ * read_only: true,
760
+ * entries: [
761
+ * { text: "src/main.rs:42: match\n", properties: { file: "src/main.rs", line: 42 } }
762
+ * ],
763
+ * ratio: 0.3,
764
+ * panel_id: "search"
765
+ * });
766
+ */
767
+ createVirtualBufferInSplit(options: CreateVirtualBufferOptions): Promise<number>;
768
+ /**
769
+ * Create a virtual buffer in an existing split
770
+ * @param options - Configuration for the virtual buffer
771
+ * @returns Promise resolving to the buffer ID of the created virtual buffer
772
+ */
773
+ createVirtualBufferInExistingSplit(options: CreateVirtualBufferInExistingSplitOptions): Promise<number>;
774
+ /**
775
+ * Create a virtual buffer in the current split as a new tab
776
+ * This is useful for help panels, documentation, etc. that should open
777
+ * alongside other buffers rather than in a separate split.
778
+ * @param options - Configuration for the virtual buffer
779
+ * @returns Promise resolving to the buffer ID of the created virtual buffer
780
+ */
781
+ createVirtualBuffer(options: CreateVirtualBufferInCurrentSplitOptions): Promise<number>;
782
+ /**
783
+ * Define a buffer mode with keybindings
784
+ * @param name - Mode name (e.g., "diagnostics-list")
785
+ * @param parent - Parent mode name for inheritance (e.g., "special"), or null
786
+ * @param bindings - Array of [key_string, command_name] pairs
787
+ * @param read_only - Whether buffers in this mode are read-only
788
+ * @returns true if mode was defined successfully
789
+ * @example
790
+ * editor.defineMode("diagnostics-list", "special", [
791
+ * ["Return", "diagnostics_goto"],
792
+ * ["q", "close_buffer"]
793
+ * ], true);
794
+ */
795
+ defineMode(name: string, parent?: string | null, bindings: Vec<(String, String): boolean;
796
+ /**
797
+ * Switch the current split to display a buffer
798
+ * @param buffer_id - ID of the buffer to show
799
+ * @returns true if buffer was shown successfully
800
+ */
801
+ showBuffer(buffer_id: number): boolean;
802
+ /**
803
+ * Close a buffer and remove it from all splits
804
+ * @param buffer_id - ID of the buffer to close
805
+ * @returns true if buffer was closed successfully
806
+ */
807
+ closeBuffer(buffer_id: number): boolean;
808
+ /**
809
+ * Focus a specific split
810
+ * @param split_id - ID of the split to focus
811
+ * @returns true if split was focused successfully
812
+ */
813
+ focusSplit(split_id: number): boolean;
814
+ /**
815
+ * Set the buffer displayed in a specific split
816
+ * @param split_id - ID of the split
817
+ * @param buffer_id - ID of the buffer to display in the split
818
+ * @returns true if the buffer was set successfully
819
+ */
820
+ setSplitBuffer(split_id: number, buffer_id: number): boolean;
821
+ /**
822
+ * Close a split (if not the last one)
823
+ * @param split_id - ID of the split to close
824
+ * @returns true if the split was closed successfully
825
+ */
826
+ closeSplit(split_id: number): boolean;
827
+ /**
828
+ * Get text properties at the cursor position in a buffer
829
+ * @param buffer_id - ID of the buffer to query
830
+ * @returns Array of property objects for text ranges containing the cursor
831
+ * @example
832
+ * const props = editor.getTextPropertiesAtCursor(bufferId);
833
+ * if (props.length > 0 && props[0].location) {
834
+ * editor.openFile(props[0].location.file, props[0].location.line, 0);
835
+ * }
836
+ */
837
+ getTextPropertiesAtCursor(buffer_id: number): Record<string, unknown>[];
838
+ /**
839
+ * Set the content of a virtual buffer with text properties
840
+ * @param buffer_id - ID of the virtual buffer
841
+ * @param entries - Array of text entries with properties
842
+ * @returns true if content was set successfully
843
+ */
844
+ setVirtualBufferContent(buffer_id: number, entries: TextPropertyEntry[]): boolean;
845
+
846
+ }
847
+
848
+ // Export for module compatibility
849
+ export {};