@fresh-editor/fresh-editor 0.3.5 → 0.3.7
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 +147 -0
- package/README.md +9 -2
- package/package.json +1 -1
- package/plugins/audit_mode.i18n.json +84 -0
- package/plugins/audit_mode.ts +139 -3
- package/plugins/config-schema.json +33 -3
- package/plugins/dashboard.ts +34 -111
- package/plugins/flash.ts +22 -4
- package/plugins/git_blame.ts +10 -6
- package/plugins/git_log.ts +705 -323
- package/plugins/git_statusbar.i18n.json +72 -0
- package/plugins/git_statusbar.ts +133 -0
- package/plugins/goto_with_selection.i18n.json +58 -0
- package/plugins/goto_with_selection.ts +17 -0
- package/plugins/lib/fresh.d.ts +911 -15
- package/plugins/lib/index.ts +34 -0
- package/plugins/lib/widgets.ts +903 -0
- package/plugins/live_diff.ts +442 -32
- package/plugins/merge_conflict.ts +89 -64
- package/plugins/orchestrator.ts +3425 -0
- package/plugins/pkg.ts +235 -54
- package/plugins/rust-lsp.ts +58 -40
- package/plugins/schemas/theme.schema.json +18 -0
- package/plugins/search_replace.i18n.json +140 -28
- package/plugins/search_replace.ts +1335 -515
- package/plugins/tab_actions.i18n.json +212 -0
- package/plugins/tab_actions.ts +76 -0
- package/plugins/theme_editor.i18n.json +112 -0
- package/plugins/theme_editor.ts +30 -5
- package/plugins/tsconfig.json +3 -0
- package/plugins/vi_mode.ts +49 -17
- package/themes/dark.json +1 -0
- package/themes/dracula.json +1 -0
- package/themes/high-contrast.json +1 -0
- package/themes/light.json +1 -0
- package/themes/nord.json +1 -0
- package/themes/nostalgia.json +1 -0
- package/themes/solarized-dark.json +1 -0
- package/themes/terminal.json +4 -0
package/plugins/lib/fresh.d.ts
CHANGED
|
@@ -116,6 +116,18 @@ type TextPropertyEntry = {
|
|
|
116
116
|
* Optional sub-range styling within this entry
|
|
117
117
|
*/
|
|
118
118
|
inlineOverlays?: Array<InlineOverlay>;
|
|
119
|
+
/**
|
|
120
|
+
* See `TextPropertyEntry::pad_to_chars`.
|
|
121
|
+
*/
|
|
122
|
+
padToChars?: number;
|
|
123
|
+
/**
|
|
124
|
+
* See `TextPropertyEntry::truncate_to_chars`.
|
|
125
|
+
*/
|
|
126
|
+
truncateToChars?: number;
|
|
127
|
+
/**
|
|
128
|
+
* See `TextPropertyEntry::segments`.
|
|
129
|
+
*/
|
|
130
|
+
segments?: Array<StyledSegment>;
|
|
119
131
|
};
|
|
120
132
|
type TsCompositeLayoutConfig = {
|
|
121
133
|
/**
|
|
@@ -240,6 +252,10 @@ type ViewportInfo = {
|
|
|
240
252
|
*/
|
|
241
253
|
height: number;
|
|
242
254
|
};
|
|
255
|
+
type ScreenSize = {
|
|
256
|
+
width: number;
|
|
257
|
+
height: number;
|
|
258
|
+
};
|
|
243
259
|
type KeyEventPayload = {
|
|
244
260
|
/**
|
|
245
261
|
* Key name (e.g. `"a"`, `"escape"`, `"f1"`).
|
|
@@ -307,15 +323,18 @@ type ViewTokenWireKind = {
|
|
|
307
323
|
} | "Newline" | "Space" | "Break" | {
|
|
308
324
|
"BinaryByte": number;
|
|
309
325
|
};
|
|
326
|
+
type TokenColor = [number, number, number] | string;
|
|
310
327
|
type ViewTokenStyle = {
|
|
311
328
|
/**
|
|
312
|
-
* Foreground color
|
|
329
|
+
* Foreground color. Either `[r, g, b]` or a named/theme string —
|
|
330
|
+
* see [`TokenColor`].
|
|
313
331
|
*/
|
|
314
|
-
fg:
|
|
332
|
+
fg: TokenColor | null;
|
|
315
333
|
/**
|
|
316
|
-
* Background color
|
|
334
|
+
* Background color. Either `[r, g, b]` or a named/theme string —
|
|
335
|
+
* see [`TokenColor`].
|
|
317
336
|
*/
|
|
318
|
-
bg:
|
|
337
|
+
bg: TokenColor | null;
|
|
319
338
|
/**
|
|
320
339
|
* Whether to render in bold
|
|
321
340
|
*/
|
|
@@ -324,6 +343,10 @@ type ViewTokenStyle = {
|
|
|
324
343
|
* Whether to render in italic
|
|
325
344
|
*/
|
|
326
345
|
italic: boolean;
|
|
346
|
+
/**
|
|
347
|
+
* Whether to render with underline
|
|
348
|
+
*/
|
|
349
|
+
underline: boolean;
|
|
327
350
|
};
|
|
328
351
|
type PromptSuggestion = {
|
|
329
352
|
/**
|
|
@@ -420,6 +443,37 @@ type BufferInfo = {
|
|
|
420
443
|
*/
|
|
421
444
|
splits: number[];
|
|
422
445
|
};
|
|
446
|
+
type WindowInfo = {
|
|
447
|
+
/**
|
|
448
|
+
* Stable session id. The base session is always `1`.
|
|
449
|
+
*/
|
|
450
|
+
id: number;
|
|
451
|
+
/**
|
|
452
|
+
* User-visible label (defaults to root basename).
|
|
453
|
+
*/
|
|
454
|
+
label: string;
|
|
455
|
+
/**
|
|
456
|
+
* Absolute project root.
|
|
457
|
+
*/
|
|
458
|
+
root: string;
|
|
459
|
+
/**
|
|
460
|
+
* Project this session belongs to — the canonical repo
|
|
461
|
+
* root (or arbitrary directory) the user pointed the
|
|
462
|
+
* new-session form at. `null` for legacy sessions that
|
|
463
|
+
* predate the Project Path field. The Orchestrator Open
|
|
464
|
+
* dialog filters by this so the "this project's sessions"
|
|
465
|
+
* view is one keystroke away from the all-projects view.
|
|
466
|
+
*/
|
|
467
|
+
project_path?: string | null;
|
|
468
|
+
/**
|
|
469
|
+
* `true` when the session shares its working tree with
|
|
470
|
+
* other sessions (worktree-creation was off at session
|
|
471
|
+
* time, or the session lives in a non-git directory).
|
|
472
|
+
* Persistence-only field; defaults to `false` and isn't
|
|
473
|
+
* emitted when false.
|
|
474
|
+
*/
|
|
475
|
+
shared_worktree?: boolean;
|
|
476
|
+
};
|
|
423
477
|
type JsDiagnostic = {
|
|
424
478
|
/**
|
|
425
479
|
* Document URI
|
|
@@ -500,6 +554,17 @@ type ActionPopupOptions = {
|
|
|
500
554
|
*/
|
|
501
555
|
actions: Array<TsActionPopupAction>;
|
|
502
556
|
};
|
|
557
|
+
type TsLspMenuItem = {
|
|
558
|
+
/**
|
|
559
|
+
* Stable identifier used as the `action_id` in the resulting
|
|
560
|
+
* `action_popup_result` event (prefixed by `{plugin_id}|`).
|
|
561
|
+
*/
|
|
562
|
+
id: string;
|
|
563
|
+
/**
|
|
564
|
+
* Display label shown in the popup row.
|
|
565
|
+
*/
|
|
566
|
+
label: string;
|
|
567
|
+
};
|
|
503
568
|
type FileExplorerDecoration = {
|
|
504
569
|
/**
|
|
505
570
|
* File path to decorate
|
|
@@ -582,6 +647,37 @@ type CreateTerminalOptions = {
|
|
|
582
647
|
* across editor restarts.
|
|
583
648
|
*/
|
|
584
649
|
persistent?: boolean;
|
|
650
|
+
/**
|
|
651
|
+
* Optional session id to attach the new terminal buffer to.
|
|
652
|
+
* Defaults to the active session at creation time. Setting this
|
|
653
|
+
* lets Orchestrator and similar plugins spawn a terminal *into* an
|
|
654
|
+
* inactive session (e.g. an agent in a worktree the user hasn't
|
|
655
|
+
* dived into yet). The terminal's split is created in that
|
|
656
|
+
* session's stashed split tree; the buffer is attached to the
|
|
657
|
+
* target session's membership set rather than the active one's.
|
|
658
|
+
*/
|
|
659
|
+
windowId?: WindowId;
|
|
660
|
+
/**
|
|
661
|
+
* Argv to spawn directly inside the PTY instead of the host's
|
|
662
|
+
* configured shell. `None` (default) keeps the historical
|
|
663
|
+
* behaviour: spawn the user's shell and let the caller type into
|
|
664
|
+
* it via `sendTerminalInput`. `Some([cmd, ...args])` runs that
|
|
665
|
+
* exact command as the PTY child — no shell middleman, so the
|
|
666
|
+
* process exits cleanly when the agent does and the
|
|
667
|
+
* terminal-buffer's `terminal_exit` plugin hook reflects the
|
|
668
|
+
* agent's real exit status. Used by Orchestrator so a session
|
|
669
|
+
* with agent `python3` is just python3 in the PTY rather than
|
|
670
|
+
* bash-running-python3-as-a-subshell-command.
|
|
671
|
+
*/
|
|
672
|
+
command?: Array<string>;
|
|
673
|
+
/**
|
|
674
|
+
* Tab title for the terminal buffer. Defaults to `command[0]`
|
|
675
|
+
* (when `command` is set) or `"Terminal N"` (the historical
|
|
676
|
+
* auto-numbered title). If another terminal in the same window
|
|
677
|
+
* already uses the requested title, the host appends `" (k)"`
|
|
678
|
+
* to disambiguate. Empty string is treated the same as `None`.
|
|
679
|
+
*/
|
|
680
|
+
title?: string;
|
|
585
681
|
};
|
|
586
682
|
type CursorInfo = {
|
|
587
683
|
/**
|
|
@@ -635,11 +731,11 @@ type OverlayOptions = {
|
|
|
635
731
|
type OverlayColorSpec = [number, number, number] | string;
|
|
636
732
|
type InlineOverlay = {
|
|
637
733
|
/**
|
|
638
|
-
* Start
|
|
734
|
+
* Start offset within the entry's text. See `unit`.
|
|
639
735
|
*/
|
|
640
736
|
start: number;
|
|
641
737
|
/**
|
|
642
|
-
* End
|
|
738
|
+
* End offset within the entry's text (exclusive). See `unit`.
|
|
643
739
|
*/
|
|
644
740
|
end: number;
|
|
645
741
|
/**
|
|
@@ -650,6 +746,29 @@ type InlineOverlay = {
|
|
|
650
746
|
* Optional properties for this sub-range (e.g., click target metadata)
|
|
651
747
|
*/
|
|
652
748
|
properties?: Record<string, any>;
|
|
749
|
+
/**
|
|
750
|
+
* Unit for `start` / `end`. Defaults to `byte`.
|
|
751
|
+
*/
|
|
752
|
+
unit?: OffsetUnit;
|
|
753
|
+
};
|
|
754
|
+
type OffsetUnit = "byte" | "char";
|
|
755
|
+
type StyledSegment = {
|
|
756
|
+
/**
|
|
757
|
+
* Verbatim text for this segment.
|
|
758
|
+
*/
|
|
759
|
+
text: string;
|
|
760
|
+
/**
|
|
761
|
+
* When set, the host emits an `InlineOverlay` covering this
|
|
762
|
+
* segment's text in the final entry.
|
|
763
|
+
*/
|
|
764
|
+
style?: Partial<OverlayOptions>;
|
|
765
|
+
/**
|
|
766
|
+
* Additional overlays inside this segment. Offsets are in
|
|
767
|
+
* the overlay's own `unit`, relative to the segment's start
|
|
768
|
+
* (NOT the final entry text); the host shifts them by the
|
|
769
|
+
* segment's position during concatenation.
|
|
770
|
+
*/
|
|
771
|
+
overlays?: Array<InlineOverlay>;
|
|
653
772
|
};
|
|
654
773
|
type GrammarInfoSnapshot = {
|
|
655
774
|
/**
|
|
@@ -682,6 +801,360 @@ type PluginAnimationKind = {
|
|
|
682
801
|
durationMs: number;
|
|
683
802
|
delayMs: number;
|
|
684
803
|
};
|
|
804
|
+
type HintEntry = {
|
|
805
|
+
/**
|
|
806
|
+
* The key chord, e.g. `"Tab"`, `"Alt+P"`, `"Esc"`.
|
|
807
|
+
*/
|
|
808
|
+
keys: string;
|
|
809
|
+
/**
|
|
810
|
+
* The human-readable label for the action.
|
|
811
|
+
*/
|
|
812
|
+
label: string;
|
|
813
|
+
};
|
|
814
|
+
type ButtonKind = "normal" | "primary" | "danger";
|
|
815
|
+
type TreeNode = {
|
|
816
|
+
/**
|
|
817
|
+
* The pre-rendered row content (text + per-row overlays).
|
|
818
|
+
* The host renders this verbatim after the indent + disclosure
|
|
819
|
+
* prefix; plugin overlays are byte-shifted by the prefix
|
|
820
|
+
* length.
|
|
821
|
+
*/
|
|
822
|
+
text: TextPropertyEntry;
|
|
823
|
+
/**
|
|
824
|
+
* 0-based depth — controls leading indent (`depth * 2` spaces).
|
|
825
|
+
*/
|
|
826
|
+
depth: number;
|
|
827
|
+
/**
|
|
828
|
+
* When true, render a disclosure glyph (`▶` collapsed / `▼`
|
|
829
|
+
* expanded) and emit a hit area over it that fires the `expand`
|
|
830
|
+
* event. Leaf nodes (`false`) get no glyph and no expand hit;
|
|
831
|
+
* the row width occupies the full row.
|
|
832
|
+
*/
|
|
833
|
+
hasChildren: boolean;
|
|
834
|
+
/**
|
|
835
|
+
* Per-node checkbox state. Only rendered when the parent
|
|
836
|
+
* `Tree` has `checkable: true`. `None` = no checkbox glyph;
|
|
837
|
+
* `Some(true)` = `[v]`; `Some(false)` = `[ ]`. The plugin
|
|
838
|
+
* owns the truth — the host fires `widget_event { event_type:
|
|
839
|
+
* "toggle" }` and the plugin pushes the new state back via
|
|
840
|
+
* `WidgetMutation::SetCheckedKeys`.
|
|
841
|
+
*/
|
|
842
|
+
checked?: boolean | null;
|
|
843
|
+
};
|
|
844
|
+
type WidgetSpec = {
|
|
845
|
+
"kind": "row";
|
|
846
|
+
children: Array<WidgetSpec>;
|
|
847
|
+
key?: string | null;
|
|
848
|
+
} | {
|
|
849
|
+
"kind": "col";
|
|
850
|
+
children: Array<WidgetSpec>;
|
|
851
|
+
key?: string | null;
|
|
852
|
+
} | {
|
|
853
|
+
"kind": "hintBar";
|
|
854
|
+
entries: Array<HintEntry>;
|
|
855
|
+
key?: string | null;
|
|
856
|
+
} | {
|
|
857
|
+
"kind": "toggle";
|
|
858
|
+
checked: boolean;
|
|
859
|
+
label: string;
|
|
860
|
+
focused: boolean;
|
|
861
|
+
key?: string | null;
|
|
862
|
+
} | {
|
|
863
|
+
"kind": "button";
|
|
864
|
+
label: string;
|
|
865
|
+
focused: boolean;
|
|
866
|
+
intent: ButtonKind;
|
|
867
|
+
key?: string | null;
|
|
868
|
+
/**
|
|
869
|
+
* When true, the button renders in a muted style, is dropped
|
|
870
|
+
* from the Tab cycle, and clicks on it are ignored. Use for
|
|
871
|
+
* actions that aren't currently available against the
|
|
872
|
+
* surrounding state (e.g. "Archive" on the base session). The
|
|
873
|
+
* button still occupies its layout cell so the surrounding
|
|
874
|
+
* row doesn't reshuffle when the disabled flag flips.
|
|
875
|
+
*/
|
|
876
|
+
disabled: boolean;
|
|
877
|
+
} | {
|
|
878
|
+
"kind": "spacer";
|
|
879
|
+
cols: number;
|
|
880
|
+
flex: boolean;
|
|
881
|
+
key?: string | null;
|
|
882
|
+
} | {
|
|
883
|
+
"kind": "list";
|
|
884
|
+
items: Array<TextPropertyEntry>;
|
|
885
|
+
itemKeys: Array<string>;
|
|
886
|
+
selectedIndex: number;
|
|
887
|
+
/**
|
|
888
|
+
* Number of rows of the panel's available height the list
|
|
889
|
+
* should occupy. Plugin computes from its viewport. The
|
|
890
|
+
* host shows up to this many items per render.
|
|
891
|
+
*/
|
|
892
|
+
visibleRows: number;
|
|
893
|
+
/**
|
|
894
|
+
* Whether `Tab` / `Shift+Tab` will land focus on this
|
|
895
|
+
* list. Defaults to `true` (lists are normal tabbable
|
|
896
|
+
* widgets). Picker-style usage typically sets this to
|
|
897
|
+
* `false` so Tab moves between the filter input and
|
|
898
|
+
* the action buttons, while Up/Down on the focused
|
|
899
|
+
* filter still forwards to the list via host smart-key
|
|
900
|
+
* dispatch.
|
|
901
|
+
*/
|
|
902
|
+
focusable: boolean;
|
|
903
|
+
key?: string | null;
|
|
904
|
+
} | {
|
|
905
|
+
"kind": "tree";
|
|
906
|
+
nodes: Array<TreeNode>;
|
|
907
|
+
itemKeys: Array<string>;
|
|
908
|
+
selectedIndex: number;
|
|
909
|
+
visibleRows: number;
|
|
910
|
+
/**
|
|
911
|
+
* Initial-only set of expanded item keys. Once the widget
|
|
912
|
+
* has rendered, the host's instance-state `expanded_keys`
|
|
913
|
+
* is authoritative; updating this field on subsequent specs
|
|
914
|
+
* has no effect (use `WidgetMutation::SetExpandedKeys` to
|
|
915
|
+
* override host state).
|
|
916
|
+
*/
|
|
917
|
+
expandedKeys: Array<string>;
|
|
918
|
+
/**
|
|
919
|
+
* When true, every node with `checked: Some(_)` renders a
|
|
920
|
+
* `[v]` / `[ ]` glyph and emits a `toggle` hit area over
|
|
921
|
+
* the glyph. Click on the glyph fires `widget_event {
|
|
922
|
+
* event_type: "toggle", payload: { key, checked: <new> } }`;
|
|
923
|
+
* the plugin updates its model and pushes the new state
|
|
924
|
+
* back via `WidgetMutation::SetCheckedKeys`.
|
|
925
|
+
*/
|
|
926
|
+
checkable: boolean;
|
|
927
|
+
key?: string | null;
|
|
928
|
+
} | {
|
|
929
|
+
"kind": "text";
|
|
930
|
+
/**
|
|
931
|
+
* Initial text. Spec value is read at first render only;
|
|
932
|
+
* instance state takes over thereafter.
|
|
933
|
+
*/
|
|
934
|
+
value: string;
|
|
935
|
+
/**
|
|
936
|
+
* Initial byte-offset cursor within `value`. Negative
|
|
937
|
+
* (encoded as `i32` in JSON) means "no cursor" — clamped
|
|
938
|
+
* to `[0, value.len()]` host-side.
|
|
939
|
+
*/
|
|
940
|
+
cursorByte: number;
|
|
941
|
+
/**
|
|
942
|
+
* Whether this widget has visual focus.
|
|
943
|
+
*/
|
|
944
|
+
focused: boolean;
|
|
945
|
+
/**
|
|
946
|
+
* Optional label rendered before / above the editing
|
|
947
|
+
* region. Empty = omitted.
|
|
948
|
+
*/
|
|
949
|
+
label?: string;
|
|
950
|
+
/**
|
|
951
|
+
* Placeholder shown when unfocused and `value` is empty.
|
|
952
|
+
*/
|
|
953
|
+
placeholder?: string | null;
|
|
954
|
+
/**
|
|
955
|
+
* Number of visible rows of editing region. `0` falls back
|
|
956
|
+
* to `1` (single-line). `1` = single-line behaviour;
|
|
957
|
+
* `>= 2` = multi-line behaviour. See the type-level doc
|
|
958
|
+
* for the per-mode semantics.
|
|
959
|
+
*/
|
|
960
|
+
rows: number;
|
|
961
|
+
/**
|
|
962
|
+
* Visible column width. `0` = auto-fit (single-line) or
|
|
963
|
+
* panel width (multi-line). When set, single-line
|
|
964
|
+
* head-truncates with `…` and multi-line tail-truncates
|
|
965
|
+
* per-line.
|
|
966
|
+
*/
|
|
967
|
+
fieldWidth: number;
|
|
968
|
+
/**
|
|
969
|
+
* Single-line soft cap on visible chars after the
|
|
970
|
+
* `field_width` pad. `0` = no cap. Ignored when `rows > 1`.
|
|
971
|
+
*/
|
|
972
|
+
maxVisibleChars: number;
|
|
973
|
+
/**
|
|
974
|
+
* Stretch the visible field to fill the available
|
|
975
|
+
* width of the enclosing container. Overrides
|
|
976
|
+
* `field_width` when set: the renderer computes
|
|
977
|
+
* `panel_width - label_overhead - bracket_overhead` as
|
|
978
|
+
* the effective visible width. Multi-line widgets
|
|
979
|
+
* already fill the panel width by default; this flag is
|
|
980
|
+
* most useful for single-line inputs inside a
|
|
981
|
+
* `LabeledSection` or a flexible row.
|
|
982
|
+
*/
|
|
983
|
+
fullWidth: boolean;
|
|
984
|
+
/**
|
|
985
|
+
* Optional completion candidates. When non-empty AND
|
|
986
|
+
* `label` is non-empty (the chrome trigger), the
|
|
987
|
+
* renderer paints a popup directly under the input,
|
|
988
|
+
* inside a unified box: the input's normal `╰─...─╯`
|
|
989
|
+
* bottom border becomes a dimmed `┄` separator, the
|
|
990
|
+
* labeled section's side borders extend down through
|
|
991
|
+
* the candidate rows, and a single `╰─...─╯` bottom
|
|
992
|
+
* closes the whole block. Candidates render left-
|
|
993
|
+
* aligned with the input's text (the position right
|
|
994
|
+
* after `[`), with the host-managed selected index
|
|
995
|
+
* highlighted.
|
|
996
|
+
*
|
|
997
|
+
* Smart-key dispatch on a focused Text-with-completions:
|
|
998
|
+
* Up/Down moves selection (host-internal, no event),
|
|
999
|
+
* Tab fires `completion_accept` with the selected
|
|
1000
|
+
* candidate, Enter / Escape fire `completion_dismiss`
|
|
1001
|
+
* (the dispatcher's normal "Enter focus-advance / Esc
|
|
1002
|
+
* close panel" only runs once the popup is closed).
|
|
1003
|
+
*
|
|
1004
|
+
* Plugins push candidates in response to the text
|
|
1005
|
+
* widget's `change` event via
|
|
1006
|
+
* `WidgetMutation::SetCompletions`. An empty `items`
|
|
1007
|
+
* closes the popup.
|
|
1008
|
+
*/
|
|
1009
|
+
completions?: Array<string>;
|
|
1010
|
+
/**
|
|
1011
|
+
* How many candidate rows the popup paints at once
|
|
1012
|
+
* when it opens. Excess candidates stay reachable
|
|
1013
|
+
* via Up/Down (host auto-scrolls to keep selection
|
|
1014
|
+
* in view) or the mouse wheel; a thumb glyph paints
|
|
1015
|
+
* in the right edge of the popup whenever there's
|
|
1016
|
+
* more to scroll. `0` (default) falls back to `5`.
|
|
1017
|
+
*/
|
|
1018
|
+
completionsVisibleRows: number;
|
|
1019
|
+
key?: string | null;
|
|
1020
|
+
} | {
|
|
1021
|
+
"kind": "labeledSection";
|
|
1022
|
+
/**
|
|
1023
|
+
* Legend text printed in the top border. Empty = no
|
|
1024
|
+
* legend (the top border becomes one unbroken line).
|
|
1025
|
+
*/
|
|
1026
|
+
label: string;
|
|
1027
|
+
/**
|
|
1028
|
+
* The single wrapped widget. Boxed because `WidgetSpec`
|
|
1029
|
+
* is recursive.
|
|
1030
|
+
*/
|
|
1031
|
+
child: WidgetSpec;
|
|
1032
|
+
/**
|
|
1033
|
+
* When this section is a Block child of a Row, request
|
|
1034
|
+
* `width_pct` percent of the row's `panel_width` instead
|
|
1035
|
+
* of the equal-split default. Multiple siblings with
|
|
1036
|
+
* `width_pct` set sum to ≤ 100; the remainder splits
|
|
1037
|
+
* equally among siblings without an explicit width.
|
|
1038
|
+
* Out-of-range values (0 or > 100) fall back to the
|
|
1039
|
+
* equal-split path.
|
|
1040
|
+
*/
|
|
1041
|
+
widthPct?: number | null;
|
|
1042
|
+
key?: string | null;
|
|
1043
|
+
} | {
|
|
1044
|
+
"kind": "windowEmbed";
|
|
1045
|
+
/**
|
|
1046
|
+
* Numeric editor-window id, matching `WindowId(N).0`.
|
|
1047
|
+
* `0` (or any unknown id) renders empty placeholder
|
|
1048
|
+
* rows without dispatching the per-window render.
|
|
1049
|
+
* `u32` rather than `u64` to keep the TS binding a
|
|
1050
|
+
* plain `number`; window ids never exceed 4B in
|
|
1051
|
+
* practice.
|
|
1052
|
+
*/
|
|
1053
|
+
windowId: number;
|
|
1054
|
+
/**
|
|
1055
|
+
* Number of visible rows the embed should occupy.
|
|
1056
|
+
*/
|
|
1057
|
+
rows: number;
|
|
1058
|
+
key?: string | null;
|
|
1059
|
+
} | {
|
|
1060
|
+
"kind": "raw";
|
|
1061
|
+
entries: Array<TextPropertyEntry>;
|
|
1062
|
+
key?: string | null;
|
|
1063
|
+
} | {
|
|
1064
|
+
"kind": "overlay";
|
|
1065
|
+
child: WidgetSpec;
|
|
1066
|
+
key?: string | null;
|
|
1067
|
+
};
|
|
1068
|
+
type WidgetAction = {
|
|
1069
|
+
"kind": "focusAdvance";
|
|
1070
|
+
delta: number;
|
|
1071
|
+
} | {
|
|
1072
|
+
"kind": "activate";
|
|
1073
|
+
} | {
|
|
1074
|
+
"kind": "selectMove";
|
|
1075
|
+
delta: number;
|
|
1076
|
+
} | {
|
|
1077
|
+
"kind": "textInputKey";
|
|
1078
|
+
key: string;
|
|
1079
|
+
} | {
|
|
1080
|
+
"kind": "textInputChar";
|
|
1081
|
+
text: string;
|
|
1082
|
+
} | {
|
|
1083
|
+
"kind": "key";
|
|
1084
|
+
key: string;
|
|
1085
|
+
};
|
|
1086
|
+
type WidgetMutation = {
|
|
1087
|
+
"kind": "setValue";
|
|
1088
|
+
widgetKey: string;
|
|
1089
|
+
value: string;
|
|
1090
|
+
cursorByte?: number | null;
|
|
1091
|
+
} | {
|
|
1092
|
+
"kind": "setCompletions";
|
|
1093
|
+
widgetKey: string;
|
|
1094
|
+
items: Array<string>;
|
|
1095
|
+
} | {
|
|
1096
|
+
"kind": "setChecked";
|
|
1097
|
+
widgetKey: string;
|
|
1098
|
+
checked: boolean;
|
|
1099
|
+
} | {
|
|
1100
|
+
"kind": "setSelectedIndex";
|
|
1101
|
+
widgetKey: string;
|
|
1102
|
+
index: number;
|
|
1103
|
+
} | {
|
|
1104
|
+
"kind": "setItems";
|
|
1105
|
+
widgetKey: string;
|
|
1106
|
+
items: Array<TextPropertyEntry>;
|
|
1107
|
+
itemKeys: Array<string>;
|
|
1108
|
+
} | {
|
|
1109
|
+
"kind": "setExpandedKeys";
|
|
1110
|
+
widgetKey: string;
|
|
1111
|
+
keys: Array<string>;
|
|
1112
|
+
} | {
|
|
1113
|
+
"kind": "setCheckedKeys";
|
|
1114
|
+
widgetKey: string;
|
|
1115
|
+
checked: boolean;
|
|
1116
|
+
keys: Array<string>;
|
|
1117
|
+
} | {
|
|
1118
|
+
"kind": "appendTreeNodes";
|
|
1119
|
+
widgetKey: string;
|
|
1120
|
+
newNodes: Array<TreeNode>;
|
|
1121
|
+
newItemKeys: Array<string>;
|
|
1122
|
+
} | {
|
|
1123
|
+
"kind": "setRawEntries";
|
|
1124
|
+
widgetKey: string;
|
|
1125
|
+
entries: Array<TextPropertyEntry>;
|
|
1126
|
+
} | {
|
|
1127
|
+
"kind": "setFocusKey";
|
|
1128
|
+
widgetKey: string;
|
|
1129
|
+
};
|
|
1130
|
+
type SearchTakeResult = {
|
|
1131
|
+
/**
|
|
1132
|
+
* Matches discovered since the previous take()
|
|
1133
|
+
*/
|
|
1134
|
+
matches: Array<GrepMatch>;
|
|
1135
|
+
/**
|
|
1136
|
+
* Whether the producer has finished (no more matches will arrive)
|
|
1137
|
+
*/
|
|
1138
|
+
done: boolean;
|
|
1139
|
+
/**
|
|
1140
|
+
* Total number of matches the producer has emitted across all batches
|
|
1141
|
+
* (including ones already drained on prior take() calls)
|
|
1142
|
+
*/
|
|
1143
|
+
totalSeen: number;
|
|
1144
|
+
/**
|
|
1145
|
+
* Whether the producer stopped early because it hit `maxResults`
|
|
1146
|
+
*/
|
|
1147
|
+
truncated: boolean;
|
|
1148
|
+
/**
|
|
1149
|
+
* Producer error, if any (e.g., invalid regex). When set, `done` is also true.
|
|
1150
|
+
*/
|
|
1151
|
+
error?: string | null;
|
|
1152
|
+
};
|
|
1153
|
+
interface SearchHandle {
|
|
1154
|
+
searchId: number;
|
|
1155
|
+
take(): SearchTakeResult;
|
|
1156
|
+
cancel(): void;
|
|
1157
|
+
}
|
|
685
1158
|
type AuthorityFilesystem = {
|
|
686
1159
|
kind: "local";
|
|
687
1160
|
};
|
|
@@ -1082,7 +1555,9 @@ interface EditorAPI {
|
|
|
1082
1555
|
* contexts only (e.g. `"tour-active"`, `"review-mode"`), not built-in
|
|
1083
1556
|
* editor modes.
|
|
1084
1557
|
*/
|
|
1085
|
-
registerCommand(name: string, description: string, handlerName: string, context?: string | null
|
|
1558
|
+
registerCommand(name: string, description: string, handlerName: string, context?: string | null, options?: {
|
|
1559
|
+
terminalBypass?: boolean;
|
|
1560
|
+
} | null): boolean;
|
|
1086
1561
|
/**
|
|
1087
1562
|
* Unregister a command by name
|
|
1088
1563
|
*/
|
|
@@ -1096,6 +1571,17 @@ interface EditorAPI {
|
|
|
1096
1571
|
*/
|
|
1097
1572
|
executeAction(actionName: string): boolean;
|
|
1098
1573
|
/**
|
|
1574
|
+
* Register a custom statusbar token.
|
|
1575
|
+
* Token will be named "plugin_name:token_name" where plugin_name is the current plugin.
|
|
1576
|
+
* Returns true if registration succeeded, false if invalid or already registered.
|
|
1577
|
+
*/
|
|
1578
|
+
registerStatusBarElement(tokenName: string, title: string): boolean;
|
|
1579
|
+
/**
|
|
1580
|
+
* Set the value of a status-bar token for a specific buffer.
|
|
1581
|
+
* The full token key sent to the editor is "plugin_name:token_name".
|
|
1582
|
+
*/
|
|
1583
|
+
setStatusBarValue(bufferId: number, tokenName: string, value: string): boolean;
|
|
1584
|
+
/**
|
|
1099
1585
|
* Translate a string - reads plugin name from __pluginName__ global
|
|
1100
1586
|
* Args is optional - can be omitted, undefined, null, or an object
|
|
1101
1587
|
*/
|
|
@@ -1142,6 +1628,13 @@ interface EditorAPI {
|
|
|
1142
1628
|
*/
|
|
1143
1629
|
getViewport(): ViewportInfo | null;
|
|
1144
1630
|
/**
|
|
1631
|
+
* Total terminal dimensions in cells. Unlike `getViewport()`
|
|
1632
|
+
* (which reports the active split, shrunk by any vertical
|
|
1633
|
+
* split layout), this reflects the full terminal — what a
|
|
1634
|
+
* floating overlay sized by `heightPct` actually gets.
|
|
1635
|
+
*/
|
|
1636
|
+
getScreenSize(): ScreenSize;
|
|
1637
|
+
/**
|
|
1145
1638
|
* List every split with its active buffer and viewport.
|
|
1146
1639
|
*
|
|
1147
1640
|
* Plugins that need to operate on every visible buffer
|
|
@@ -1211,10 +1704,41 @@ interface EditorAPI {
|
|
|
1211
1704
|
*/
|
|
1212
1705
|
openFile(path: string, line: number | null, column: number | null): boolean;
|
|
1213
1706
|
/**
|
|
1707
|
+
* Open a file in the background — no focus change, no
|
|
1708
|
+
* active-split mutation. `windowId` defaults to the active
|
|
1709
|
+
* session. Setting it to an inactive session id loads the
|
|
1710
|
+
* file's buffer and adds it as a tab in that session's
|
|
1711
|
+
* stashed split tree, ready to be revealed on next dive.
|
|
1712
|
+
* Orchestrator uses this to populate worktree sessions with
|
|
1713
|
+
* preselected files.
|
|
1714
|
+
*/
|
|
1715
|
+
openFileInBackground(path: string, windowId?: number): boolean;
|
|
1716
|
+
/**
|
|
1214
1717
|
* Open a file in a specific split
|
|
1215
1718
|
*/
|
|
1216
1719
|
openFileInSplit(splitId: number, path: string, line: number, column: number): boolean;
|
|
1217
1720
|
/**
|
|
1721
|
+
* Open `path` as a regular buffer in forced large-file (file-backed)
|
|
1722
|
+
* mode. The file is created (empty) if missing — designed for
|
|
1723
|
+
* buffers that will be filled by a concurrent `spawnProcess` with
|
|
1724
|
+
* `stdoutTo`. Resolves with the new buffer's id, or `null` on
|
|
1725
|
+
* failure.
|
|
1726
|
+
*
|
|
1727
|
+
* Pair with `refreshBufferFromDisk` to grow the buffer as the
|
|
1728
|
+
* streaming write advances.
|
|
1729
|
+
*/
|
|
1730
|
+
openFileStreaming(path: string): Promise<number | null>;
|
|
1731
|
+
/**
|
|
1732
|
+
* Re-stat the file backing `bufferId` and extend the buffer if the
|
|
1733
|
+
* file has grown. Resolves with the new total byte length, or
|
|
1734
|
+
* `null` if the buffer has no file path or doesn't exist.
|
|
1735
|
+
*
|
|
1736
|
+
* Used to drive a streaming display: while a `spawnProcess` writes
|
|
1737
|
+
* to a temp file, the plugin polls this on a timer so the buffer
|
|
1738
|
+
* length tracks the file length.
|
|
1739
|
+
*/
|
|
1740
|
+
refreshBufferFromDisk(bufferId: number): Promise<number | null>;
|
|
1741
|
+
/**
|
|
1218
1742
|
* Show a buffer in the current split
|
|
1219
1743
|
*/
|
|
1220
1744
|
showBuffer(bufferId: number): boolean;
|
|
@@ -1223,6 +1747,30 @@ interface EditorAPI {
|
|
|
1223
1747
|
*/
|
|
1224
1748
|
closeBuffer(bufferId: number): boolean;
|
|
1225
1749
|
/**
|
|
1750
|
+
* Close other buffers in split
|
|
1751
|
+
*/
|
|
1752
|
+
closeOtherBuffersInSplit(bufferId: number, splitId: number): boolean;
|
|
1753
|
+
/**
|
|
1754
|
+
* Close all buffers in split
|
|
1755
|
+
*/
|
|
1756
|
+
closeAllBuffersInSplit(splitId: number): boolean;
|
|
1757
|
+
/**
|
|
1758
|
+
* Close buffers to right in split
|
|
1759
|
+
*/
|
|
1760
|
+
closeBuffersToRightInSplit(bufferId: number, splitId: number): boolean;
|
|
1761
|
+
/**
|
|
1762
|
+
* Close buffers to left in split
|
|
1763
|
+
*/
|
|
1764
|
+
closeBuffersToLeftInSplit(bufferId: number, splitId: number): boolean;
|
|
1765
|
+
/**
|
|
1766
|
+
* Move the active tab to the left in the active split
|
|
1767
|
+
*/
|
|
1768
|
+
moveTabToLeft(): boolean;
|
|
1769
|
+
/**
|
|
1770
|
+
* Move the active tab to the right in the active split
|
|
1771
|
+
*/
|
|
1772
|
+
moveTabToRight(): boolean;
|
|
1773
|
+
/**
|
|
1226
1774
|
* Start a frame-buffer animation over an arbitrary screen region.
|
|
1227
1775
|
* Returns an animation id usable with `cancelAnimation`.
|
|
1228
1776
|
*/
|
|
@@ -1380,6 +1928,64 @@ interface EditorAPI {
|
|
|
1380
1928
|
*/
|
|
1381
1929
|
getUserConfig(): unknown;
|
|
1382
1930
|
/**
|
|
1931
|
+
* Declare a boolean config field for the calling plugin.
|
|
1932
|
+
*
|
|
1933
|
+
* Validates `options` synchronously: the JS call throws if any
|
|
1934
|
+
* unknown key is present or if `default` isn't a boolean. The
|
|
1935
|
+
* Settings UI grows a "Plugin Settings → <plugin>" sub-category
|
|
1936
|
+
* containing a toggle for this field. Returns the current value
|
|
1937
|
+
* (user-set if present, otherwise the declared `default`).
|
|
1938
|
+
*/
|
|
1939
|
+
defineConfigBoolean(name: string, options: {
|
|
1940
|
+
default: boolean;
|
|
1941
|
+
description?: string;
|
|
1942
|
+
}): boolean;
|
|
1943
|
+
/**
|
|
1944
|
+
* Declare an integer config field for the calling plugin. Throws on
|
|
1945
|
+
* invalid options or if the default falls outside `minimum/maximum`.
|
|
1946
|
+
*/
|
|
1947
|
+
defineConfigInteger(name: string, options: {
|
|
1948
|
+
default: number;
|
|
1949
|
+
description?: string;
|
|
1950
|
+
minimum?: number;
|
|
1951
|
+
maximum?: number;
|
|
1952
|
+
}): number;
|
|
1953
|
+
/**
|
|
1954
|
+
* Declare a floating-point number config field. Throws on bad
|
|
1955
|
+
* options or default outside `minimum/maximum`.
|
|
1956
|
+
*/
|
|
1957
|
+
defineConfigNumber(name: string, options: {
|
|
1958
|
+
default: number;
|
|
1959
|
+
description?: string;
|
|
1960
|
+
minimum?: number;
|
|
1961
|
+
maximum?: number;
|
|
1962
|
+
}): number;
|
|
1963
|
+
/**
|
|
1964
|
+
* Declare a free-form string config field.
|
|
1965
|
+
*/
|
|
1966
|
+
defineConfigString(name: string, options: {
|
|
1967
|
+
default: string;
|
|
1968
|
+
description?: string;
|
|
1969
|
+
}): string;
|
|
1970
|
+
/**
|
|
1971
|
+
* Declare an array-of-strings config field (e.g. a list of
|
|
1972
|
+
* patterns). The Settings UI renders this as a list editor.
|
|
1973
|
+
*/
|
|
1974
|
+
defineConfigStringArray(name: string, options: {
|
|
1975
|
+
default: string[];
|
|
1976
|
+
description?: string;
|
|
1977
|
+
}): string[];
|
|
1978
|
+
/**
|
|
1979
|
+
* Get the calling plugin's settings as a JS object.
|
|
1980
|
+
*
|
|
1981
|
+
* Returns the merged value at `config.plugins.<plugin_name>.settings`.
|
|
1982
|
+
* The shape comes from whatever the plugin declared via
|
|
1983
|
+
* `editor.definePluginConfig(...)` (defaults pre-populated by the
|
|
1984
|
+
* host, user overrides on top from the Settings UI). Returns `null`
|
|
1985
|
+
* if the plugin hasn't declared a schema and has no user-set value.
|
|
1986
|
+
*/
|
|
1987
|
+
getPluginConfig(): unknown;
|
|
1988
|
+
/**
|
|
1383
1989
|
* Reload configuration from file
|
|
1384
1990
|
*/
|
|
1385
1991
|
reloadConfig(): void;
|
|
@@ -1602,6 +2208,21 @@ interface EditorAPI {
|
|
|
1602
2208
|
*/
|
|
1603
2209
|
clearFolds(bufferId: number): boolean;
|
|
1604
2210
|
/**
|
|
2211
|
+
* Publish a set of toggleable fold ranges on the buffer. Same
|
|
2212
|
+
* shape an LSP `foldingRange` response would take. Unlike
|
|
2213
|
+
* `addFold`, this does *not* pre-collapse anything — the
|
|
2214
|
+
* standard fold-toggle keybinding finds the range under the
|
|
2215
|
+
* cursor and collapses or expands it on demand. Replacing call
|
|
2216
|
+
* replaces the prior set.
|
|
2217
|
+
*
|
|
2218
|
+
* `ranges` is a JS array of objects shaped
|
|
2219
|
+
* `{ startLine, endLine, kind? }` (lines are 0-indexed).
|
|
2220
|
+
* `kind` is one of `"comment"`, `"imports"`, `"region"` per
|
|
2221
|
+
* the LSP spec; omitted/unknown values are accepted as plain
|
|
2222
|
+
* folds.
|
|
2223
|
+
*/
|
|
2224
|
+
setFoldingRanges(bufferId: number, rangesArr: Record<string, unknown>[]): boolean;
|
|
2225
|
+
/**
|
|
1605
2226
|
* Add a soft break point for marker-based line wrapping
|
|
1606
2227
|
*/
|
|
1607
2228
|
addSoftBreak(bufferId: number, namespace: string, position: number, indent: number): boolean;
|
|
@@ -1676,6 +2297,13 @@ interface EditorAPI {
|
|
|
1676
2297
|
* theme-key string (e.g. `"editor.line_number_fg"`). Theme keys
|
|
1677
2298
|
* are resolved at render time so the line follows theme changes.
|
|
1678
2299
|
* Both default to `null` (no foreground / transparent background).
|
|
2300
|
+
* * `gutterGlyph` — optional single character (any short string)
|
|
2301
|
+
* rendered in the line-number column on this virtual line's
|
|
2302
|
+
* first visual row. Use to mark e.g. a deletion line with "-"
|
|
2303
|
+
* so the indicator sits next to the deleted content instead
|
|
2304
|
+
* of on the following source line.
|
|
2305
|
+
* * `gutterColor` — color for `gutterGlyph`, same shape as
|
|
2306
|
+
* `fg`/`bg`. Falls back to the theme's line-number fg.
|
|
1679
2307
|
*/
|
|
1680
2308
|
addVirtualLine(bufferId: number, position: number, text: string, options: Record<string, unknown>, above: boolean, namespace: string, priority: number): boolean;
|
|
1681
2309
|
/**
|
|
@@ -1750,6 +2378,24 @@ interface EditorAPI {
|
|
|
1750
2378
|
*/
|
|
1751
2379
|
setPromptTitle(title: StyledText[]): boolean;
|
|
1752
2380
|
/**
|
|
2381
|
+
* Set the footer chrome row of the floating-overlay prompt's
|
|
2382
|
+
* results pane. Plugins use this for hotkey-hint banners
|
|
2383
|
+
* (Orchestrator's `[n] new [d] dive [Esc] close` row).
|
|
2384
|
+
* Empty array clears the footer. Has no visible effect on
|
|
2385
|
+
* non-overlay prompts.
|
|
2386
|
+
*/
|
|
2387
|
+
setPromptFooter(footer: StyledText[]): boolean;
|
|
2388
|
+
/**
|
|
2389
|
+
* Override the currently-highlighted suggestion row in the
|
|
2390
|
+
* open prompt. The editor clamps `index` to the suggestion
|
|
2391
|
+
* list's bounds and the renderer scrolls it into view on
|
|
2392
|
+
* the next frame. No-op when no prompt is open or the
|
|
2393
|
+
* suggestion list is empty. Typical use: re-opening a
|
|
2394
|
+
* picker and pre-selecting the entry the user last acted on
|
|
2395
|
+
* (Orchestrator highlights the active session).
|
|
2396
|
+
*/
|
|
2397
|
+
setPromptSelectedIndex(index: number): boolean;
|
|
2398
|
+
/**
|
|
1753
2399
|
* Define a buffer mode (takes bindings as array of [key, command] pairs)
|
|
1754
2400
|
*/
|
|
1755
2401
|
defineMode(name: string, bindingsArr: string[][], readOnly?: boolean, allowTextInput?: boolean, inheritNormalBindings?: boolean): boolean;
|
|
@@ -1774,6 +2420,81 @@ interface EditorAPI {
|
|
|
1774
2420
|
*/
|
|
1775
2421
|
focusSplit(splitId: number): boolean;
|
|
1776
2422
|
/**
|
|
2423
|
+
* Create a new editor session rooted at `root`. `root` must be
|
|
2424
|
+
* an absolute path; relative paths are rejected by the editor
|
|
2425
|
+
* (logged, no session created). The new session's id is
|
|
2426
|
+
* reported via the `window_created` hook payload — plugins
|
|
2427
|
+
* that need the id should listen for that event rather than
|
|
2428
|
+
* polling `listWindows`.
|
|
2429
|
+
*
|
|
2430
|
+
* Returns `false` only when the IPC channel to the editor is
|
|
2431
|
+
* closed (editor is shutting down).
|
|
2432
|
+
*/
|
|
2433
|
+
createWindow(root: string, label: string): boolean;
|
|
2434
|
+
/**
|
|
2435
|
+
* Make the session with id `id` the active one. No-op if
|
|
2436
|
+
* already active. Errors (id not found) are logged on the
|
|
2437
|
+
* editor side; the JS caller can verify by reading
|
|
2438
|
+
* `activeWindow()` after.
|
|
2439
|
+
*/
|
|
2440
|
+
setActiveWindow(id: number): boolean;
|
|
2441
|
+
/**
|
|
2442
|
+
* Close session `id`. Refuses to close the active session or
|
|
2443
|
+
* the base session (id 1). Logs and no-ops on failure.
|
|
2444
|
+
*/
|
|
2445
|
+
closeWindow(id: number): boolean;
|
|
2446
|
+
/**
|
|
2447
|
+
* Eagerly initialise an inactive session's per-session state
|
|
2448
|
+
* (file tree walk, ignore matcher, etc.) without diving.
|
|
2449
|
+
* No-op for the active session or unknown id.
|
|
2450
|
+
*/
|
|
2451
|
+
prewarmWindow(id: number): boolean;
|
|
2452
|
+
/**
|
|
2453
|
+
* Register a `notify`-backed watch on `path`. Returns a
|
|
2454
|
+
* promise that resolves to a numeric `handle` (also passed
|
|
2455
|
+
* in subsequent `path_changed` event payloads). The promise
|
|
2456
|
+
* rejects on `notify` errors (path missing, kernel limit).
|
|
2457
|
+
*
|
|
2458
|
+
* `recursive` defaults to `false`. Non-recursive watches
|
|
2459
|
+
* cover the path itself plus its direct children for
|
|
2460
|
+
* directories — see `services/file_watcher.rs` for the
|
|
2461
|
+
* rationale.
|
|
2462
|
+
*/
|
|
2463
|
+
watchPath(path: string, recursive?: boolean): Promise<number>;
|
|
2464
|
+
/**
|
|
2465
|
+
* Drop a watcher by its handle. Unknown handles are
|
|
2466
|
+
* silently ignored.
|
|
2467
|
+
*/
|
|
2468
|
+
unwatchPath(handle: number): boolean;
|
|
2469
|
+
/**
|
|
2470
|
+
* Tell the editor that the floating-overlay prompt's
|
|
2471
|
+
* preview pane should render the entire split tree of
|
|
2472
|
+
* session `id` natively. `0` (or any unknown id) clears the
|
|
2473
|
+
* override and the preview falls back to the existing
|
|
2474
|
+
* path-based phantom-leaf renderer.
|
|
2475
|
+
*
|
|
2476
|
+
* Orchestrator calls this on each prompt-selection-change so
|
|
2477
|
+
* the right pane shows the highlighted session's full
|
|
2478
|
+
* editor UI live — splits, terminals, syntax highlighting,
|
|
2479
|
+
* decorations — at native rendering cost.
|
|
2480
|
+
*/
|
|
2481
|
+
previewWindowInRect(id: number): boolean;
|
|
2482
|
+
/**
|
|
2483
|
+
* Clear the session-preview override. Equivalent to
|
|
2484
|
+
* `previewWindowInRect(0)` but reads better at call sites.
|
|
2485
|
+
*/
|
|
2486
|
+
clearWindowPreview(): boolean;
|
|
2487
|
+
/**
|
|
2488
|
+
* All editor sessions, sorted by id (creation order). Always
|
|
2489
|
+
* non-empty (the base session is always present).
|
|
2490
|
+
*/
|
|
2491
|
+
listWindows(): WindowInfo[];
|
|
2492
|
+
/**
|
|
2493
|
+
* The currently active session id. Always present in
|
|
2494
|
+
* `listWindows()`.
|
|
2495
|
+
*/
|
|
2496
|
+
activeWindow(): number;
|
|
2497
|
+
/**
|
|
1777
2498
|
* Set scroll position of a split
|
|
1778
2499
|
*/
|
|
1779
2500
|
setSplitScroll(splitId: number, topByte: number): boolean;
|
|
@@ -1855,6 +2576,22 @@ interface EditorAPI {
|
|
|
1855
2576
|
*/
|
|
1856
2577
|
getGlobalState(key: string): unknown;
|
|
1857
2578
|
/**
|
|
2579
|
+
* Set per-session state on the **active** session. Same
|
|
2580
|
+
* shape as `setGlobalState` (write-through to snapshot +
|
|
2581
|
+
* dispatched to editor; null/undefined deletes), but the
|
|
2582
|
+
* underlying storage lives on `Session.plugin_state` and
|
|
2583
|
+
* swaps with the rest of session state on `setActiveWindow`.
|
|
2584
|
+
* Plugins that genuinely want per-project state use this;
|
|
2585
|
+
* Orchestrator itself uses `setGlobalState` because its session
|
|
2586
|
+
* list lives above session boundaries.
|
|
2587
|
+
*/
|
|
2588
|
+
setWindowState(key: string, value: unknown): boolean;
|
|
2589
|
+
/**
|
|
2590
|
+
* Get per-session state from the **active** session
|
|
2591
|
+
* (snapshot read). `undefined` if missing.
|
|
2592
|
+
*/
|
|
2593
|
+
getWindowState(key: string): unknown;
|
|
2594
|
+
/**
|
|
1858
2595
|
* Create a scroll sync group for anchor-based synchronized scrolling
|
|
1859
2596
|
*/
|
|
1860
2597
|
createScrollSyncGroup(groupId: number, leftSplit: number, rightSplit: number): boolean;
|
|
@@ -1879,6 +2616,12 @@ interface EditorAPI {
|
|
|
1879
2616
|
*/
|
|
1880
2617
|
showActionPopup(opts: ActionPopupOptions): boolean;
|
|
1881
2618
|
/**
|
|
2619
|
+
* Contribute (or replace, or clear) menu rows for the LSP-Servers
|
|
2620
|
+
* popup. Pass an empty `items` to clear this plugin's slice for
|
|
2621
|
+
* the given language. See `PluginCommand::SetLspMenuContributions`.
|
|
2622
|
+
*/
|
|
2623
|
+
setLspMenuContributions(pluginId: string, language: string, items: TsLspMenuItem[]): boolean;
|
|
2624
|
+
/**
|
|
1882
2625
|
* Disable LSP for a specific language
|
|
1883
2626
|
*/
|
|
1884
2627
|
disableLspForLanguage(language: string): boolean;
|
|
@@ -1924,6 +2667,15 @@ interface EditorAPI {
|
|
|
1924
2667
|
*/
|
|
1925
2668
|
focusBufferGroupPanel(groupId: number, panelName: string): boolean;
|
|
1926
2669
|
/**
|
|
2670
|
+
* Re-point a buffer-group's panel at a different buffer id.
|
|
2671
|
+
*
|
|
2672
|
+
* Streaming plugins (e.g. git-log) allocate one file-backed
|
|
2673
|
+
* buffer per item and call this on navigation to swap which
|
|
2674
|
+
* buffer the panel displays — instead of mutating a single
|
|
2675
|
+
* shared buffer's contents. Resolves with `true` on success.
|
|
2676
|
+
*/
|
|
2677
|
+
setBufferGroupPanelBuffer(groupId: number, panelName: string, bufferId: number): Promise<boolean>;
|
|
2678
|
+
/**
|
|
1927
2679
|
* Set virtual buffer content (takes array of entry objects)
|
|
1928
2680
|
*
|
|
1929
2681
|
* Note: entries should be TextPropertyEntry[] - uses manual parsing for HashMap support
|
|
@@ -1934,9 +2686,68 @@ interface EditorAPI {
|
|
|
1934
2686
|
*/
|
|
1935
2687
|
getTextPropertiesAtCursor(bufferId: number): TextPropertiesAtCursor;
|
|
1936
2688
|
/**
|
|
2689
|
+
* Mount a declarative widget panel inside a virtual buffer.
|
|
2690
|
+
*
|
|
2691
|
+
* `spec` is a `WidgetSpec` JSON tree (see fresh.d.ts for the
|
|
2692
|
+
* shape). The host renders the spec into the buffer; subsequent
|
|
2693
|
+
* `updateWidgetPanel` calls re-render the panel against the
|
|
2694
|
+
* previously-mounted spec.
|
|
2695
|
+
*
|
|
2696
|
+
* Returns true on successful queue, false if the IPC channel is
|
|
2697
|
+
* closed.
|
|
2698
|
+
*/
|
|
2699
|
+
mountWidgetPanel(panelId: number, bufferId: number, specObj: unknown): boolean;
|
|
2700
|
+
/**
|
|
2701
|
+
* Replace the spec of a previously-mounted widget panel.
|
|
2702
|
+
* No-op if the panel id was never mounted.
|
|
2703
|
+
*/
|
|
2704
|
+
updateWidgetPanel(panelId: number, specObj: unknown): boolean;
|
|
2705
|
+
/**
|
|
2706
|
+
* Unmount a previously-mounted widget panel. The plugin retains
|
|
2707
|
+
* ownership of the underlying virtual buffer.
|
|
2708
|
+
*/
|
|
2709
|
+
unmountWidgetPanel(panelId: number): boolean;
|
|
2710
|
+
/**
|
|
2711
|
+
* Route a keystroke / nav action to the panel's focused widget.
|
|
2712
|
+
*
|
|
2713
|
+
* `action` is a `WidgetAction` JSON object — see fresh.d.ts for
|
|
2714
|
+
* the shapes (`{kind: "focusAdvance", delta: 1}` etc.). Plugin's
|
|
2715
|
+
* `defineMode` bindings dispatch into here for keys handled by
|
|
2716
|
+
* the widget layer; the host runtime acts on the panel's
|
|
2717
|
+
* currently focused widget and fires `widget_event` as
|
|
2718
|
+
* appropriate.
|
|
2719
|
+
*/
|
|
2720
|
+
widgetCommand(panelId: number, actionObj: unknown): boolean;
|
|
2721
|
+
/**
|
|
2722
|
+
* Apply a targeted mutation to a mounted widget panel — the
|
|
2723
|
+
* IPC fast path. Use instead of `updateWidgetPanel` when the
|
|
2724
|
+
* model change touches a single widget; the host applies the
|
|
2725
|
+
* mutation in place without re-transmitting the full spec.
|
|
2726
|
+
* See `WidgetMutation` in fresh.d.ts for the shapes.
|
|
2727
|
+
*/
|
|
2728
|
+
widgetMutate(panelId: number, mutationObj: unknown): boolean;
|
|
2729
|
+
/**
|
|
2730
|
+
* Mount a declarative widget panel as a centered floating
|
|
2731
|
+
* overlay (not bound to any virtual buffer).
|
|
2732
|
+
*/
|
|
2733
|
+
mountFloatingWidget(panelId: number, specObj: unknown, widthPct: number, heightPct: number): boolean;
|
|
2734
|
+
/**
|
|
2735
|
+
* Replace the spec of the currently-mounted floating widget panel.
|
|
2736
|
+
*/
|
|
2737
|
+
updateFloatingWidget(panelId: number, specObj: unknown): boolean;
|
|
2738
|
+
/**
|
|
2739
|
+
* Tear down the floating widget panel.
|
|
2740
|
+
*/
|
|
2741
|
+
unmountFloatingWidget(panelId: number): boolean;
|
|
2742
|
+
/**
|
|
1937
2743
|
* Spawn a process (async, returns request_id)
|
|
2744
|
+
*
|
|
2745
|
+
* Optional 4th argument `stdoutTo: string` pipes the child's stdout
|
|
2746
|
+
* directly into the named file instead of buffering it. The
|
|
2747
|
+
* resolved `SpawnResult.stdout` is empty in that case; the bytes
|
|
2748
|
+
* land on disk for `openFile` to pick up as a file-backed buffer.
|
|
1938
2749
|
*/
|
|
1939
|
-
spawnProcess(command: string, args: string[], cwd?: string): ProcessHandle<SpawnResult>;
|
|
2750
|
+
spawnProcess(command: string, args: string[], cwd?: string, stdoutTo?: string): ProcessHandle<SpawnResult>;
|
|
1940
2751
|
/**
|
|
1941
2752
|
* Spawn a process on the host regardless of the active authority.
|
|
1942
2753
|
*
|
|
@@ -2006,18 +2817,17 @@ interface EditorAPI {
|
|
|
2006
2817
|
*/
|
|
2007
2818
|
grepProject(pattern: string, fixedString: boolean | null, caseSensitive: boolean | null, maxResults: number | null, wholeWords: boolean | null): Promise<GrepMatch[]>;
|
|
2008
2819
|
/**
|
|
2009
|
-
*
|
|
2010
|
-
*
|
|
2011
|
-
*
|
|
2820
|
+
* Begin a streaming project-wide search and return a `SearchHandle`.
|
|
2821
|
+
* The producer (host) writes matches at full speed into shared state;
|
|
2822
|
+
* the consumer drains via `handle.take()` at its own cadence. Call
|
|
2823
|
+
* `handle.cancel()` to abort.
|
|
2012
2824
|
*/
|
|
2013
|
-
|
|
2825
|
+
beginSearch(pattern: string, opts?: {
|
|
2014
2826
|
fixedString?: boolean;
|
|
2015
2827
|
caseSensitive?: boolean;
|
|
2016
2828
|
maxResults?: number;
|
|
2017
2829
|
wholeWords?: boolean;
|
|
2018
|
-
}
|
|
2019
|
-
searchId: number;
|
|
2020
|
-
};
|
|
2830
|
+
}): SearchHandle;
|
|
2021
2831
|
/**
|
|
2022
2832
|
* Replace matches in a file's buffer (async)
|
|
2023
2833
|
* Opens the file if not already in a buffer, applies edits via the buffer model,
|
|
@@ -2049,6 +2859,15 @@ interface EditorAPI {
|
|
|
2049
2859
|
*/
|
|
2050
2860
|
closeTerminal(terminalId: number): boolean;
|
|
2051
2861
|
/**
|
|
2862
|
+
* Send `signal` ("SIGTERM" / "SIGKILL" / "SIGINT" / "SIGHUP")
|
|
2863
|
+
* to every process group the window `id` is tracking. The
|
|
2864
|
+
* window's authority decides delivery; this is the
|
|
2865
|
+
* canonical entry point for "stop everything this window
|
|
2866
|
+
* owns" rather than reaching at the terminal level. Returns
|
|
2867
|
+
* `false` only when the command channel is closed.
|
|
2868
|
+
*/
|
|
2869
|
+
signalWindow(id: number, signal: string): boolean;
|
|
2870
|
+
/**
|
|
2052
2871
|
* Force refresh of line display
|
|
2053
2872
|
*/
|
|
2054
2873
|
refreshLines(bufferId: number): boolean;
|
|
@@ -2088,6 +2907,33 @@ interface EditorAPI {
|
|
|
2088
2907
|
getPluginApi<K extends keyof FreshPluginRegistry>(name: K): FreshPluginRegistry[K] | null;
|
|
2089
2908
|
}
|
|
2090
2909
|
/**
|
|
2910
|
+
* Typed overload of `editor.defineConfigEnum`. The macro-generated
|
|
2911
|
+
* signature can't express `<E extends string>` propagating from the
|
|
2912
|
+
* `values` array into the return type, so it's declared here. Use
|
|
2913
|
+
* `as const` on the `values` array to get a literal-union return:
|
|
2914
|
+
*
|
|
2915
|
+
* ```ts
|
|
2916
|
+
* const mode = editor.defineConfigEnum("mode", {
|
|
2917
|
+
* values: ["normal", "insert"] as const,
|
|
2918
|
+
* default: "normal",
|
|
2919
|
+
* });
|
|
2920
|
+
* mode; // typed as "normal" | "insert"
|
|
2921
|
+
* ```
|
|
2922
|
+
*
|
|
2923
|
+
* Typed overload of `editor.getPluginConfig`. Plugins that declared
|
|
2924
|
+
* their fields via `defineConfigX` can pass the shape type explicitly:
|
|
2925
|
+
* `editor.getPluginConfig<{ autoEnable: boolean; ... }>()`. Without
|
|
2926
|
+
* the generic, falls back to `unknown`.
|
|
2927
|
+
*/
|
|
2928
|
+
interface EditorAPI {
|
|
2929
|
+
defineConfigEnum<E extends string>(name: string, options: {
|
|
2930
|
+
values: readonly E[];
|
|
2931
|
+
default: NoInfer<E>;
|
|
2932
|
+
description?: string;
|
|
2933
|
+
}): E;
|
|
2934
|
+
getPluginConfig<T = unknown>(): T;
|
|
2935
|
+
}
|
|
2936
|
+
/**
|
|
2091
2937
|
* Maps every hook event name to its payload type.
|
|
2092
2938
|
*
|
|
2093
2939
|
* Payloads match the flat JSON produced by `hook_args_to_json` on the Rust
|
|
@@ -2321,6 +3167,56 @@ interface HookEventMap {
|
|
|
2321
3167
|
action: string;
|
|
2322
3168
|
}[];
|
|
2323
3169
|
};
|
|
3170
|
+
// ── PTY terminals (see crates/fresh-core/src/hooks.rs) ───────────────────
|
|
3171
|
+
terminal_output: {
|
|
3172
|
+
terminal_id: number;
|
|
3173
|
+
last_line: string;
|
|
3174
|
+
};
|
|
3175
|
+
terminal_exit: {
|
|
3176
|
+
terminal_id: number;
|
|
3177
|
+
exit_code: number | null;
|
|
3178
|
+
};
|
|
3179
|
+
// ── filesystem watching (watchPath plugin API) ────────────────────────────
|
|
3180
|
+
path_changed: {
|
|
3181
|
+
handle: number;
|
|
3182
|
+
path: string;
|
|
3183
|
+
/** "modify" | "create" | "delete" | "rename" | "other" */
|
|
3184
|
+
kind: string;
|
|
3185
|
+
};
|
|
3186
|
+
// ── editor sessions (Orchestrator; see orchestrator-sessions-design.md) ────────
|
|
3187
|
+
window_created: {
|
|
3188
|
+
id: number;
|
|
3189
|
+
label: string;
|
|
3190
|
+
root: string;
|
|
3191
|
+
};
|
|
3192
|
+
window_closed: {
|
|
3193
|
+
id: number;
|
|
3194
|
+
};
|
|
3195
|
+
active_window_changed: {
|
|
3196
|
+
previous_id: number | null;
|
|
3197
|
+
active_id: number;
|
|
3198
|
+
};
|
|
3199
|
+
// ── widget runtime ───────────────────────────────────────────────────────
|
|
3200
|
+
/**
|
|
3201
|
+
* A widget mounted via `editor.mountWidgetPanel` emitted a
|
|
3202
|
+
* semantic event. Fired when the host's hit-test routes a mouse
|
|
3203
|
+
* click to a `Toggle` / `Button` widget node within a mounted
|
|
3204
|
+
* widget panel. See `docs/internal/plugin-widget-library-design.md`.
|
|
3205
|
+
*
|
|
3206
|
+
* Routing is by `panel_id` (matches the id the plugin allocated
|
|
3207
|
+
* at mount time) plus `widget_key` (the stable `key` set on the
|
|
3208
|
+
* widget spec node, or empty when the spec did not assign one).
|
|
3209
|
+
*
|
|
3210
|
+
* `event_type` and `payload` shapes:
|
|
3211
|
+
* * Toggle: `event_type = "toggle"`, `payload = { checked: <new> }`.
|
|
3212
|
+
* * Button: `event_type = "activate"`, `payload = {}`.
|
|
3213
|
+
*/
|
|
3214
|
+
widget_event: {
|
|
3215
|
+
panel_id: number;
|
|
3216
|
+
widget_key: string;
|
|
3217
|
+
event_type: string;
|
|
3218
|
+
payload: Record<string, unknown>;
|
|
3219
|
+
};
|
|
2324
3220
|
}
|
|
2325
3221
|
/**
|
|
2326
3222
|
* Typed overloads of `editor.on` / `editor.off`.
|