@fresh-editor/fresh-editor 0.2.2 → 0.2.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,72 @@
1
1
  # Release Notes
2
2
 
3
+ ## 0.2.4
4
+
5
+ ### Features
6
+
7
+ * **Markdown Compose Mode**: Distraction-free writing mode with concealed markup, soft breaks, table rendering, and mouse support. Split-view allows editing source and rendered markdown side-by-side with synchronized scrolling.
8
+
9
+ * **Vertical Rulers**: Configurable column rulers with add/remove commands via command palette. Per-buffer state and Settings UI JSON editor support (#1028).
10
+
11
+ * **Horizontal Scrollbar**: New horizontal scrollbar with drag support and toggle commands (#972).
12
+
13
+ * **Smooth Scrolling**: Cursor movement now scrolls one line at a time instead of jumping/recentering the viewport (#1040).
14
+
15
+ ### Improvements
16
+
17
+ * **Macro Keybinding**: F4 shortcut for Play Last Macro. Removed Ctrl+0-9 and Alt+Shift+0-9 macro keybindings (#700).
18
+
19
+ * **Configurable Clipboard**: New `clipboard` config with `use_osc52` and `use_system_clipboard` toggles to prevent hangs in certain terminals (#964). Useful for Putty and other terminals that sometimes cause Fresh to hang on OSC 52.
20
+
21
+ * **Scrollbar Visibility**: New `show_vertical_scrollbar` and `show_horizontal_scrollbar` config options (#974).
22
+
23
+ * **Package Manager**: Reinstall support for local-path packages.
24
+
25
+ * **File Explorer Persistence**: Show hidden and show gitignored toggles now persist to config immediately (#569).
26
+
27
+ ### Bug Fixes
28
+
29
+ * **Macro correctness**: Replaying a macro now respects the exact same effect as interactive flow.
30
+
31
+ * **Cursor Navigation**: Cursor up/down now lands at end-of-line when goal column is past content (#514).
32
+
33
+ * **Line Numbers**: Fixed line numbers leaking between splits due to shared margins state. Line numbers now live exclusively in per-split BufferViewState.
34
+
35
+ ### Plugin API
36
+
37
+ * **Plugin API v2**: Versioned plugin API with `createTerminal`, `sendTerminalInput`, `closeTerminal`, `getAllCursors`, and plugin state API. Improved type declarations in `fresh.d.ts` (#1045).
38
+
39
+ * **Split Labels**: Splits can be labeled to prevent files opening in managed splits. Labels persist across save/restore. New `before` option to place buffers left/top.
40
+
41
+ ### Internal
42
+
43
+ * Refactored per-buffer view state: cursors owned by SplitViewState, ComposeState extracted from EditorState.
44
+ * Conceal ranges, soft breaks, and overlay filtering by view_mode at render time.
45
+ * Plugin state snapshot reports active split's view_mode and compose flag.
46
+ * i18n updates for vertical rulers and macro shortcuts across all locales.
47
+ * PieceTree Performance: Use binary search instead of linear scan in line lookup.
48
+
49
+ ---
50
+
51
+ ## 0.2.3
52
+
53
+ ### Bug Fixes
54
+
55
+ * **Undo Corruption After Save**: Fixed undo corrupting text after a bulk edit (e.g. multi-cursor or replace-all) followed by save. Piece tree buffers are now restored alongside the tree during undo.
56
+
57
+ * **Theme Not Found After Restart**: Fixed theme reverting to default when the JSON `name` field differs from the filename (#1001).
58
+
59
+ * **AltGr+Shift Input on Windows**: Fixed AltGr+Shift key combinations not being recognized as text input (#993).
60
+
61
+ * **Winget Manifest**: Fixed `UpgradeBehavior` indentation causing schema validation failure in winget publishing.
62
+
63
+ ### Internal
64
+
65
+ * Added shadow model undo/redo property-based tests for increased piece tree correctness confidence.
66
+ * Added blog showcase system with animated GIF demos for the documentation site.
67
+
68
+ ---
69
+
3
70
  ## 0.2.2
4
71
 
5
72
  ### Bug Fixes
package/README.md CHANGED
@@ -1,51 +1,54 @@
1
1
  # Fresh
2
2
 
3
- A terminal-based text editor. [Official Website →](https://sinelaw.github.io/fresh/)
3
+ A modern, full-featured terminal text editor, **with zero configuration**. Familiar keybindings, mouse support, and IDE-level features — no learning curve required.
4
4
 
5
- **[📦 Installation Instructions](#installation)**
5
+ [Official Website](https://sinelaw.github.io/fresh/)  ·  [Documentation](https://getfresh.dev/docs)  ·  [Discord](https://discord.gg/qUutBj9t)  ·  [Contributing](#contributing)
6
6
 
7
- **[Contributing](#contributing)**
7
+ **[Quick Install](#installation):**   `curl https://raw.githubusercontent.com/sinelaw/fresh/refs/heads/master/scripts/install.sh | sh`
8
8
 
9
- **[Discord](https://discord.gg/qUutBj9t)**
9
+ ---
10
10
 
11
- ## Why?
11
+ ![Fresh Demo](docs/fresh-demo2.gif)
12
12
 
13
- Why another text editor? Fresh brings the intuitive, conventional UX of editors like VS Code and Sublime Text to the terminal.
13
+ Fresh brings the intuitive UX of VS Code and Sublime Text to the terminal. Standard keybindings, full mouse support, menus, and a command palette — everything works the way you'd expect, right out of the box. No modes, no memorizing shortcuts.
14
14
 
15
- While veterans like Emacs and Vim - and newer editors like Neovim and Helix - are excellent for power users who prefer modal, highly specialized workflows, they often present a steep learning curve for those used to standard GUI interactions. Fresh is built for the developer who wants a familiar, non-modal experience out-of-the-box, without sacrificing the speed and portability of the command line. Keyboard bindings, mouse support, menus, command palette etc. are all designed to be familiar to most modern users.
15
+ Built for real-world performance: Fresh handles [multi-gigabyte files](https://noamlewis.com/blog/2025/12/09/how-fresh-loads-huge-files-fast) with negligible memory overhead and delivers consistently low-latency input, regardless of file size.
16
16
 
17
- Architecturally, Fresh is built to handle multi-gigabyte files or slow network streams efficiently, maintaining a negligible memory overhead regardless of file size. While traditional editors struggle with latency and RAM bloat on large files, Fresh delivers consistent, high-speed performance on any scale.
17
+ ### Command Palette & Fuzzy Finder
18
18
 
19
- The goal for Fresh is to be an intuitive and accessible, high-performance terminal-based editor that "just works" on any hardware, for everyone.
19
+ One shortcut to find files, run commands, switch buffers, and jump to any line.
20
20
 
21
- ## Discovery & Ease of Use
21
+ ![Command Palette](docs/blog/productivity/command-palette/showcase.gif)
22
22
 
23
- Fresh is designed for discovery. It features native UIs, a full Menu system, and a powerful Command Palette. With full mouse support, transitioning from graphical editors is seamless.
23
+ ### Multi-Cursor Editing
24
24
 
25
- ## Modern Extensibility
25
+ Select and edit multiple occurrences simultaneously — the same workflow you know from graphical editors.
26
26
 
27
- Extend Fresh easily using modern tools. Plugins are written in TypeScript and run securely in a sandboxed Deno environment, providing access to a modern JavaScript ecosystem without compromising stability.
27
+ ![Multi-Cursor](docs/blog/editing/multi-cursor/showcase.gif)
28
28
 
29
- ## Low-Latency Performance
29
+ ### Themes & Customization
30
30
 
31
- Fresh is engineered for speed. It delivers a low-latency experience, with text appearing instantly. The editor is designed to be light and fast, reliably opening and editing [huge files up to multi-gigabyte sizes](https://noamlewis.com/blog/2025/12/09/how-fresh-loads-huge-files-fast) without slowdown.
31
+ Browse and apply color themes instantly. Full settings UI and interactive keybinding editor included.
32
32
 
33
- ## Comprehensive Feature Set
33
+ ![Select Theme](docs/blog/themes/select-theme/showcase.gif)
34
34
 
35
- - **File Management**: open/save/new/close, file explorer, tabs, auto-revert, git file finder
36
- - **Editing**: undo/redo, multi-cursor, block selection, smart indent, comments, clipboard
37
- - **Search & Replace**: incremental search, find in selection, query replace, git grep
38
- - **Navigation**: go to line/bracket, word movement, position history, bookmarks, error navigation
39
- - **Views & Layout**: split panes, line numbers, line wrap, backgrounds, markdown preview
40
- - **Language Server (LSP)**: go to definition, references, hover, code actions, rename, diagnostics, autocompletion
41
- - **Productivity**: command palette, menu bar, keyboard macros, git log, diagnostics panel
42
- - **Plugins & Extensibility**: TypeScript plugins, color highlighter, TODO highlighter, merge conflicts, path complete, keymaps
43
- - **Internationalization**: Multiple language support (see [`locales/`](locales/) for available languages), plugin translation system
35
+ See more feature demos: [Editing](https://getfresh.dev/docs/blog/editing) (search & replace, block selection, sort lines, ...) · [Productivity](https://getfresh.dev/docs/blog/productivity) (file explorer, split view, integrated terminal, ...) · [Themes](https://getfresh.dev/docs/blog/themes)
44
36
 
45
- ![Fresh Demo](docs/fresh-demo2.gif)
46
- ![Fresh Screenshot](docs/public/images/screenshot1.png)
47
- ![Fresh Screenshot](docs/public/images/screenshot2.png)
48
- ![Fresh Screenshot](docs/public/images/screenshot3.png)
37
+ ---
38
+
39
+ ## Feature Overview
40
+
41
+ | Category | Features |
42
+ |----------|----------|
43
+ | **File Management** | open/save/new/close, file explorer, tabs, auto-revert, git file finder |
44
+ | **Editing** | undo/redo, multi-cursor, block selection, smart indent, comments, clipboard |
45
+ | **Search & Replace** | incremental search, find in selection, query replace, git grep |
46
+ | **Navigation** | go to line/bracket, word movement, position history, bookmarks, error navigation |
47
+ | **Views & Layout** | split panes, line numbers, line wrap, backgrounds, markdown preview |
48
+ | **Language Server (LSP)** | go to definition, references, hover, code actions, rename, diagnostics, autocompletion |
49
+ | **Productivity** | command palette, menu bar, keyboard macros, git log, diagnostics panel |
50
+ | **Extensibility** | TypeScript plugins (sandboxed Deno), color highlighter, TODO highlighter, merge conflicts, path complete, keymaps |
51
+ | **Internationalization** | Multiple language support (see [`locales/`](locales/)), plugin translation system |
49
52
 
50
53
  ## Installation
51
54
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fresh-editor/fresh-editor",
3
- "version": "0.2.2",
3
+ "version": "0.2.4",
4
4
  "description": "A modern terminal-based text editor with plugin support",
5
5
  "repository": {
6
6
  "type": "git",
@@ -36,8 +36,11 @@
36
36
  "syntax_highlighting": true,
37
37
  "show_menu_bar": true,
38
38
  "show_tab_bar": true,
39
+ "show_vertical_scrollbar": true,
40
+ "show_horizontal_scrollbar": false,
39
41
  "use_terminal_bg": false,
40
42
  "cursor_style": "default",
43
+ "rulers": [],
41
44
  "tab_size": 4,
42
45
  "auto_indent": true,
43
46
  "scroll_offset": 3,
@@ -88,6 +91,14 @@
88
91
  "show_hidden": false
89
92
  }
90
93
  },
94
+ "clipboard": {
95
+ "description": "Clipboard settings (which clipboard methods to use)",
96
+ "$ref": "#/$defs/ClipboardConfig",
97
+ "default": {
98
+ "use_osc52": true,
99
+ "use_system_clipboard": true
100
+ }
101
+ },
91
102
  "terminal": {
92
103
  "description": "Terminal settings",
93
104
  "$ref": "#/$defs/TerminalConfig",
@@ -230,6 +241,18 @@
230
241
  "default": true,
231
242
  "x-section": "Display"
232
243
  },
244
+ "show_vertical_scrollbar": {
245
+ "description": "Whether the vertical scrollbar is visible in each split pane.\nCan be toggled at runtime via command palette or keybinding.\nDefault: true",
246
+ "type": "boolean",
247
+ "default": true,
248
+ "x-section": "Display"
249
+ },
250
+ "show_horizontal_scrollbar": {
251
+ "description": "Whether the horizontal scrollbar is visible in each split pane.\nThe horizontal scrollbar appears when line wrap is disabled and content extends beyond the viewport.\nCan be toggled at runtime via command palette or keybinding.\nDefault: false",
252
+ "type": "boolean",
253
+ "default": false,
254
+ "x-section": "Display"
255
+ },
233
256
  "use_terminal_bg": {
234
257
  "description": "Use the terminal's default background color instead of the theme's editor background.\nWhen enabled, the editor background inherits from the terminal emulator,\nallowing transparency or custom terminal backgrounds to show through.\nDefault: false",
235
258
  "type": "boolean",
@@ -242,6 +265,17 @@
242
265
  "default": "default",
243
266
  "x-section": "Display"
244
267
  },
268
+ "rulers": {
269
+ "description": "Vertical ruler lines at specific column positions.\nDraws subtle vertical lines to help with line length conventions.\nExample: [80, 120] draws rulers at columns 80 and 120.\nDefault: [] (no rulers)",
270
+ "type": "array",
271
+ "items": {
272
+ "type": "integer",
273
+ "format": "uint",
274
+ "minimum": 0
275
+ },
276
+ "default": [],
277
+ "x-section": "Display"
278
+ },
245
279
  "tab_size": {
246
280
  "description": "Number of spaces per tab character",
247
281
  "type": "integer",
@@ -529,6 +563,22 @@
529
563
  }
530
564
  }
531
565
  },
566
+ "ClipboardConfig": {
567
+ "description": "Clipboard configuration\n\nControls which clipboard methods are used for copy/paste operations.\nBy default, all methods are enabled and the editor tries them in order:\n1. OSC 52 escape sequences (works in modern terminals like Kitty, Alacritty, Wezterm)\n2. System clipboard via X11/Wayland APIs (works in Gnome Console, XFCE Terminal, etc.)\n3. Internal clipboard (always available as fallback)\n\nIf you experience hangs or issues (e.g., when using PuTTY or certain SSH setups),\nyou can disable specific methods.",
568
+ "type": "object",
569
+ "properties": {
570
+ "use_osc52": {
571
+ "description": "Enable OSC 52 escape sequences for clipboard access (default: true)\nDisable this if your terminal doesn't support OSC 52 or if it causes hangs",
572
+ "type": "boolean",
573
+ "default": true
574
+ },
575
+ "use_system_clipboard": {
576
+ "description": "Enable system clipboard access via X11/Wayland APIs (default: true)\nDisable this if you don't have a display server or it causes issues",
577
+ "type": "boolean",
578
+ "default": true
579
+ }
580
+ }
581
+ },
532
582
  "TerminalConfig": {
533
583
  "description": "Terminal configuration",
534
584
  "type": "object",
@@ -250,6 +250,25 @@ type BufferInfo = {
250
250
  * Length of buffer in bytes
251
251
  */
252
252
  length: number;
253
+ /**
254
+ * Whether this is a virtual buffer (not backed by a file)
255
+ */
256
+ is_virtual: boolean;
257
+ /**
258
+ * Current view mode of the active split: "source" or "compose"
259
+ */
260
+ view_mode: string;
261
+ /**
262
+ * True if any split showing this buffer has compose mode enabled.
263
+ * Plugins should use this (not view_mode) to decide whether to maintain
264
+ * decorations, since decorations live on the buffer and are filtered
265
+ * per-split at render time.
266
+ */
267
+ is_composing_in_any_split: boolean;
268
+ /**
269
+ * Compose width (if set), from the active split's view state
270
+ */
271
+ compose_width: number | null;
253
272
  };
254
273
  type JsDiagnostic = {
255
274
  /**
@@ -359,61 +378,66 @@ type FormatterPackConfig = {
359
378
  */
360
379
  args: Array<string>;
361
380
  };
362
- type BackgroundProcessResult = {
381
+ type TerminalResult = {
363
382
  /**
364
- * Unique process ID for later reference
383
+ * The created buffer ID (for use with setSplitBuffer, etc.)
365
384
  */
366
- process_id: number;
385
+ bufferId: number;
367
386
  /**
368
- * Process exit code (0 usually means success, -1 if killed)
369
- * Only present when the process has exited
387
+ * The terminal ID (for use with sendTerminalInput, closeTerminal)
370
388
  */
371
- exit_code: number;
372
- };
373
- type BufferSavedDiff = {
374
- equal: boolean;
375
- byte_ranges: Array<[number, number]>;
376
- line_ranges: Array<[number, number]> | null;
377
- };
378
- type TsCompositeHunk = {
389
+ terminalId: number;
379
390
  /**
380
- * Starting line in old buffer (0-indexed)
391
+ * The split ID (if created in a new split)
381
392
  */
382
- oldStart: number;
393
+ splitId: number | null;
394
+ };
395
+ type CreateTerminalOptions = {
383
396
  /**
384
- * Number of lines in old buffer
397
+ * Working directory for the terminal (defaults to editor cwd)
385
398
  */
386
- oldCount: number;
399
+ cwd?: string;
387
400
  /**
388
- * Starting line in new buffer (0-indexed)
401
+ * Split direction: "horizontal" or "vertical" (default: "vertical")
389
402
  */
390
- newStart: number;
403
+ direction?: string;
391
404
  /**
392
- * Number of lines in new buffer
405
+ * Split ratio 0.0-1.0 (default: 0.5)
393
406
  */
394
- newCount: number;
395
- };
396
- type TsCreateCompositeBufferOptions = {
407
+ ratio?: number;
397
408
  /**
398
- * Buffer name (displayed in tabs/title)
409
+ * Whether to focus the new terminal split (default: true)
399
410
  */
400
- name: string;
411
+ focus?: boolean;
412
+ };
413
+ type CursorInfo = {
401
414
  /**
402
- * Mode for keybindings
415
+ * Byte position of the cursor
403
416
  */
404
- mode: string;
417
+ position: number;
405
418
  /**
406
- * Layout configuration
419
+ * Selection range (if any)
407
420
  */
408
- layout: TsCompositeLayoutConfig;
421
+ selection: {
422
+ start: number;
423
+ end: number;
424
+ } | null;
425
+ };
426
+ type BackgroundProcessResult = {
409
427
  /**
410
- * Source pane configurations
428
+ * Unique process ID for later reference
411
429
  */
412
- sources: Array<TsCompositeSourceConfig>;
430
+ process_id: number;
413
431
  /**
414
- * Diff hunks for alignment (optional)
432
+ * Process exit code (0 usually means success, -1 if killed)
433
+ * Only present when the process has exited
415
434
  */
416
- hunks: Array<TsCompositeHunk> | null;
435
+ exit_code: number;
436
+ };
437
+ type BufferSavedDiff = {
438
+ equal: boolean;
439
+ byte_ranges: Array<[number, number]>;
440
+ line_ranges: Array<[number, number]> | null;
417
441
  };
418
442
  type CreateVirtualBufferInExistingSplitOptions = {
419
443
  /**
@@ -495,6 +519,10 @@ type CreateVirtualBufferInSplitOptions = {
495
519
  */
496
520
  lineWrap?: boolean;
497
521
  /**
522
+ * Place the new buffer before (left/top of) the existing content (default: false)
523
+ */
524
+ before?: boolean;
525
+ /**
498
526
  * Initial content entries with optional properties
499
527
  */
500
528
  entries?: Array<TextPropertyEntry>;
@@ -600,28 +628,6 @@ type SpawnResult = {
600
628
  */
601
629
  exit_code: number;
602
630
  };
603
- type PromptSuggestion = {
604
- /**
605
- * The text to display
606
- */
607
- text: string;
608
- /**
609
- * Optional description
610
- */
611
- description?: string;
612
- /**
613
- * The value to use when selected (defaults to text if None)
614
- */
615
- value?: string;
616
- /**
617
- * Whether this suggestion is disabled (greyed out, defaults to false)
618
- */
619
- disabled?: boolean;
620
- /**
621
- * Optional keyboard shortcut
622
- */
623
- keybinding?: string;
624
- };
625
631
  type TextPropertiesAtCursor = Array<Record<string, unknown>>;
626
632
  type TsHighlightSpan = {
627
633
  start: number;
@@ -644,6 +650,11 @@ type VirtualBufferResult = {
644
650
  * Main editor API interface
645
651
  */
646
652
  interface EditorAPI {
653
+ /**
654
+ * Get the plugin API version. Plugins can check this to verify
655
+ * the editor supports the features they need.
656
+ */
657
+ apiVersion(): number;
647
658
  /**
648
659
  * Get the active buffer ID (0 if none)
649
660
  */
@@ -713,15 +724,15 @@ interface EditorAPI {
713
724
  /**
714
725
  * Get primary cursor info for active buffer
715
726
  */
716
- getPrimaryCursor(): unknown;
727
+ getPrimaryCursor(): CursorInfo | null;
717
728
  /**
718
729
  * Get all cursors for active buffer
719
730
  */
720
- getAllCursors(): unknown;
731
+ getAllCursors(): CursorInfo[];
721
732
  /**
722
733
  * Get all cursor positions as byte offsets
723
734
  */
724
- getAllCursorPositions(): unknown;
735
+ getAllCursorPositions(): number[];
725
736
  /**
726
737
  * Get viewport info for active buffer
727
738
  */
@@ -825,6 +836,16 @@ interface EditorAPI {
825
836
  */
826
837
  pathIsAbsolute(path: string): boolean;
827
838
  /**
839
+ * Get the UTF-8 byte length of a JavaScript string.
840
+ *
841
+ * JS strings are UTF-16 internally, so `str.length` returns the number of
842
+ * UTF-16 code units, not the number of bytes in a UTF-8 encoding. The
843
+ * editor API uses byte offsets for all buffer positions (overlays, cursor,
844
+ * getBufferText ranges, etc.). This helper lets plugins convert JS string
845
+ * lengths / regex match indices to the byte offsets the editor expects.
846
+ */
847
+ utf8ByteLength(text: string): number;
848
+ /**
828
849
  * Check if file exists
829
850
  */
830
851
  fileExists(path: string): boolean;
@@ -906,7 +927,7 @@ interface EditorAPI {
906
927
  /**
907
928
  * Check if a background process is still running
908
929
  */
909
- isProcessRunning(ProcessId: number): boolean;
930
+ isProcessRunning(processId: number): boolean;
910
931
  /**
911
932
  * Kill a process by ID (alias for killBackgroundProcess)
912
933
  */
@@ -921,13 +942,13 @@ interface EditorAPI {
921
942
  * Uses typed CreateCompositeBufferOptions - serde validates field names at runtime
922
943
  * via `deny_unknown_fields` attribute
923
944
  */
924
- createCompositeBuffer(opts: CreateCompositeBufferOptions): Promise<number>;
945
+ createCompositeBuffer(opts: TsCreateCompositeBufferOptions): Promise<number>;
925
946
  /**
926
947
  * Update alignment hunks for a composite buffer
927
948
  *
928
949
  * Uses typed Vec<CompositeHunk> - serde validates field names at runtime
929
950
  */
930
- updateCompositeAlignment(bufferId: number, hunks: CompositeHunk[]): boolean;
951
+ updateCompositeAlignment(bufferId: number, hunks: TsCompositeHunk[]): boolean;
931
952
  /**
932
953
  * Close a composite buffer
933
954
  */
@@ -944,12 +965,16 @@ interface EditorAPI {
944
965
  *
945
966
  * Theme key examples: "ui.status_bar_fg", "editor.selection_bg", "syntax.keyword"
946
967
  *
968
+ * Options: fg, bg (RGB array or theme key string), bold, italic, underline,
969
+ * strikethrough, extend_to_line_end (all booleans, default false).
970
+ *
947
971
  * Example usage in TypeScript:
948
972
  * ```typescript
949
973
  * editor.addOverlay(bufferId, "my-namespace", 0, 10, {
950
974
  * fg: "syntax.keyword", // theme key
951
975
  * bg: [40, 40, 50], // RGB array
952
976
  * bold: true,
977
+ * strikethrough: true,
953
978
  * });
954
979
  * ```
955
980
  */
@@ -971,6 +996,30 @@ interface EditorAPI {
971
996
  */
972
997
  removeOverlay(bufferId: number, handle: string): boolean;
973
998
  /**
999
+ * Add a conceal range that hides or replaces a byte range during rendering
1000
+ */
1001
+ addConceal(bufferId: number, namespace: string, start: number, end: number, replacement: string | null): boolean;
1002
+ /**
1003
+ * Clear all conceal ranges in a namespace
1004
+ */
1005
+ clearConcealNamespace(bufferId: number, namespace: string): boolean;
1006
+ /**
1007
+ * Clear all conceal ranges that overlap with a byte range
1008
+ */
1009
+ clearConcealsInRange(bufferId: number, start: number, end: number): boolean;
1010
+ /**
1011
+ * Add a soft break point for marker-based line wrapping
1012
+ */
1013
+ addSoftBreak(bufferId: number, namespace: string, position: number, indent: number): boolean;
1014
+ /**
1015
+ * Clear all soft breaks in a namespace
1016
+ */
1017
+ clearSoftBreakNamespace(bufferId: number, namespace: string): boolean;
1018
+ /**
1019
+ * Clear all soft breaks that fall within a byte range
1020
+ */
1021
+ clearSoftBreaksInRange(bufferId: number, start: number, end: number): boolean;
1022
+ /**
974
1023
  * Submit a view transform for a buffer/split
975
1024
  *
976
1025
  * Accepts tokens in the simple format:
@@ -985,6 +1034,11 @@ interface EditorAPI {
985
1034
  */
986
1035
  clearViewTransform(bufferId: number, splitId: number | null): boolean;
987
1036
  /**
1037
+ * Set layout hints (compose width, column guides) for a buffer/split
1038
+ * without going through the view_transform pipeline.
1039
+ */
1040
+ setLayoutHints(bufferId: number, splitId: number | null, hints: LayoutHints): boolean;
1041
+ /**
988
1042
  * Set file explorer decorations for a namespace
989
1043
  */
990
1044
  setFileExplorerDecorations(namespace: string, decorations: Record<string, unknown>[]): boolean;
@@ -1034,7 +1088,8 @@ interface EditorAPI {
1034
1088
  *
1035
1089
  * Uses typed Vec<Suggestion> - serde validates field names at runtime
1036
1090
  */
1037
- setPromptSuggestions(suggestions: Suggestion[]): boolean;
1091
+ setPromptSuggestions(suggestions: PromptSuggestion[]): boolean;
1092
+ setPromptInputSync(sync: boolean): boolean;
1038
1093
  /**
1039
1094
  * Define a buffer mode (takes bindings as array of [key, command] pairs)
1040
1095
  */
@@ -1068,6 +1123,18 @@ interface EditorAPI {
1068
1123
  */
1069
1124
  setSplitRatio(splitId: number, ratio: number): boolean;
1070
1125
  /**
1126
+ * Set a label on a split (e.g., "sidebar")
1127
+ */
1128
+ setSplitLabel(splitId: number, label: string): boolean;
1129
+ /**
1130
+ * Remove a label from a split
1131
+ */
1132
+ clearSplitLabel(splitId: number): boolean;
1133
+ /**
1134
+ * Find a split by label (async)
1135
+ */
1136
+ getSplitByLabel(label: string): Promise<number | null>;
1137
+ /**
1071
1138
  * Distribute all splits evenly
1072
1139
  */
1073
1140
  distributeSplitsEvenly(): boolean;
@@ -1088,10 +1155,22 @@ interface EditorAPI {
1088
1155
  */
1089
1156
  setLineNumbers(bufferId: number, enabled: boolean): boolean;
1090
1157
  /**
1158
+ * Set the view mode for a buffer ("source" or "compose")
1159
+ */
1160
+ setViewMode(bufferId: number, mode: string): boolean;
1161
+ /**
1091
1162
  * Enable or disable line wrapping for a buffer/split
1092
1163
  */
1093
1164
  setLineWrap(bufferId: number, splitId: number | null, enabled: boolean): boolean;
1094
1165
  /**
1166
+ * Set plugin-managed per-buffer view state (write-through to snapshot + command for persistence)
1167
+ */
1168
+ setViewState(bufferId: number, key: string, value: unknown): boolean;
1169
+ /**
1170
+ * Get plugin-managed per-buffer view state (reads from snapshot)
1171
+ */
1172
+ getViewState(bufferId: number, key: string): unknown;
1173
+ /**
1095
1174
  * Create a scroll sync group for anchor-based synchronized scrolling
1096
1175
  */
1097
1176
  createScrollSyncGroup(groupId: number, leftSplit: number, rightSplit: number): boolean;
@@ -1183,6 +1262,18 @@ interface EditorAPI {
1183
1262
  */
1184
1263
  killBackgroundProcess(processId: number): boolean;
1185
1264
  /**
1265
+ * Create a new terminal in a split (async, returns TerminalResult)
1266
+ */
1267
+ createTerminal(opts?: CreateTerminalOptions): Promise<TerminalResult>;
1268
+ /**
1269
+ * Send input data to a terminal
1270
+ */
1271
+ sendTerminalInput(terminalId: number, data: string): boolean;
1272
+ /**
1273
+ * Close a terminal
1274
+ */
1275
+ closeTerminal(terminalId: number): boolean;
1276
+ /**
1186
1277
  * Force refresh of line display
1187
1278
  */
1188
1279
  refreshLines(bufferId: number): boolean;