@fresh-editor/fresh-editor 0.3.0 → 0.3.2
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 +120 -2
- package/package.json +1 -1
- package/plugins/astro-lsp.ts +6 -12
- package/plugins/audit_mode.ts +106 -113
- package/plugins/bash-lsp.ts +15 -22
- package/plugins/clangd-lsp.ts +15 -24
- package/plugins/clojure-lsp.ts +9 -12
- package/plugins/cmake-lsp.ts +9 -12
- package/plugins/code-tour.ts +15 -16
- package/plugins/config-schema.json +49 -5
- package/plugins/csharp_support.ts +25 -30
- package/plugins/css-lsp.ts +15 -22
- package/plugins/dart-lsp.ts +9 -12
- package/plugins/dashboard.ts +118 -0
- package/plugins/devcontainer.i18n.json +84 -28
- package/plugins/devcontainer.ts +897 -170
- package/plugins/diagnostics_panel.ts +10 -17
- package/plugins/diff_nav.ts +20 -1
- package/plugins/elixir-lsp.ts +9 -12
- package/plugins/erlang-lsp.ts +9 -12
- package/plugins/examples/bookmarks.ts +10 -16
- package/plugins/find_references.ts +5 -9
- package/plugins/flash.ts +585 -0
- package/plugins/fsharp-lsp.ts +9 -12
- package/plugins/git_explorer.ts +16 -20
- package/plugins/git_gutter.ts +65 -79
- package/plugins/git_log.ts +8 -8
- package/plugins/gleam-lsp.ts +9 -12
- package/plugins/go-lsp.ts +15 -22
- package/plugins/graphql-lsp.ts +9 -12
- package/plugins/haskell-lsp.ts +9 -12
- package/plugins/html-lsp.ts +15 -24
- package/plugins/java-lsp.ts +9 -12
- package/plugins/json-lsp.ts +15 -24
- package/plugins/julia-lsp.ts +9 -12
- package/plugins/kotlin-lsp.ts +15 -22
- package/plugins/latex-lsp.ts +9 -12
- package/plugins/lib/fresh.d.ts +378 -0
- package/plugins/live_diff.i18n.json +450 -0
- package/plugins/live_diff.ts +946 -0
- package/plugins/lua-lsp.ts +15 -22
- package/plugins/markdown_compose.ts +78 -122
- package/plugins/markdown_source.ts +8 -10
- package/plugins/marksman-lsp.ts +9 -12
- package/plugins/merge_conflict.ts +15 -17
- package/plugins/nim-lsp.ts +9 -12
- package/plugins/nix-lsp.ts +9 -12
- package/plugins/nushell-lsp.ts +9 -12
- package/plugins/ocaml-lsp.ts +9 -12
- package/plugins/odin-lsp.ts +15 -22
- package/plugins/path_complete.ts +5 -6
- package/plugins/perl-lsp.ts +9 -12
- package/plugins/php-lsp.ts +15 -22
- package/plugins/pkg.ts +10 -21
- package/plugins/protobuf-lsp.ts +9 -12
- package/plugins/python-lsp.ts +15 -24
- package/plugins/r-lsp.ts +9 -12
- package/plugins/ruby-lsp.ts +15 -22
- package/plugins/rust-lsp.ts +18 -28
- package/plugins/scala-lsp.ts +9 -12
- package/plugins/schemas/theme.schema.json +66 -0
- package/plugins/search_replace.ts +10 -13
- package/plugins/solidity-lsp.ts +9 -12
- package/plugins/sql-lsp.ts +9 -12
- package/plugins/svelte-lsp.ts +9 -12
- package/plugins/swift-lsp.ts +9 -12
- package/plugins/tailwindcss-lsp.ts +9 -12
- package/plugins/templ-lsp.ts +9 -12
- package/plugins/terraform-lsp.ts +9 -12
- package/plugins/theme_editor.i18n.json +182 -14
- package/plugins/theme_editor.ts +152 -208
- package/plugins/toml-lsp.ts +15 -22
- package/plugins/tsconfig.json +101 -0
- package/plugins/typescript-lsp.ts +15 -24
- package/plugins/typst-lsp.ts +15 -22
- package/plugins/vi_mode.ts +77 -290
- package/plugins/vue-lsp.ts +9 -12
- package/plugins/yaml-lsp.ts +15 -22
- package/plugins/zig-lsp.ts +9 -12
- package/themes/dark.json +2 -0
- package/themes/dracula.json +2 -0
- package/themes/high-contrast.json +2 -0
- package/themes/light.json +2 -0
- package/themes/nord.json +2 -0
- package/themes/nostalgia.json +2 -0
- package/themes/solarized-dark.json +2 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,123 @@
|
|
|
1
1
|
# Release Notes
|
|
2
2
|
|
|
3
|
+
## 0.3.2
|
|
4
|
+
|
|
5
|
+
### Features
|
|
6
|
+
|
|
7
|
+
* **Live Diff plugin** (experimental): Unified-diff overlay rendered live in the editable buffer. If your file is unmodified in the editor, it updates as the file changes on disk when auto-revert kicks in - great for watching an agent edit your file. Opt-in via `Live Diff: Toggle (Global)` / `Live Diff: Toggle (Buffer)`. Reference selectable per buffer: `vs HEAD` / `vs Disk` / `vs Branch...` / `vs Default Branch`.
|
|
8
|
+
|
|
9
|
+
* **New Startup section in Settings** (open Settings and search "Startup") groups everything that fires on launch:
|
|
10
|
+
- **Blank-workspace flow** (#1753) — *Auto Create Empty Buffer On Last Buffer Close* (Editor) and *Auto Open On Last Buffer Close* (File Explorer). With both off, closing the last buffer leaves a truly blank pane (no `[No Name]`, no gutter, no `~`); buffer-specific status-bar items and menu entries are suppressed, and a subdued centered hint shows the keys to escape (`Ctrl+P` / `Ctrl+O` / `Ctrl+E`).
|
|
11
|
+
- *Skip Session Restore When Files Passed* — `fresh src/main.rs` opens just that file; bare `fresh` and `fresh some/dir` still restore. Hot-exit recovery still runs. `--restore` overrides.
|
|
12
|
+
- *Restore Previous Session* (existing, moved into Startup).
|
|
13
|
+
|
|
14
|
+
* **File explorer side** (thanks @paveloparev!): *Side* under File Explorer in Settings — left or right.
|
|
15
|
+
|
|
16
|
+
* **Prompt Line now hidden by default**: *Show Prompt Line* now defaults off — the prompt line only appears while a prompt is active. Turn it back on via Settings.
|
|
17
|
+
|
|
18
|
+
* **Mark mode preserved through Go to Line** so you can extend selections across the jump. Use **Set Mark** command followed by **Goto Line** to start a selection and extend it to the target line.
|
|
19
|
+
|
|
20
|
+
* **Copy File Path commands**: New commands: "Copy File Path" and "Copy Relative File Path" to copy current buffer's path to your clipboard. Also available by right-clicking on a tab name.
|
|
21
|
+
|
|
22
|
+
* **CLI Help Localization**: The `--help` output is now fully localized using runtime i18n lookups.
|
|
23
|
+
|
|
24
|
+
* **Relative +/- Goto Line**: Infers absolute vs relative jumps from a leading sign (e.g., `:+10` jumps 10 lines down, `:10` jumps to line 10).
|
|
25
|
+
|
|
26
|
+
* **Rust Toolchain Update**: Updated to Rust 1.95 in `rust-toolchain.toml` to fix compatibility issues with newer LLVM/clang versions on systems like Arch Linux (#1782).
|
|
27
|
+
|
|
28
|
+
### Improvements
|
|
29
|
+
|
|
30
|
+
* **Plugin loading deferred off the boot critical path** — another ~225 ms saved. Same load order, same hooks, just async.
|
|
31
|
+
|
|
32
|
+
* **Popup focus**: LSP popups that auto-show on file open (status popup, hover, signature help, plugin Text overlays) no longer steal the next keystroke. They show unfocused with an `[Alt+T to focus]` hint; user-invoked popups (Completion, code actions, status-bar `{remote}`, LSP-status menu) still grab focus on show. Settings / Menu / Prompt modals take precedence over unfocused buffer popups for `Esc` / `popup_focus`.
|
|
33
|
+
|
|
34
|
+
* **Status Bar visual integration** (#1711): The "Palette: Ctrl+P" hint and "LSP (on)" indicator now blend into the status bar by default. Built-in themes have been updated with coherent prominent colors for these indicators.
|
|
35
|
+
|
|
36
|
+
* **Prompt interaction and scrolling** (#1660):
|
|
37
|
+
- Minimal scrolling: the suggestion list no longer recenters the selection on every move, preventing "row jumping" during navigation.
|
|
38
|
+
- Clicks no longer cause accidental list shifts; double-click correctly confirms selections.
|
|
39
|
+
- Preview-on-click supported for "Reload with encoding".
|
|
40
|
+
|
|
41
|
+
* **Global Menu Bar**: "Toggle Menu Bar" state is now persisted globally across all workspaces.
|
|
42
|
+
|
|
43
|
+
* **Windows integration**: High-quality app icon applied to the running window; app manifest and version info embedded in the binary.
|
|
44
|
+
|
|
45
|
+
### Bug Fixes
|
|
46
|
+
|
|
47
|
+
* **Windows subprocesses**: Transient console windows are now hidden when spawning subprocesses (e.g., formatters, linters).
|
|
48
|
+
|
|
49
|
+
* **Terminal CWD**: Fixed shell spawning failure on Windows when the current directory has a `\\?\` UNC prefix.
|
|
50
|
+
|
|
51
|
+
* **Live Diff stability**: Fixed crashes on surrogate-pair content (emojis) and corrected gutter rendering for empty lines inside added blocks.
|
|
52
|
+
|
|
53
|
+
### Under the Hood
|
|
54
|
+
|
|
55
|
+
* **Syntax Highlight Caching**: New multi-phase caching system (memoised scope lookups and whole-file cache for small files) significantly reduces CPU usage during rendering.
|
|
56
|
+
|
|
57
|
+
## 0.3.1
|
|
58
|
+
|
|
59
|
+
### Features
|
|
60
|
+
|
|
61
|
+
* **Animations framework**: tab-switch slide; cursor-jump trail animation. Disable it via Settings UI. Animations available to plugins via API.
|
|
62
|
+
|
|
63
|
+
* **Flash plugin** (label-jump, à la flash.nvim): bundled plugin — type a pattern, press the displayed label to jump, even across split panes.
|
|
64
|
+
|
|
65
|
+
* **Devcontainer fixes**: See below
|
|
66
|
+
|
|
67
|
+
### Improvements
|
|
68
|
+
|
|
69
|
+
* **Relative-numbers go-to negative** (thanks @paveloparev!): `g<-N>` jumps N lines up in relative-numbers mode.
|
|
70
|
+
|
|
71
|
+
* **Racket language support**: `.rkt` / `.rktd` / `.rktl` / `.scrbl` highlight out of the box; LSP via `racket-langserver`.
|
|
72
|
+
|
|
73
|
+
* **`{remote}` indicator default-on**: rendered on bottom-left for fresh installs (`F6` default keybinding, palette command).
|
|
74
|
+
|
|
75
|
+
* **Quick Open keybindings** (thanks @paveloparev!): `Ctrl+'` for files, `Ctrl+;` for buffers. Some terminals don't like passing these keys, you can rebind in the Keybinding UI (future version will probably change the default shortcuts to be more terminal-friendly across platforms).
|
|
76
|
+
|
|
77
|
+
* **Completion popup rebindable** (#1705): Allow modifying key bindings for the non-lsp completions popup.
|
|
78
|
+
|
|
79
|
+
* **Better scrolling** on markdown preview buffers and very-long-line buffers via a new two-tier line-wrap cache.
|
|
80
|
+
|
|
81
|
+
* **LSP**:
|
|
82
|
+
- Stuck request no longer blocks others (#1679): per-server handlers on independent tokio tasks + 30 s timeout. R `languageserver` 0.3.17 no longer wedges completion / signature help.
|
|
83
|
+
- Empty-server completion fallback to buffer-word completions.
|
|
84
|
+
- Failure-stub log so "View Log" works after a failed spawn.
|
|
85
|
+
|
|
86
|
+
* **Devcontainer** spec-conformance + UX:
|
|
87
|
+
- Lifecycle `cwd = remoteWorkspaceFolder`; object-form entries run in parallel and continue past failures; `remoteEnv` propagated; `shutdownAction: stopContainer` honoured on Detach; `userEnvProbe` captured and merged; `remoteUser` falls back per spec.
|
|
88
|
+
- Lifecycle stdout/stderr surface in the panel; `Show *` commands reuse a single panel; build log split reused not stacked; parse errors surface (and `Open Config` stays registered); `onAutoForward: notify` toasts; state-relevant commands gated by authority; no re-prompt after restart.
|
|
89
|
+
- **Devcontainer Goto-Definition across host / container**: LSP URIs translate at the boundary; container-only paths (e.g. `flask/app.py` under the venv) are fetched into a buffer.
|
|
90
|
+
|
|
91
|
+
* **File explorer preview** no longer loses focus to LSP popups in the editor pane.
|
|
92
|
+
|
|
93
|
+
* **Plugin types**: `tsconfig.json` for `tsc --noEmit` in CI; `editor.on(fn)` infers payload types from `HookEventMap`; `HookArgs` derives serde.
|
|
94
|
+
|
|
95
|
+
* **Conceal substitution** now emits the replacement glyph for whitespace tokens (Space / Newline / Break).
|
|
96
|
+
|
|
97
|
+
### Bug Fixes
|
|
98
|
+
|
|
99
|
+
* **`plugins/` folder in your project no longer hides bundled commands** (#1722): Fresh stops scanning the working directory for plugins.
|
|
100
|
+
|
|
101
|
+
* **Scroll & viewport**:
|
|
102
|
+
- Mouse-wheel / PageDown / scrollbar-drag now reach EOF on word-wrapped buffers, including compose-mode markdown ending in a table. Within-line scroll re-clamps; gutter calc unified.
|
|
103
|
+
- Search wrap-around Down-arrow stall: stale `scrolled_up_in_wrap` cleared on recenter.
|
|
104
|
+
|
|
105
|
+
* **Non-ASCII truncation panics** (#1715, #1718): settings search/preview/description/changelog, file-browser sort-arrow header, status-bar `truncate_path`, shell `truncate_command`, map-input value previews. Text search inside rows with multi-byte glyphs no longer panics either.
|
|
106
|
+
|
|
107
|
+
* **`setLayoutHints`** binds `compose_width` to the buffer, not whichever buffer is active.
|
|
108
|
+
|
|
109
|
+
### Under the Hood
|
|
110
|
+
|
|
111
|
+
* **Line-wrap cache** (`LineWrapCache` + tier-2 `VisualRowIndex`) becomes the single source of truth — `wrap_line` / `WrappedSegment` deleted; scroll math, cursor position, and scrollbar thumb share one pipeline.
|
|
112
|
+
|
|
113
|
+
* **Marker-tree `remove_in_range`** for `SoftBreakManager` / `ConcealManager` / `OverlayManager`: O(log N + k), proptest invariants.
|
|
114
|
+
|
|
115
|
+
* **`LspUri` newtype** enforces host / container URI translation at the type level.
|
|
116
|
+
|
|
117
|
+
* **Refactors**: `handle_mouse_click` (764 lines) → 14 helpers; `real_main` decomposed; `plugin_dispatch` match arms extracted; `quickjs_backend` ID-allocation boilerplate collapsed; `FromJs` impls into a macro; mouse multi-click + scroll dispatch deduped.
|
|
118
|
+
|
|
119
|
+
* **Test infrastructure**: fake `devcontainer` / `docker` / `pylsp` CLIs drive e2es without real binaries; plugin fixtures load from `<config_dir>/plugins/` instead of the cwd; animations default off in tests.
|
|
120
|
+
|
|
3
121
|
## 0.3.0
|
|
4
122
|
|
|
5
123
|
This version brings major features and many quality-of-life improvements and bug fixes:
|
|
@@ -27,8 +145,8 @@ And more (see below). A large version is more likely to contain regression bugs,
|
|
|
27
145
|
- Build log streams into a workspace split; failed attaches offer Retry / Show Logs / Detach via a recovery popup.
|
|
28
146
|
- `initializeCommand` runs on attach.
|
|
29
147
|
|
|
30
|
-
* **`init.ts`**: Fresh now auto-loads `~/.config/fresh/init.ts`! Allows you to run plugin code on startup, which complements the purely declarative config system with imperative, environment-aware logic. Use command palette `init: Edit` to generate a template with some examples. Use `init: Reload` to run it after editing. Use `--no-init` / `--safe` to skip loading.
|
|
31
|
-
- Tip: *Enable LSP* when editing `init.ts` to get help and completions.
|
|
148
|
+
* **`init.ts`**: Fresh now auto-loads `~/.config/fresh/init.ts`! Allows you to run plugin code on startup, which complements the purely declarative config system with imperative, environment-aware logic. Use command palette `init: Edit` to generate a template with some examples. Use `init: Reload` to run it after editing. Use `--no-init` / `--safe` to skip loading.
|
|
149
|
+
- Tip: *Enable LSP* when editing `init.ts` to get help and completions.
|
|
32
150
|
- Example (for the Dashboard plugin):
|
|
33
151
|
```typescript
|
|
34
152
|
// in your init.ts file:
|
package/package.json
CHANGED
package/plugins/astro-lsp.ts
CHANGED
|
@@ -35,7 +35,7 @@ const INSTALL_COMMANDS = {
|
|
|
35
35
|
|
|
36
36
|
let astroLspError: { serverCommand: string; message: string } | null = null;
|
|
37
37
|
|
|
38
|
-
|
|
38
|
+
editor.on("lsp_server_error", (data) => {
|
|
39
39
|
if (data.language !== "astro") {
|
|
40
40
|
return;
|
|
41
41
|
}
|
|
@@ -54,11 +54,9 @@ function on_astro_lsp_server_error(data: LspServerErrorData): void {
|
|
|
54
54
|
} else {
|
|
55
55
|
editor.setStatus(`Astro LSP error: ${data.message}`);
|
|
56
56
|
}
|
|
57
|
-
}
|
|
58
|
-
registerHandler("on_astro_lsp_server_error", on_astro_lsp_server_error);
|
|
59
|
-
editor.on("lsp_server_error", "on_astro_lsp_server_error");
|
|
57
|
+
});
|
|
60
58
|
|
|
61
|
-
|
|
59
|
+
editor.on("lsp_status_clicked", (data) => {
|
|
62
60
|
if (data.language !== "astro" || !astroLspError) {
|
|
63
61
|
return;
|
|
64
62
|
}
|
|
@@ -76,11 +74,9 @@ function on_astro_lsp_status_clicked(data: LspStatusClickedData): void {
|
|
|
76
74
|
{ id: "dismiss", label: "Dismiss (ESC)" },
|
|
77
75
|
],
|
|
78
76
|
});
|
|
79
|
-
}
|
|
80
|
-
registerHandler("on_astro_lsp_status_clicked", on_astro_lsp_status_clicked);
|
|
81
|
-
editor.on("lsp_status_clicked", "on_astro_lsp_status_clicked");
|
|
77
|
+
});
|
|
82
78
|
|
|
83
|
-
|
|
79
|
+
editor.on("action_popup_result", (data) => {
|
|
84
80
|
if (data.popup_id !== "astro-lsp-help") {
|
|
85
81
|
return;
|
|
86
82
|
}
|
|
@@ -111,8 +107,6 @@ function on_astro_lsp_action_result(data: ActionPopupResultData): void {
|
|
|
111
107
|
default:
|
|
112
108
|
editor.debug(`astro-lsp: Unknown action: ${data.action_id}`);
|
|
113
109
|
}
|
|
114
|
-
}
|
|
115
|
-
registerHandler("on_astro_lsp_action_result", on_astro_lsp_action_result);
|
|
116
|
-
editor.on("action_popup_result", "on_astro_lsp_action_result");
|
|
110
|
+
});
|
|
117
111
|
|
|
118
112
|
editor.debug("astro-lsp: Plugin loaded");
|
package/plugins/audit_mode.ts
CHANGED
|
@@ -54,6 +54,7 @@ interface Hunk {
|
|
|
54
54
|
oldRange: { start: number; end: number }; // old file line range
|
|
55
55
|
type: 'add' | 'remove' | 'modify';
|
|
56
56
|
lines: string[];
|
|
57
|
+
status?: string;
|
|
57
58
|
contextHeader: string;
|
|
58
59
|
byteOffset: number; // Position in the virtual buffer
|
|
59
60
|
gitStatus?: 'staged' | 'unstaged' | 'untracked';
|
|
@@ -2462,48 +2463,9 @@ function review_discard_file() {
|
|
|
2462
2463
|
}
|
|
2463
2464
|
registerHandler("review_discard_file", review_discard_file);
|
|
2464
2465
|
|
|
2465
|
-
async function on_review_discard_hunk_confirm(args: { prompt_type: string; input: string; selected_index: number | null }): Promise<boolean> {
|
|
2466
|
-
if (args.prompt_type !== "review-discard-hunk-confirm") return true;
|
|
2467
|
-
const response = args.input.trim().toLowerCase();
|
|
2468
|
-
if (response === "discard" || args.selected_index === 0) {
|
|
2469
|
-
const hunk = getHunkAtDiffCursor();
|
|
2470
|
-
if (hunk && hunk.file) {
|
|
2471
|
-
const patch = buildHunkPatch(hunk.file, hunk);
|
|
2472
|
-
const ok = await applyHunkPatch(patch, ["--reverse"]);
|
|
2473
|
-
if (ok) {
|
|
2474
|
-
editor.setStatus(editor.t("status.hunk_discarded") || "Hunk discarded");
|
|
2475
|
-
await refreshMagitData();
|
|
2476
|
-
}
|
|
2477
|
-
}
|
|
2478
|
-
} else {
|
|
2479
|
-
editor.setStatus("Discard cancelled");
|
|
2480
|
-
}
|
|
2481
|
-
return false;
|
|
2482
|
-
}
|
|
2483
|
-
registerHandler("on_review_discard_hunk_confirm", on_review_discard_hunk_confirm);
|
|
2484
2466
|
|
|
2485
|
-
async function on_review_discard_confirm(args: { prompt_type: string; input: string; selected_index: number | null }): Promise<boolean> {
|
|
2486
|
-
if (args.prompt_type !== "review-discard-confirm") return true;
|
|
2487
2467
|
|
|
2488
|
-
|
|
2489
|
-
if (response === "discard" || args.selected_index === 0) {
|
|
2490
|
-
const f = pendingDiscardFile;
|
|
2491
|
-
if (f) {
|
|
2492
|
-
if (f.category === 'untracked') {
|
|
2493
|
-
await editor.spawnProcess("rm", ["--", f.path]);
|
|
2494
|
-
} else {
|
|
2495
|
-
await editor.spawnProcess("git", ["checkout", "--", f.path]);
|
|
2496
|
-
}
|
|
2497
|
-
await refreshMagitData();
|
|
2498
|
-
editor.setStatus(`Discarded: ${f.path}`);
|
|
2499
|
-
}
|
|
2500
|
-
} else {
|
|
2501
|
-
editor.setStatus("Discard cancelled");
|
|
2502
|
-
}
|
|
2503
|
-
pendingDiscardFile = null;
|
|
2504
|
-
return false;
|
|
2505
|
-
}
|
|
2506
|
-
registerHandler("on_review_discard_confirm", on_review_discard_confirm);
|
|
2468
|
+
|
|
2507
2469
|
|
|
2508
2470
|
/**
|
|
2509
2471
|
* Refresh file list and diffs using the new git status approach, then re-render.
|
|
@@ -3456,28 +3418,15 @@ async function review_delete_comment() {
|
|
|
3456
3418
|
}
|
|
3457
3419
|
registerHandler("review_delete_comment", review_delete_comment);
|
|
3458
3420
|
|
|
3459
|
-
|
|
3460
|
-
if (args.prompt_type !== "review-delete-comment-confirm") return true;
|
|
3461
|
-
const response = args.input.trim().toLowerCase();
|
|
3462
|
-
if ((response === "delete" || args.selected_index === 0) && pendingDeleteCommentId) {
|
|
3463
|
-
if (pendingDeleteCommentId === '__note__') {
|
|
3464
|
-
state.note = '';
|
|
3465
|
-
} else {
|
|
3466
|
-
state.comments = state.comments.filter(c => c.id !== pendingDeleteCommentId);
|
|
3467
|
-
}
|
|
3468
|
-
persistReview();
|
|
3469
|
-
updateMagitDisplay();
|
|
3470
|
-
editor.setStatus("Deleted");
|
|
3471
|
-
} else {
|
|
3472
|
-
editor.setStatus("Delete cancelled");
|
|
3473
|
-
}
|
|
3474
|
-
pendingDeleteCommentId = null;
|
|
3475
|
-
return false;
|
|
3476
|
-
}
|
|
3477
|
-
registerHandler("on_review_delete_comment_confirm", on_review_delete_comment_confirm);
|
|
3421
|
+
|
|
3478
3422
|
|
|
3479
3423
|
// Prompt event handlers
|
|
3480
|
-
|
|
3424
|
+
|
|
3425
|
+
|
|
3426
|
+
|
|
3427
|
+
|
|
3428
|
+
// Register prompt event handlers
|
|
3429
|
+
editor.on("prompt_confirmed", (args) => {
|
|
3481
3430
|
if (args.prompt_type !== "review-comment") {
|
|
3482
3431
|
return true;
|
|
3483
3432
|
}
|
|
@@ -3540,38 +3489,47 @@ function on_review_prompt_confirm(args: { prompt_type: string; input: string }):
|
|
|
3540
3489
|
}
|
|
3541
3490
|
pendingCommentInfo = null;
|
|
3542
3491
|
return true;
|
|
3543
|
-
}
|
|
3544
|
-
|
|
3492
|
+
});
|
|
3493
|
+
editor.on("prompt_confirmed", async (args) => {
|
|
3494
|
+
if (args.prompt_type !== "review-discard-confirm") return true;
|
|
3545
3495
|
|
|
3546
|
-
|
|
3547
|
-
if (args.
|
|
3548
|
-
|
|
3549
|
-
|
|
3550
|
-
|
|
3496
|
+
const response = args.input.trim().toLowerCase();
|
|
3497
|
+
if (response === "discard" || args.selected_index === 0) {
|
|
3498
|
+
const f = pendingDiscardFile;
|
|
3499
|
+
if (f) {
|
|
3500
|
+
if (f.category === 'untracked') {
|
|
3501
|
+
await editor.spawnProcess("rm", ["--", f.path]);
|
|
3502
|
+
} else {
|
|
3503
|
+
await editor.spawnProcess("git", ["checkout", "--", f.path]);
|
|
3504
|
+
}
|
|
3505
|
+
await refreshMagitData();
|
|
3506
|
+
editor.setStatus(`Discarded: ${f.path}`);
|
|
3507
|
+
}
|
|
3508
|
+
} else {
|
|
3509
|
+
editor.setStatus("Discard cancelled");
|
|
3551
3510
|
}
|
|
3552
|
-
|
|
3553
|
-
|
|
3554
|
-
|
|
3555
|
-
|
|
3556
|
-
|
|
3557
|
-
|
|
3558
|
-
|
|
3559
|
-
|
|
3560
|
-
|
|
3561
|
-
|
|
3562
|
-
|
|
3563
|
-
|
|
3564
|
-
|
|
3565
|
-
|
|
3566
|
-
|
|
3567
|
-
|
|
3511
|
+
pendingDiscardFile = null;
|
|
3512
|
+
return false;
|
|
3513
|
+
});
|
|
3514
|
+
editor.on("prompt_confirmed", async (args) => {
|
|
3515
|
+
if (args.prompt_type !== "review-discard-hunk-confirm") return true;
|
|
3516
|
+
const response = args.input.trim().toLowerCase();
|
|
3517
|
+
if (response === "discard" || args.selected_index === 0) {
|
|
3518
|
+
const hunk = getHunkAtDiffCursor();
|
|
3519
|
+
if (hunk && hunk.file) {
|
|
3520
|
+
const patch = buildHunkPatch(hunk.file, hunk);
|
|
3521
|
+
const ok = await applyHunkPatch(patch, ["--reverse"]);
|
|
3522
|
+
if (ok) {
|
|
3523
|
+
editor.setStatus(editor.t("status.hunk_discarded") || "Hunk discarded");
|
|
3524
|
+
await refreshMagitData();
|
|
3525
|
+
}
|
|
3526
|
+
}
|
|
3568
3527
|
} else {
|
|
3569
|
-
editor.
|
|
3528
|
+
editor.setStatus("Discard cancelled");
|
|
3570
3529
|
}
|
|
3571
|
-
|
|
3572
|
-
|
|
3573
|
-
|
|
3574
|
-
function on_review_edit_note_confirm(args: { prompt_type: string; input: string }): boolean {
|
|
3530
|
+
return false;
|
|
3531
|
+
});
|
|
3532
|
+
editor.on("prompt_confirmed", (args) => {
|
|
3575
3533
|
if (args.prompt_type !== "review-edit-note") return true;
|
|
3576
3534
|
if (args.input && args.input.trim()) {
|
|
3577
3535
|
state.note = args.input.trim();
|
|
@@ -3585,8 +3543,45 @@ function on_review_edit_note_confirm(args: { prompt_type: string; input: string
|
|
|
3585
3543
|
}
|
|
3586
3544
|
}
|
|
3587
3545
|
return true;
|
|
3546
|
+
});
|
|
3547
|
+
editor.on("prompt_confirmed", (args) => {
|
|
3548
|
+
if (args.prompt_type !== "review-delete-comment-confirm") return true;
|
|
3549
|
+
const response = args.input.trim().toLowerCase();
|
|
3550
|
+
if ((response === "delete" || args.selected_index === 0) && pendingDeleteCommentId) {
|
|
3551
|
+
if (pendingDeleteCommentId === '__note__') {
|
|
3552
|
+
state.note = '';
|
|
3553
|
+
} else {
|
|
3554
|
+
state.comments = state.comments.filter(c => c.id !== pendingDeleteCommentId);
|
|
3555
|
+
}
|
|
3556
|
+
persistReview();
|
|
3557
|
+
updateMagitDisplay();
|
|
3558
|
+
editor.setStatus("Deleted");
|
|
3559
|
+
} else {
|
|
3560
|
+
editor.setStatus("Delete cancelled");
|
|
3561
|
+
}
|
|
3562
|
+
pendingDeleteCommentId = null;
|
|
3563
|
+
return false;
|
|
3564
|
+
});
|
|
3565
|
+
editor.on("prompt_cancelled", (args) => {
|
|
3566
|
+
if (args.prompt_type === "review-comment") {
|
|
3567
|
+
pendingCommentInfo = null;
|
|
3568
|
+
editingCommentId = null;
|
|
3569
|
+
editor.setStatus(editor.t("status.comment_cancelled"));
|
|
3570
|
+
}
|
|
3571
|
+
return true;
|
|
3572
|
+
});
|
|
3573
|
+
|
|
3574
|
+
async function review_edit_note() {
|
|
3575
|
+
const label = editor.t("prompt.overall_comment") || "Note: ";
|
|
3576
|
+
if (state.note) {
|
|
3577
|
+
editor.startPromptWithInitial(label, "review-edit-note", state.note);
|
|
3578
|
+
} else {
|
|
3579
|
+
editor.startPrompt(label, "review-edit-note");
|
|
3580
|
+
}
|
|
3588
3581
|
}
|
|
3589
|
-
registerHandler("
|
|
3582
|
+
registerHandler("review_edit_note", review_edit_note);
|
|
3583
|
+
|
|
3584
|
+
|
|
3590
3585
|
|
|
3591
3586
|
async function review_export_session() {
|
|
3592
3587
|
const cwd = editor.getCwd();
|
|
@@ -3736,15 +3731,15 @@ async function openReviewPanels(groupName: string): Promise<boolean> {
|
|
|
3736
3731
|
|
|
3737
3732
|
updateMagitDisplay();
|
|
3738
3733
|
|
|
3739
|
-
editor.focusBufferGroupPanel(state.groupId
|
|
3734
|
+
editor.focusBufferGroupPanel(state.groupId!, "diff");
|
|
3740
3735
|
|
|
3741
|
-
editor.on("resize",
|
|
3736
|
+
editor.on("resize", onReviewDiffResize);
|
|
3742
3737
|
updateReviewStatus();
|
|
3743
|
-
editor.on("buffer_activated",
|
|
3744
|
-
editor.on("buffer_closed",
|
|
3745
|
-
editor.on("cursor_moved",
|
|
3746
|
-
editor.on("viewport_changed",
|
|
3747
|
-
editor.on("mouse_click",
|
|
3738
|
+
editor.on("buffer_activated", on_review_buffer_activated);
|
|
3739
|
+
editor.on("buffer_closed", on_review_buffer_closed);
|
|
3740
|
+
editor.on("cursor_moved", on_review_cursor_moved);
|
|
3741
|
+
editor.on("viewport_changed", on_review_viewport_changed);
|
|
3742
|
+
editor.on("mouse_click", on_review_mouse_click);
|
|
3748
3743
|
return true;
|
|
3749
3744
|
}
|
|
3750
3745
|
|
|
@@ -3820,12 +3815,12 @@ function stop_review_diff() {
|
|
|
3820
3815
|
}
|
|
3821
3816
|
state.reviewBufferId = null;
|
|
3822
3817
|
editor.setContext("review-mode", false);
|
|
3823
|
-
editor.off("resize",
|
|
3824
|
-
editor.off("buffer_activated",
|
|
3825
|
-
editor.off("buffer_closed",
|
|
3826
|
-
editor.off("cursor_moved",
|
|
3827
|
-
editor.off("viewport_changed",
|
|
3828
|
-
editor.off("mouse_click",
|
|
3818
|
+
editor.off("resize", onReviewDiffResize);
|
|
3819
|
+
editor.off("buffer_activated", on_review_buffer_activated);
|
|
3820
|
+
editor.off("buffer_closed", on_review_buffer_closed);
|
|
3821
|
+
editor.off("cursor_moved", on_review_cursor_moved);
|
|
3822
|
+
editor.off("viewport_changed", on_review_viewport_changed);
|
|
3823
|
+
editor.off("mouse_click", on_review_mouse_click);
|
|
3829
3824
|
editor.setStatus(editor.t("status.stopped"));
|
|
3830
3825
|
}
|
|
3831
3826
|
registerHandler("stop_review_diff", stop_review_diff);
|
|
@@ -3968,7 +3963,8 @@ async function start_review_range(): Promise<void> {
|
|
|
3968
3963
|
}
|
|
3969
3964
|
registerHandler("start_review_range", start_review_range);
|
|
3970
3965
|
|
|
3971
|
-
|
|
3966
|
+
|
|
3967
|
+
editor.on("prompt_confirmed", (args) => {
|
|
3972
3968
|
if (args.prompt_type !== "review-range") return true;
|
|
3973
3969
|
const range = parseRangeInput(args.input);
|
|
3974
3970
|
if (!range) {
|
|
@@ -3979,9 +3975,7 @@ function on_review_range_confirm(args: { prompt_type: string; input: string }):
|
|
|
3979
3975
|
// can return immediately.
|
|
3980
3976
|
bootstrapRangeReview(range);
|
|
3981
3977
|
return true;
|
|
3982
|
-
}
|
|
3983
|
-
registerHandler("on_review_range_confirm", on_review_range_confirm);
|
|
3984
|
-
editor.on("prompt_confirmed", "on_review_range_confirm");
|
|
3978
|
+
});
|
|
3985
3979
|
|
|
3986
3980
|
async function bootstrapRangeReview(range: ReviewRange): Promise<void> {
|
|
3987
3981
|
editor.setStatus(editor.t("status.generating") || "Generating diff…");
|
|
@@ -4607,7 +4601,7 @@ async function start_review_branch(): Promise<void> {
|
|
|
4607
4601
|
if (branchState.groupId !== null) {
|
|
4608
4602
|
editor.focusBufferGroupPanel(branchState.groupId, "log");
|
|
4609
4603
|
}
|
|
4610
|
-
editor.on("cursor_moved",
|
|
4604
|
+
editor.on("cursor_moved", on_review_branch_cursor_moved);
|
|
4611
4605
|
|
|
4612
4606
|
editor.setStatus(
|
|
4613
4607
|
editor.t("status.review_branch_ready", {
|
|
@@ -4621,7 +4615,7 @@ registerHandler("start_review_branch", start_review_branch);
|
|
|
4621
4615
|
function stop_review_branch(): void {
|
|
4622
4616
|
if (!branchState.isOpen) return;
|
|
4623
4617
|
if (branchState.groupId !== null) editor.closeBufferGroup(branchState.groupId);
|
|
4624
|
-
editor.off("cursor_moved",
|
|
4618
|
+
editor.off("cursor_moved", on_review_branch_cursor_moved);
|
|
4625
4619
|
branchState.isOpen = false;
|
|
4626
4620
|
branchState.groupId = null;
|
|
4627
4621
|
branchState.logBufferId = null;
|
|
@@ -4717,7 +4711,9 @@ editor.registerCommand("%cmd.export_markdown", "%cmd.export_markdown_desc", "rev
|
|
|
4717
4711
|
editor.registerCommand("%cmd.export_json", "%cmd.export_json_desc", "review_export_json", "review-mode");
|
|
4718
4712
|
|
|
4719
4713
|
// Handler for when buffers are closed - cleans up scroll sync groups and composite buffers
|
|
4720
|
-
|
|
4714
|
+
|
|
4715
|
+
|
|
4716
|
+
editor.on("buffer_closed", (data) => {
|
|
4721
4717
|
// If one of the diff view buffers is closed, clean up the scroll sync group
|
|
4722
4718
|
if (activeSideBySideState) {
|
|
4723
4719
|
if (data.buffer_id === activeSideBySideState.oldBufferId ||
|
|
@@ -4744,10 +4740,7 @@ function on_buffer_closed(data: any) {
|
|
|
4744
4740
|
activeCompositeDiffState = null;
|
|
4745
4741
|
}
|
|
4746
4742
|
}
|
|
4747
|
-
}
|
|
4748
|
-
registerHandler("on_buffer_closed", on_buffer_closed);
|
|
4749
|
-
|
|
4750
|
-
editor.on("buffer_closed", "on_buffer_closed");
|
|
4743
|
+
});
|
|
4751
4744
|
|
|
4752
4745
|
editor.defineMode("review-mode", [
|
|
4753
4746
|
// Native cursor motion in the unified diff stream.
|
package/plugins/bash-lsp.ts
CHANGED
|
@@ -49,7 +49,10 @@ let bashLspError: { serverCommand: string; message: string } | null = null;
|
|
|
49
49
|
/**
|
|
50
50
|
* Handle LSP server errors for Bash
|
|
51
51
|
*/
|
|
52
|
-
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
// Register hook for LSP server errors
|
|
55
|
+
editor.on("lsp_server_error", (data) => {
|
|
53
56
|
// Only handle Bash language errors
|
|
54
57
|
if (data.language !== "bash") {
|
|
55
58
|
return;
|
|
@@ -71,18 +74,15 @@ function on_bash_lsp_server_error(data: LspServerErrorData): void {
|
|
|
71
74
|
} else {
|
|
72
75
|
editor.setStatus(`Bash LSP error: ${data.message}`);
|
|
73
76
|
}
|
|
74
|
-
}
|
|
75
|
-
registerHandler("on_bash_lsp_server_error", on_bash_lsp_server_error);
|
|
76
|
-
|
|
77
|
-
// Register hook for LSP server errors
|
|
78
|
-
editor.on("lsp_server_error", "on_bash_lsp_server_error");
|
|
77
|
+
});
|
|
79
78
|
|
|
80
79
|
/**
|
|
81
80
|
* Handle status bar click when there's a Bash LSP error
|
|
82
81
|
*/
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
// Register hook for status bar clicks
|
|
85
|
+
editor.on("lsp_status_clicked", (data) => {
|
|
86
86
|
// Only handle Bash language clicks when there's an error
|
|
87
87
|
if (data.language !== "bash" || !bashLspError) {
|
|
88
88
|
return;
|
|
@@ -103,18 +103,15 @@ function on_bash_lsp_status_clicked(
|
|
|
103
103
|
{ id: "dismiss", label: "Dismiss (ESC)" },
|
|
104
104
|
],
|
|
105
105
|
});
|
|
106
|
-
}
|
|
107
|
-
registerHandler("on_bash_lsp_status_clicked", on_bash_lsp_status_clicked);
|
|
108
|
-
|
|
109
|
-
// Register hook for status bar clicks
|
|
110
|
-
editor.on("lsp_status_clicked", "on_bash_lsp_status_clicked");
|
|
106
|
+
});
|
|
111
107
|
|
|
112
108
|
/**
|
|
113
109
|
* Handle action popup results for Bash LSP help
|
|
114
110
|
*/
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
// Register hook for action popup results
|
|
114
|
+
editor.on("action_popup_result", (data) => {
|
|
118
115
|
// Only handle our popup
|
|
119
116
|
if (data.popup_id !== "bash-lsp-help") {
|
|
120
117
|
return;
|
|
@@ -152,10 +149,6 @@ function on_bash_lsp_action_result(
|
|
|
152
149
|
default:
|
|
153
150
|
editor.debug(`bash-lsp: Unknown action: ${data.action_id}`);
|
|
154
151
|
}
|
|
155
|
-
}
|
|
156
|
-
registerHandler("on_bash_lsp_action_result", on_bash_lsp_action_result);
|
|
157
|
-
|
|
158
|
-
// Register hook for action popup results
|
|
159
|
-
editor.on("action_popup_result", "on_bash_lsp_action_result");
|
|
152
|
+
});
|
|
160
153
|
|
|
161
154
|
editor.debug("bash-lsp: Plugin loaded");
|
package/plugins/clangd-lsp.ts
CHANGED
|
@@ -54,9 +54,10 @@ let clangdLspError: {
|
|
|
54
54
|
/**
|
|
55
55
|
* Handle LSP server errors for C/C++
|
|
56
56
|
*/
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
// Register hook for LSP server errors
|
|
60
|
+
editor.on("lsp_server_error", (data) => {
|
|
60
61
|
// Only handle C/C++ language errors
|
|
61
62
|
if (!HANDLED_LANGUAGES.includes(data.language)) {
|
|
62
63
|
return;
|
|
@@ -79,18 +80,15 @@ function on_clangd_lsp_server_error(
|
|
|
79
80
|
} else {
|
|
80
81
|
editor.setStatus(`C/C++ LSP error: ${data.message}`);
|
|
81
82
|
}
|
|
82
|
-
}
|
|
83
|
-
registerHandler("on_clangd_lsp_server_error", on_clangd_lsp_server_error);
|
|
84
|
-
|
|
85
|
-
// Register hook for LSP server errors
|
|
86
|
-
editor.on("lsp_server_error", "on_clangd_lsp_server_error");
|
|
83
|
+
});
|
|
87
84
|
|
|
88
85
|
/**
|
|
89
86
|
* Handle status bar click when there's a C/C++ LSP error
|
|
90
87
|
*/
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
// Register hook for status bar clicks
|
|
91
|
+
editor.on("lsp_status_clicked", (data) => {
|
|
94
92
|
// Only handle C/C++ language clicks when there's an error
|
|
95
93
|
if (!HANDLED_LANGUAGES.includes(data.language) || !clangdLspError) {
|
|
96
94
|
return;
|
|
@@ -111,18 +109,15 @@ function on_clangd_lsp_status_clicked(
|
|
|
111
109
|
{ id: "dismiss", label: "Dismiss (ESC)" },
|
|
112
110
|
],
|
|
113
111
|
});
|
|
114
|
-
}
|
|
115
|
-
registerHandler("on_clangd_lsp_status_clicked", on_clangd_lsp_status_clicked);
|
|
116
|
-
|
|
117
|
-
// Register hook for status bar clicks
|
|
118
|
-
editor.on("lsp_status_clicked", "on_clangd_lsp_status_clicked");
|
|
112
|
+
});
|
|
119
113
|
|
|
120
114
|
/**
|
|
121
115
|
* Handle action popup results for C/C++ LSP help
|
|
122
116
|
*/
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
// Register hook for action popup results
|
|
120
|
+
editor.on("action_popup_result", (data) => {
|
|
126
121
|
// Only handle our popup
|
|
127
122
|
if (data.popup_id !== "clangd-lsp-help") {
|
|
128
123
|
return;
|
|
@@ -162,10 +157,6 @@ function on_clangd_lsp_action_result(
|
|
|
162
157
|
default:
|
|
163
158
|
editor.debug(`clangd-lsp: Unknown action: ${data.action_id}`);
|
|
164
159
|
}
|
|
165
|
-
}
|
|
166
|
-
registerHandler("on_clangd_lsp_action_result", on_clangd_lsp_action_result);
|
|
167
|
-
|
|
168
|
-
// Register hook for action popup results
|
|
169
|
-
editor.on("action_popup_result", "on_clangd_lsp_action_result");
|
|
160
|
+
});
|
|
170
161
|
|
|
171
162
|
editor.debug("clangd-lsp: Plugin loaded");
|