@fresh-editor/fresh-editor 0.3.8 → 0.3.9
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 +49 -0
- package/README.md +0 -1
- package/package.json +1 -1
- package/plugins/dashboard.ts +3 -3
- package/plugins/examples/bookmarks.ts +3 -2
- package/plugins/lib/finder.ts +57 -10
- package/plugins/lib/fresh.d.ts +71 -31
- package/plugins/lib/widgets.ts +8 -0
- package/plugins/live_grep.i18n.json +349 -27
- package/plugins/live_grep.ts +596 -141
- package/plugins/orchestrator.ts +1227 -393
- package/plugins/vi_mode.ts +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,54 @@
|
|
|
1
1
|
# Release Notes
|
|
2
2
|
|
|
3
|
+
## 0.3.9
|
|
4
|
+
|
|
5
|
+
### Features
|
|
6
|
+
|
|
7
|
+
#### Universal Search (multi-scope Live Grep)
|
|
8
|
+
|
|
9
|
+
Live Grep grows into a universal search overlay: search across multiple **scopes** — project files, open **Buffers**, and **Terminals** scrollback — with **Word** and **Regex** search modes (each keybindable). The overlay gets a clickable widget toolbar (focusable provider button, toggle controls), a full-width header band, and inline status shown in the overlay itself. Closed-terminal scrollback is retained so it stays searchable (#2099).
|
|
10
|
+
|
|
11
|
+
#### Orchestrator & git worktrees
|
|
12
|
+
|
|
13
|
+
* **Attach sessions to existing git worktrees** and discover them automatically (#2095).
|
|
14
|
+
* Multi-select **bulk actions**, worktree ordering, and a *Show all worktrees* filter toggle.
|
|
15
|
+
* Draggable scrollbars on the picker lists, with bulk-pane reorder.
|
|
16
|
+
|
|
17
|
+
#### Editor
|
|
18
|
+
|
|
19
|
+
* **Move to Next / Previous Paragraph** actions, including translations (#2084, contributed by @PavelLoparev; requested in #2083).
|
|
20
|
+
|
|
21
|
+
#### Language Support
|
|
22
|
+
|
|
23
|
+
* **C3** (`.c3`) syntax highlighting and LSP (#2101, requested by @data-man).
|
|
24
|
+
|
|
25
|
+
#### Plugins & API
|
|
26
|
+
|
|
27
|
+
* New `getWorkingDataDir()` (per-working-dir data root) and `getTerminalDir()` plugin APIs.
|
|
28
|
+
* Overlay toolbar widget APIs — clickable `Toggle`/`Button` controls, `toggleOverlayToolbarWidget`, and a `Row { wrap }` layout that reflows toolbars across lines.
|
|
29
|
+
|
|
30
|
+
### Improvements
|
|
31
|
+
|
|
32
|
+
* The **dashboard no longer opens automatically** on startup by default. To re-enable it, open **Settings**, select **Plugin: dashboard**, and turn on **AutoOpen** ("Show the dashboard automatically when Fresh starts with no real files open."). The dashboard remains available any time via the **Show Dashboard** command.
|
|
33
|
+
* Homebrew install simplified now that fresh-editor is in homebrew-core — `brew install fresh-editor`, no tap step.
|
|
34
|
+
|
|
35
|
+
### Bug Fixes
|
|
36
|
+
|
|
37
|
+
* Plugin `getCursorLine()` now returns the real cursor line instead of `0` (#2076, reported by @pmburov).
|
|
38
|
+
* **Reduced serial-console lag** by not repainting on non-visual plugin async events (#2100, reported by @jetpax).
|
|
39
|
+
* **Custom theme colours** no longer silently ignored for many UI fields (#2080, contributed by @flexiondotorg; reported in #2079).
|
|
40
|
+
* `PageDown`/`PageUp` no longer overshoot on a single soft-wrapped line (#2085).
|
|
41
|
+
* **Workspace restore** no longer mixes tabs from multiple projects in one window (#2056, reported by @mandolyte).
|
|
42
|
+
* **Live Grep**: *Resume* keeps the query and opens the selected result; overlay preview and input-box undo/redo corrected; Buffers scope finds unmodified open buffers; non-file-scope previews and read-only data-dir files fixed.
|
|
43
|
+
* `getKeybindingLabel` resolves correctly for bound plugin actions.
|
|
44
|
+
|
|
45
|
+
### Internal
|
|
46
|
+
|
|
47
|
+
* Major window refactor: window-scoped save/restore (`Window::from_workspace`), `WindowId`-parameterized persistence, `working_dir` derived from the active window, and `open_file`/LSP/watch helpers moved onto `Window`.
|
|
48
|
+
* Orchestrator bring-up characterization tests and fixtures across persistence layouts.
|
|
49
|
+
* Serial-console lag benchmark/diagnostic scripts; theme-key resolver schema-drift guard.
|
|
50
|
+
* Internal docs excluded from the public docs build.
|
|
51
|
+
|
|
3
52
|
## 0.3.8
|
|
4
53
|
|
|
5
54
|
### Features / Improvements
|
package/README.md
CHANGED
|
@@ -84,7 +84,6 @@ On macOS and some linux distros (Bazzite/Bluefin/Aurora):
|
|
|
84
84
|
> **Note:** On macOS, see [macOS Terminal Tips](https://getfresh.dev/docs/configuration/keyboard#macos-terminal-tips) for recommended terminal configuration.
|
|
85
85
|
|
|
86
86
|
```bash
|
|
87
|
-
brew tap sinelaw/fresh
|
|
88
87
|
brew install fresh-editor
|
|
89
88
|
```
|
|
90
89
|
|
package/package.json
CHANGED
package/plugins/dashboard.ts
CHANGED
|
@@ -16,7 +16,7 @@ const editor = getEditor();
|
|
|
16
16
|
// it is never loaded, so no buffers are created, no timers run,
|
|
17
17
|
// and no network fetches fire.
|
|
18
18
|
//
|
|
19
|
-
// A second flag `plugins.dashboard.auto-open` (default
|
|
19
|
+
// A second flag `plugins.dashboard.auto-open` (default false) gates
|
|
20
20
|
// only the ambient open paths (startup + last-buffer-closed). When
|
|
21
21
|
// false the plugin still loads and the "Show Dashboard" command is
|
|
22
22
|
// still available — it just won't appear on its own.
|
|
@@ -1590,7 +1590,7 @@ registerHandler("dashboardShowOrFocus", dashboardShowOrFocus);
|
|
|
1590
1590
|
// comes from the typed plugin-config field declared below. The field
|
|
1591
1591
|
// shows up in the Settings UI under "Plugin Settings → dashboard".
|
|
1592
1592
|
editor.defineConfigBoolean("autoOpen", {
|
|
1593
|
-
default:
|
|
1593
|
+
default: false,
|
|
1594
1594
|
description: "Show the dashboard automatically when Fresh starts with no real files open.",
|
|
1595
1595
|
});
|
|
1596
1596
|
|
|
@@ -1599,7 +1599,7 @@ let autoOpenOverride: boolean | null = null;
|
|
|
1599
1599
|
function autoOpenEnabled(): boolean {
|
|
1600
1600
|
if (autoOpenOverride !== null) return autoOpenOverride;
|
|
1601
1601
|
const cfg = (editor.getPluginConfig() ?? {}) as { autoOpen?: boolean };
|
|
1602
|
-
return cfg.autoOpen
|
|
1602
|
+
return cfg.autoOpen === true;
|
|
1603
1603
|
}
|
|
1604
1604
|
|
|
1605
1605
|
function shouldShowDashboard(): boolean {
|
|
@@ -46,8 +46,9 @@ function getCurrentLocation(): {
|
|
|
46
46
|
|
|
47
47
|
// Helper: Get actual line number using the API
|
|
48
48
|
function getCurrentLineCol(): { line: number; column: number } {
|
|
49
|
-
//
|
|
50
|
-
|
|
49
|
+
// Read the primary cursor's line from the snapshot. `line` is null when the
|
|
50
|
+
// buffer has no line index yet (huge files); fall back to 0 there.
|
|
51
|
+
const lineNumber = editor.getPrimaryCursor()?.line ?? 0;
|
|
51
52
|
|
|
52
53
|
// Get cursor position within the line by reading buffer content
|
|
53
54
|
const bufferId = editor.getActiveBufferId();
|
package/plugins/lib/finder.ts
CHANGED
|
@@ -447,6 +447,33 @@ export class Finder<T> {
|
|
|
447
447
|
// Mode flags
|
|
448
448
|
private isPromptMode = false;
|
|
449
449
|
private isPanelMode = false;
|
|
450
|
+
/** True when the active prompt is a centred floating overlay. Search
|
|
451
|
+
* status then goes to the overlay's own footer (visible inside the frame)
|
|
452
|
+
* rather than the editor status bar (off at the bottom, easy to miss). */
|
|
453
|
+
private isOverlay = false;
|
|
454
|
+
|
|
455
|
+
/** Present a search-status message where the user is actually looking: on
|
|
456
|
+
* the overlay's input row (right-aligned by the match count) for a
|
|
457
|
+
* floating overlay, else the editor status bar. */
|
|
458
|
+
private setSearchStatus(message: string): void {
|
|
459
|
+
if (this.isOverlay) {
|
|
460
|
+
this.editor.setPromptStatus(message);
|
|
461
|
+
} else {
|
|
462
|
+
this.editor.setStatus(message);
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
/** Report a successful search with `count` matches. In overlay mode the
|
|
467
|
+
* "N / total" count on the input row already conveys this, so the status
|
|
468
|
+
* is cleared to avoid duplicating it; the status bar (non-overlay) still
|
|
469
|
+
* shows "Found N matches". */
|
|
470
|
+
private reportFound(count: number): void {
|
|
471
|
+
if (this.isOverlay) {
|
|
472
|
+
this.editor.setPromptStatus("");
|
|
473
|
+
} else {
|
|
474
|
+
this.editor.setStatus(`Found ${count} matches`);
|
|
475
|
+
}
|
|
476
|
+
}
|
|
450
477
|
|
|
451
478
|
// Handler names (for cleanup)
|
|
452
479
|
private handlerPrefix: string;
|
|
@@ -513,6 +540,7 @@ export class Finder<T> {
|
|
|
513
540
|
|
|
514
541
|
// Start the prompt
|
|
515
542
|
const overlay = options.floatingOverlay === true;
|
|
543
|
+
this.isOverlay = overlay;
|
|
516
544
|
if (options.initialQuery) {
|
|
517
545
|
this.editor.startPromptWithInitial(
|
|
518
546
|
options.title,
|
|
@@ -525,7 +553,7 @@ export class Finder<T> {
|
|
|
525
553
|
const result = this.editor.startPrompt(options.title, this.config.id, overlay);
|
|
526
554
|
this.editor.debug(`[Finder] startPrompt returned: ${result}`);
|
|
527
555
|
}
|
|
528
|
-
this.
|
|
556
|
+
this.setSearchStatus("Type to search…");
|
|
529
557
|
}
|
|
530
558
|
|
|
531
559
|
/**
|
|
@@ -545,6 +573,11 @@ export class Finder<T> {
|
|
|
545
573
|
// unchanged query.
|
|
546
574
|
this.promptState.lastQuery = "";
|
|
547
575
|
if (query.length === 0) return;
|
|
576
|
+
// The backend (or scope set) changed, so the on-screen results are now
|
|
577
|
+
// stale. Clear them and show progress immediately rather than leaving the
|
|
578
|
+
// previous output up while the (possibly slow) new search runs.
|
|
579
|
+
this.updatePromptResults([]);
|
|
580
|
+
this.setSearchStatus("Searching…");
|
|
548
581
|
await this.runSearch(query, this.currentSource);
|
|
549
582
|
}
|
|
550
583
|
|
|
@@ -713,9 +746,9 @@ export class Finder<T> {
|
|
|
713
746
|
this.updatePromptResults(filtered);
|
|
714
747
|
|
|
715
748
|
if (filtered.length > 0) {
|
|
716
|
-
this.
|
|
749
|
+
this.reportFound(filtered.length);
|
|
717
750
|
} else {
|
|
718
|
-
this.
|
|
751
|
+
this.setSearchStatus("No matches");
|
|
719
752
|
}
|
|
720
753
|
} else {
|
|
721
754
|
// Search mode: run external search
|
|
@@ -745,6 +778,7 @@ export class Finder<T> {
|
|
|
745
778
|
}
|
|
746
779
|
this.editor.setPromptSuggestions([]);
|
|
747
780
|
this.promptState.results = [];
|
|
781
|
+
this.setSearchStatus("");
|
|
748
782
|
return;
|
|
749
783
|
}
|
|
750
784
|
|
|
@@ -768,6 +802,11 @@ export class Finder<T> {
|
|
|
768
802
|
}
|
|
769
803
|
this.promptState.lastQuery = query;
|
|
770
804
|
|
|
805
|
+
// A search is now actually starting (every query change that gets here —
|
|
806
|
+
// typing, deleting, provider/scope refresh). Show pending status so the
|
|
807
|
+
// user sees the re-scan in progress rather than a stale result count.
|
|
808
|
+
this.setSearchStatus("Searching…");
|
|
809
|
+
|
|
771
810
|
try {
|
|
772
811
|
const searchResult = source.search(query);
|
|
773
812
|
|
|
@@ -793,21 +832,21 @@ export class Finder<T> {
|
|
|
793
832
|
this.updatePromptResults(parsed);
|
|
794
833
|
|
|
795
834
|
if (parsed.length > 0) {
|
|
796
|
-
this.
|
|
835
|
+
this.reportFound(parsed.length);
|
|
797
836
|
// Show preview of first result
|
|
798
837
|
if (this.shouldShowPreview()) {
|
|
799
838
|
await this.updatePreview(this.promptState.entries[0]);
|
|
800
839
|
}
|
|
801
840
|
} else {
|
|
802
|
-
this.
|
|
841
|
+
this.setSearchStatus("No matches");
|
|
803
842
|
}
|
|
804
843
|
} else if (result.exit_code === 1) {
|
|
805
844
|
// No matches
|
|
806
845
|
this.updatePromptResults([]);
|
|
807
|
-
this.
|
|
846
|
+
this.setSearchStatus("No matches");
|
|
808
847
|
} else if (result.exit_code !== -1) {
|
|
809
848
|
// Error (ignore -1 which means killed)
|
|
810
|
-
this.
|
|
849
|
+
this.setSearchStatus(`Search error: ${result.stderr}`);
|
|
811
850
|
}
|
|
812
851
|
} else {
|
|
813
852
|
// Promise<T[]>
|
|
@@ -821,12 +860,12 @@ export class Finder<T> {
|
|
|
821
860
|
this.updatePromptResults(results);
|
|
822
861
|
|
|
823
862
|
if (results.length > 0) {
|
|
824
|
-
this.
|
|
863
|
+
this.reportFound(results.length);
|
|
825
864
|
if (this.shouldShowPreview()) {
|
|
826
865
|
await this.updatePreview(this.promptState.entries[0]);
|
|
827
866
|
}
|
|
828
867
|
} else {
|
|
829
|
-
this.
|
|
868
|
+
this.setSearchStatus("No matches");
|
|
830
869
|
}
|
|
831
870
|
}
|
|
832
871
|
} catch (e) {
|
|
@@ -864,7 +903,15 @@ export class Finder<T> {
|
|
|
864
903
|
(entry, i) => ({
|
|
865
904
|
text: entry.label,
|
|
866
905
|
description: entry.description,
|
|
867
|
-
value
|
|
906
|
+
// The preview pane uses `value` as the authoritative
|
|
907
|
+
// `path:line:col` for the result. We must not rely on parsing the
|
|
908
|
+
// user-facing label, which may carry source badges (e.g. "[term]")
|
|
909
|
+
// that make the label unparseable as a path.
|
|
910
|
+
value: entry.location
|
|
911
|
+
? `${entry.location.file}:${entry.location.line}:${
|
|
912
|
+
entry.location.column ?? 1
|
|
913
|
+
}`
|
|
914
|
+
: `${i}`,
|
|
868
915
|
disabled: false,
|
|
869
916
|
})
|
|
870
917
|
);
|
package/plugins/lib/fresh.d.ts
CHANGED
|
@@ -735,6 +735,13 @@ type CursorInfo = {
|
|
|
735
735
|
start: number;
|
|
736
736
|
end: number;
|
|
737
737
|
} | null;
|
|
738
|
+
/**
|
|
739
|
+
* 0-indexed line number of the cursor. `None` when the line index is
|
|
740
|
+
* unavailable — e.g. a huge file whose line scan hasn't completed, where
|
|
741
|
+
* the editor positions purely by byte offset. Plugins must treat `null`
|
|
742
|
+
* as "unknown", never as line 0.
|
|
743
|
+
*/
|
|
744
|
+
line: number | null;
|
|
738
745
|
};
|
|
739
746
|
type OverlayOptions = {
|
|
740
747
|
/**
|
|
@@ -1695,7 +1702,13 @@ interface EditorAPI {
|
|
|
1695
1702
|
*/
|
|
1696
1703
|
listSplits(): SplitSnapshot[];
|
|
1697
1704
|
/**
|
|
1698
|
-
* Get the line number (0-indexed) of the primary cursor
|
|
1705
|
+
* Get the line number (0-indexed) of the primary cursor.
|
|
1706
|
+
*
|
|
1707
|
+
* @deprecated Use `getPrimaryCursor()?.line` instead. This accessor cannot
|
|
1708
|
+
* represent "line index unavailable" (huge files before their line scan) —
|
|
1709
|
+
* it returns `0` in that case, indistinguishable from a real first line.
|
|
1710
|
+
* `getPrimaryCursor().line` is `number | null` and also covers every cursor
|
|
1711
|
+
* via `getAllCursors()`.
|
|
1699
1712
|
*/
|
|
1700
1713
|
getCursorLine(): number;
|
|
1701
1714
|
/**
|
|
@@ -1864,38 +1877,17 @@ interface EditorAPI {
|
|
|
1864
1877
|
*/
|
|
1865
1878
|
getAuthorityLabel(): string;
|
|
1866
1879
|
/**
|
|
1867
|
-
* Current Workspace Trust level for the active project:
|
|
1868
|
-
* `"
|
|
1869
|
-
*
|
|
1870
|
-
*
|
|
1871
|
-
* Trust is a per-project, user-granted decision. Plugins that run
|
|
1872
|
-
* repo-controlled work (env activation, project tooling, repo-local
|
|
1873
|
-
* binaries) MUST gate on this and treat anything other than
|
|
1874
|
-
* `"trusted"` as "do not execute".
|
|
1875
|
-
*/
|
|
1876
|
-
workspaceTrustLevel(): "restricted" | "trusted" | "blocked" | "";
|
|
1877
|
-
/**
|
|
1878
|
-
* Activate an environment by setting the live env recipe: an activation
|
|
1879
|
-
* shell `snippet` (e.g. `eval "$(direnv export bash)"`,
|
|
1880
|
-
* `source .venv/bin/activate`, or `""` for a pure login shell) run in
|
|
1881
|
-
* `dir` (defaults to the workspace). It is re-evaluated on demand on the
|
|
1882
|
-
* active backend and applied to every spawn — language servers,
|
|
1883
|
-
* formatters, `spawnProcess` — so they see the project environment. No
|
|
1884
|
-
* authority rebuild; the LSP is restarted to pick it up.
|
|
1885
|
-
*
|
|
1886
|
-
* Honored only when `workspaceTrustLevel() === "trusted"` (it runs
|
|
1887
|
-
* repo-controlled code). Call `clearEnv()` to deactivate.
|
|
1888
|
-
*/
|
|
1889
|
-
setEnv(snippet: string, dir?: string): void;
|
|
1890
|
-
/**
|
|
1891
|
-
* Deactivate the environment set by `setEnv` — spawns return to the
|
|
1892
|
-
* inherited environment.
|
|
1880
|
+
* Current Workspace Trust level for the active project: `"restricted"`,
|
|
1881
|
+
* `"trusted"`, or `"blocked"` (empty when unavailable). Exposed to JS as
|
|
1882
|
+
* `editor.workspaceTrustLevel()`. Plugins that run repo-controlled work
|
|
1883
|
+
* should treat anything other than `"trusted"` as "do not execute".
|
|
1893
1884
|
*/
|
|
1894
|
-
|
|
1885
|
+
workspaceTrustLevel(): string;
|
|
1895
1886
|
/**
|
|
1896
|
-
* Whether an environment is currently active (
|
|
1897
|
-
*
|
|
1898
|
-
* re-establish its file watch
|
|
1887
|
+
* Whether an environment is currently active (set via `editor.setEnv`).
|
|
1888
|
+
* Exposed to JS as `editor.envActive()`. Lets the env-manager plugin
|
|
1889
|
+
* reflect activation and re-establish its file watch after the restart
|
|
1890
|
+
* that `setEnv` triggers.
|
|
1899
1891
|
*/
|
|
1900
1892
|
envActive(): boolean;
|
|
1901
1893
|
/**
|
|
@@ -2134,6 +2126,21 @@ interface EditorAPI {
|
|
|
2134
2126
|
*/
|
|
2135
2127
|
getDataDir(): string;
|
|
2136
2128
|
/**
|
|
2129
|
+
* Per-working-directory data root for plugin state that should be scoped
|
|
2130
|
+
* to the current project root / worktree rather than shared across all of
|
|
2131
|
+
* them (`<data_dir>/workdirs/<encoded-cwd>/`). Prefer this over
|
|
2132
|
+
* `getDataDir()` for per-project state; the directory is not created for
|
|
2133
|
+
* you. Note: terminal scrollback and orchestrator state use their own
|
|
2134
|
+
* dedicated layouts (see `getTerminalDir()`), not this root.
|
|
2135
|
+
*/
|
|
2136
|
+
getWorkingDataDir(): string;
|
|
2137
|
+
/**
|
|
2138
|
+
* Directory holding terminal scrollback backing files for the current
|
|
2139
|
+
* working directory. Each project root / worktree has its own subdir, so
|
|
2140
|
+
* a search can stay scoped to the active project's terminals.
|
|
2141
|
+
*/
|
|
2142
|
+
getTerminalDir(): string;
|
|
2143
|
+
/**
|
|
2137
2144
|
* Get themes directory path
|
|
2138
2145
|
*/
|
|
2139
2146
|
getThemesDir(): string;
|
|
@@ -2472,6 +2479,29 @@ interface EditorAPI {
|
|
|
2472
2479
|
*/
|
|
2473
2480
|
setPromptFooter(footer: StyledText[]): boolean;
|
|
2474
2481
|
/**
|
|
2482
|
+
* Set the floating-overlay prompt's header toolbar as a `WidgetSpec`
|
|
2483
|
+
* (real, clickable `Toggle`/`Button` widgets), rendered in place of the
|
|
2484
|
+
* styled-text title. Give each control a `key` equal to the action it
|
|
2485
|
+
* should fire on click (e.g. `"live_grep_toggle_files"`). Pass `null` to
|
|
2486
|
+
* clear it. No visible effect on non-overlay prompts.
|
|
2487
|
+
*/
|
|
2488
|
+
setPromptToolbar(spec: WidgetSpec | null): boolean;
|
|
2489
|
+
/**
|
|
2490
|
+
* Set the floating-overlay prompt's input-row status text, shown
|
|
2491
|
+
* right-aligned just left of the `selected / total` count (e.g.
|
|
2492
|
+
* "Searching…", "No matches"). Empty string clears it. No effect on
|
|
2493
|
+
* non-overlay prompts.
|
|
2494
|
+
*/
|
|
2495
|
+
setPromptStatus(status: string): boolean;
|
|
2496
|
+
/**
|
|
2497
|
+
* Toggle a floating-overlay toolbar control by its widget `key`. The host
|
|
2498
|
+
* owns the toggle's checked state, flips it in place, and emits a
|
|
2499
|
+
* `widget_event` (`event_type: "toggle"`, payload `{ checked }`). Use this
|
|
2500
|
+
* to route a plugin's own keyboard shortcut through the same host path as
|
|
2501
|
+
* a click or Space on the toggle, then react in your `widget_event` handler.
|
|
2502
|
+
*/
|
|
2503
|
+
toggleOverlayToolbarWidget(key: string): boolean;
|
|
2504
|
+
/**
|
|
2475
2505
|
* Override the currently-highlighted suggestion row in the
|
|
2476
2506
|
* open prompt. The editor clamps `index` to the suggestion
|
|
2477
2507
|
* list's bounds and the renderer scrolls it into view on
|
|
@@ -2860,6 +2890,16 @@ interface EditorAPI {
|
|
|
2860
2890
|
*/
|
|
2861
2891
|
clearAuthority(): void;
|
|
2862
2892
|
/**
|
|
2893
|
+
* Activate an environment: set the live env recipe (`snippet` run in
|
|
2894
|
+
* `dir`). Applied to every spawn, re-evaluated on demand — no restart.
|
|
2895
|
+
* Honored only when the workspace is Trusted.
|
|
2896
|
+
*/
|
|
2897
|
+
setEnv(snippet: string, dir: string | null): void;
|
|
2898
|
+
/**
|
|
2899
|
+
* Deactivate the environment — spawns return to the inherited env.
|
|
2900
|
+
*/
|
|
2901
|
+
clearEnv(): void;
|
|
2902
|
+
/**
|
|
2863
2903
|
* Override the Remote Indicator's displayed state. Plugins call
|
|
2864
2904
|
* this to surface lifecycle transitions that the authority layer
|
|
2865
2905
|
* doesn't know about yet — "Connecting" while `devcontainer up`
|
package/plugins/lib/widgets.ts
CHANGED
|
@@ -60,6 +60,14 @@ export function row(...children: WidgetSpec[]): WidgetSpec {
|
|
|
60
60
|
return { kind: "row", children };
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
+
/** Horizontal layout that **wraps**: children that don't fit on one line
|
|
64
|
+
* reflow onto additional lines (growing the row's height) instead of being
|
|
65
|
+
* truncated. Children are never split, so wrap a logical group (e.g. a
|
|
66
|
+
* toggle + its accelerator) in a nested `row(...)` to keep it intact. */
|
|
67
|
+
export function wrappingRow(...children: WidgetSpec[]): WidgetSpec {
|
|
68
|
+
return { kind: "row", children, wrap: true };
|
|
69
|
+
}
|
|
70
|
+
|
|
63
71
|
/** Vertical layout. Children stacked top-to-bottom. */
|
|
64
72
|
export function col(...children: WidgetSpec[]): WidgetSpec {
|
|
65
73
|
return { kind: "col", children };
|