@fresh-editor/fresh-editor 0.2.12 → 0.2.13
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 +60 -0
- package/README.md +10 -0
- package/package.json +1 -1
- package/plugins/audit_mode.ts +79 -58
- package/plugins/check-types.sh +1 -0
- package/plugins/clangd-lsp.ts +9 -6
- package/plugins/clangd_support.ts +12 -8
- package/plugins/code-tour.ts +15 -10
- package/plugins/config-schema.json +40 -3
- package/plugins/csharp_support.ts +15 -10
- package/plugins/css-lsp.ts +9 -6
- package/plugins/diagnostics_panel.ts +25 -18
- package/plugins/examples/README.md +1 -2
- package/plugins/examples/async_demo.ts +28 -28
- package/plugins/examples/bookmarks.ts +34 -32
- package/plugins/examples/buffer_query_demo.ts +20 -20
- package/plugins/examples/hello_world.ts +46 -10
- package/plugins/examples/virtual_buffer_demo.ts +16 -12
- package/plugins/find_references.ts +7 -5
- package/plugins/git_blame.ts +13 -9
- package/plugins/git_explorer.ts +9 -6
- package/plugins/git_find_file.ts +7 -5
- package/plugins/git_grep.ts +3 -2
- package/plugins/git_gutter.ts +15 -10
- package/plugins/git_log.ts +27 -18
- package/plugins/go-lsp.ts +9 -6
- package/plugins/html-lsp.ts +9 -6
- package/plugins/java-lsp.ts +9 -6
- package/plugins/json-lsp.ts +9 -6
- package/plugins/latex-lsp.ts +9 -6
- package/plugins/lib/finder.ts +1 -0
- package/plugins/lib/fresh.d.ts +139 -14
- package/plugins/live_grep.ts +3 -2
- package/plugins/markdown_compose.ts +33 -23
- package/plugins/markdown_source.ts +15 -10
- package/plugins/marksman-lsp.ts +9 -6
- package/plugins/merge_conflict.ts +33 -22
- package/plugins/odin-lsp.ts +9 -6
- package/plugins/path_complete.ts +3 -2
- package/plugins/pkg.ts +70 -48
- package/plugins/python-lsp.ts +9 -6
- package/plugins/rust-lsp.ts +102 -6
- package/plugins/search_replace.ts +32 -21
- package/plugins/templ-lsp.ts +9 -6
- package/plugins/test_i18n.ts +3 -2
- package/plugins/theme_editor.i18n.json +28 -14
- package/plugins/theme_editor.ts +1230 -495
- package/plugins/typescript-lsp.ts +9 -6
- package/plugins/vi_mode.ts +487 -297
- package/plugins/welcome.ts +9 -6
- package/plugins/zig-lsp.ts +9 -6
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,65 @@
|
|
|
1
1
|
# Release Notes
|
|
2
2
|
|
|
3
|
+
## 0.2.13
|
|
4
|
+
|
|
5
|
+
### Features
|
|
6
|
+
|
|
7
|
+
* **Inline Diagnostics**: Diagnostic text displayed at end of lines, right-aligned, with version-aware staleness dropping. Disabled by default — enable "diagnostics inline text" in the Settings UI (#1175).
|
|
8
|
+
|
|
9
|
+
* **Hanging Line Wrap**: Wrapped continuation lines preserve the indentation of their parent logical line (#1169).
|
|
10
|
+
|
|
11
|
+
* **Theme Editor Redesign**: Virtual scrolling, mouse support, flicker-free inline styling. New "Inspect Theme at Cursor" command and Ctrl+Right-Click theme info popup.
|
|
12
|
+
|
|
13
|
+
* **Open File Jump**: `path:line[:col]` syntax in Open File prompt and Quick Open (#1081, #1149).
|
|
14
|
+
|
|
15
|
+
### Improvements
|
|
16
|
+
|
|
17
|
+
* **Plugin API**: `registerHandler()` replacing `globalThis` pattern, `restartLspForLanguage`, process-limits for `registerLspServer`, async `reloadGrammars()`. Strict TypeScript across all plugins.
|
|
18
|
+
|
|
19
|
+
* **Load Plugin from Buffer**: Run and hot-reload plugins directly from an open buffer, with LSP support for plugin dev buffers.
|
|
20
|
+
|
|
21
|
+
* **Status Bar Toggle**: Command palette command and config option to show/hide the status bar.
|
|
22
|
+
|
|
23
|
+
* **LSP Environment Variables**: Pass environment variables to LSP server binaries via config (#1159).
|
|
24
|
+
|
|
25
|
+
* **LSP Language ID Overrides**: Configurable `language_id_overrides` in LSP server config.
|
|
26
|
+
|
|
27
|
+
* **Rust LSP Mode Switching**: Command palette action to switch between Full and Reduced Memory modes for rust-analyzer.
|
|
28
|
+
|
|
29
|
+
* **Signature Help Rendering**: Markdown rendering for signature help popups with hanging indent and paragraph spacing.
|
|
30
|
+
|
|
31
|
+
* **Non-Blocking Grammar Builds**: `SyntaxSet::build()` moved to a background thread. Buffered input events drained before render for CPU-constrained responsiveness.
|
|
32
|
+
|
|
33
|
+
* Disabled LSP start/restart commands for languages without LSP config (#1168).
|
|
34
|
+
|
|
35
|
+
### Bug Fixes
|
|
36
|
+
|
|
37
|
+
* **LSP Bracket Paths**: Fixed LSP failing for file paths containing `[` or `]` (#953).
|
|
38
|
+
|
|
39
|
+
* **Search F3 Navigation**: Fixed F3 losing matches after viewport scroll (#1155).
|
|
40
|
+
|
|
41
|
+
* **Settings JSON Copy**: Fixed Ctrl+C not working in settings JSON editor (#1159).
|
|
42
|
+
|
|
43
|
+
* **Line Numbers on New Files**: Fixed line numbers showing when disabled in settings for newly opened files (#1181).
|
|
44
|
+
|
|
45
|
+
* **Client/Server Paste**: Fixed bracketed paste mode and terminal feature parity in client/server sessions (#1168).
|
|
46
|
+
|
|
47
|
+
* **Popup Selection**: Fixed popup text selection copying wrong text when lines wrap (#1170).
|
|
48
|
+
|
|
49
|
+
* **Suggestions Popup Border**: Fixed bottom border overwritten by status bar (#1174).
|
|
50
|
+
|
|
51
|
+
* **TSX/JSX Language ID**: Fixed wrong `languageId` sent to LSP for TSX/JSX files (#1174).
|
|
52
|
+
|
|
53
|
+
* **LSP Error Suppression**: Suppress ContentModified/ServerCancelled errors per LSP spec instead of logging as errors.
|
|
54
|
+
|
|
55
|
+
* **Semantic Tokens**: Skip degraded semantic token responses to preserve syntax highlighting.
|
|
56
|
+
|
|
57
|
+
* **Theme Save**: Fixed save failing when themes directory doesn't exist (#1180). Fixed saving incomplete theme files.
|
|
58
|
+
|
|
59
|
+
* **LSP Completion**: Fixed completion debounce, cleanup-on-disable, and popup positioning issues.
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
3
63
|
## 0.2.12
|
|
4
64
|
|
|
5
65
|
### Features
|
package/README.md
CHANGED
|
@@ -67,6 +67,7 @@ Or, pick your preferred method:
|
|
|
67
67
|
| Debian/Ubuntu | [.deb](#debianubuntu-deb) |
|
|
68
68
|
| Fedora/RHEL | [.rpm](#fedorarhelopensuse-rpm), [Terra](https://terra.fyralabs.com/) |
|
|
69
69
|
| FreeBSD | [ports / pkg](https://www.freshports.org/editors/fresh) |
|
|
70
|
+
| Gentoo | [GURU](#gentoo-guru) |
|
|
70
71
|
| Linux (any distro) | [AppImage](#appimage), [Flatpak](#flatpak) |
|
|
71
72
|
| All platforms | [Pre-built binaries](#pre-built-binaries) |
|
|
72
73
|
| npm | [npm / npx](#npm) |
|
|
@@ -142,6 +143,15 @@ curl -sL $(curl -s https://api.github.com/repos/sinelaw/fresh/releases/latest |
|
|
|
142
143
|
|
|
143
144
|
Or download the `.rpm` file manually from the [releases page](https://github.com/sinelaw/fresh/releases).
|
|
144
145
|
|
|
146
|
+
### Gentoo ([GURU](https://wiki.gentoo.org/wiki/Project:GURU))
|
|
147
|
+
|
|
148
|
+
Enable the repository as read in [Project:GURU/Information for End Users](https://wiki.gentoo.org/wiki/Project:GURU/Information_for_End_Users) then emerge the package:
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
```bash
|
|
152
|
+
emerge --ask app-editors/fresh
|
|
153
|
+
```
|
|
154
|
+
|
|
145
155
|
### AppImage
|
|
146
156
|
|
|
147
157
|
Download the `.AppImage` file from the [releases page](https://github.com/sinelaw/fresh/releases) and run:
|
package/package.json
CHANGED
package/plugins/audit_mode.ts
CHANGED
|
@@ -589,7 +589,7 @@ async function refreshReviewData() {
|
|
|
589
589
|
|
|
590
590
|
// --- Actions ---
|
|
591
591
|
|
|
592
|
-
|
|
592
|
+
async function review_stage_hunk() {
|
|
593
593
|
const props = editor.getTextPropertiesAtCursor(editor.getActiveBufferId());
|
|
594
594
|
if (props.length > 0 && props[0].hunkId) {
|
|
595
595
|
const id = props[0].hunkId as string;
|
|
@@ -598,9 +598,10 @@ globalThis.review_stage_hunk = async () => {
|
|
|
598
598
|
if (h) h.status = 'staged';
|
|
599
599
|
await updateReviewUI();
|
|
600
600
|
}
|
|
601
|
-
}
|
|
601
|
+
}
|
|
602
|
+
registerHandler("review_stage_hunk", review_stage_hunk);
|
|
602
603
|
|
|
603
|
-
|
|
604
|
+
async function review_discard_hunk() {
|
|
604
605
|
const props = editor.getTextPropertiesAtCursor(editor.getActiveBufferId());
|
|
605
606
|
if (props.length > 0 && props[0].hunkId) {
|
|
606
607
|
const id = props[0].hunkId as string;
|
|
@@ -609,9 +610,10 @@ globalThis.review_discard_hunk = async () => {
|
|
|
609
610
|
if (h) h.status = 'discarded';
|
|
610
611
|
await updateReviewUI();
|
|
611
612
|
}
|
|
612
|
-
}
|
|
613
|
+
}
|
|
614
|
+
registerHandler("review_discard_hunk", review_discard_hunk);
|
|
613
615
|
|
|
614
|
-
|
|
616
|
+
async function review_undo_action() {
|
|
615
617
|
const props = editor.getTextPropertiesAtCursor(editor.getActiveBufferId());
|
|
616
618
|
if (props.length > 0 && props[0].hunkId) {
|
|
617
619
|
const id = props[0].hunkId as string;
|
|
@@ -620,25 +622,29 @@ globalThis.review_undo_action = async () => {
|
|
|
620
622
|
if (h) h.status = 'pending';
|
|
621
623
|
await updateReviewUI();
|
|
622
624
|
}
|
|
623
|
-
}
|
|
625
|
+
}
|
|
626
|
+
registerHandler("review_undo_action", review_undo_action);
|
|
624
627
|
|
|
625
|
-
|
|
628
|
+
function review_next_hunk() {
|
|
626
629
|
const bid = editor.getActiveBufferId();
|
|
627
630
|
const props = editor.getTextPropertiesAtCursor(bid);
|
|
628
631
|
let cur = -1;
|
|
629
632
|
if (props.length > 0 && props[0].index !== undefined) cur = props[0].index as number;
|
|
630
633
|
if (cur + 1 < state.hunks.length) editor.setBufferCursor(bid, state.hunks[cur + 1].byteOffset);
|
|
631
|
-
}
|
|
634
|
+
}
|
|
635
|
+
registerHandler("review_next_hunk", review_next_hunk);
|
|
632
636
|
|
|
633
|
-
|
|
637
|
+
function review_prev_hunk() {
|
|
634
638
|
const bid = editor.getActiveBufferId();
|
|
635
639
|
const props = editor.getTextPropertiesAtCursor(bid);
|
|
636
640
|
let cur = state.hunks.length;
|
|
637
641
|
if (props.length > 0 && props[0].index !== undefined) cur = props[0].index as number;
|
|
638
642
|
if (cur - 1 >= 0) editor.setBufferCursor(bid, state.hunks[cur - 1].byteOffset);
|
|
639
|
-
}
|
|
643
|
+
}
|
|
644
|
+
registerHandler("review_prev_hunk", review_prev_hunk);
|
|
640
645
|
|
|
641
|
-
|
|
646
|
+
function review_refresh() { refreshReviewData(); }
|
|
647
|
+
registerHandler("review_refresh", review_refresh);
|
|
642
648
|
|
|
643
649
|
let activeDiffViewState: { lSplit: number, rSplit: number } | null = null;
|
|
644
650
|
|
|
@@ -659,7 +665,7 @@ function findLineForByte(lineByteOffsets: number[], topByte: number): number {
|
|
|
659
665
|
return low;
|
|
660
666
|
}
|
|
661
667
|
|
|
662
|
-
|
|
668
|
+
function on_viewport_changed(data: any) {
|
|
663
669
|
// This handler is now a no-op - scroll sync is handled by the core
|
|
664
670
|
// using the anchor-based ScrollSyncGroup system.
|
|
665
671
|
// Keeping the handler for backward compatibility if core sync fails.
|
|
@@ -681,7 +687,8 @@ globalThis.on_viewport_changed = (data: any) => {
|
|
|
681
687
|
const targetByte = oldLineByteOffsets[Math.min(lineNum, oldLineByteOffsets.length - 1)];
|
|
682
688
|
(editor as any).setSplitScroll(oldSplitId, targetByte);
|
|
683
689
|
}
|
|
684
|
-
}
|
|
690
|
+
}
|
|
691
|
+
registerHandler("on_viewport_changed", on_viewport_changed);
|
|
685
692
|
|
|
686
693
|
/**
|
|
687
694
|
* Represents an aligned line pair for side-by-side diff display
|
|
@@ -1017,7 +1024,7 @@ interface CompositeDiffState {
|
|
|
1017
1024
|
|
|
1018
1025
|
let activeCompositeDiffState: CompositeDiffState | null = null;
|
|
1019
1026
|
|
|
1020
|
-
|
|
1027
|
+
async function review_drill_down() {
|
|
1021
1028
|
const bid = editor.getActiveBufferId();
|
|
1022
1029
|
const props = editor.getTextPropertiesAtCursor(bid);
|
|
1023
1030
|
if (props.length > 0 && props[0].hunkId) {
|
|
@@ -1048,10 +1055,8 @@ globalThis.review_drill_down = async () => {
|
|
|
1048
1055
|
const oldContent = gitShow.stdout;
|
|
1049
1056
|
|
|
1050
1057
|
// Read new file content (use absolute path for readFile)
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
newContent = await editor.readFile(absoluteFilePath);
|
|
1054
|
-
} catch (e) {
|
|
1058
|
+
const newContent = await editor.readFile(absoluteFilePath);
|
|
1059
|
+
if (newContent === null) {
|
|
1055
1060
|
editor.setStatus(editor.t("status.failed_new_version"));
|
|
1056
1061
|
return;
|
|
1057
1062
|
}
|
|
@@ -1185,7 +1190,8 @@ globalThis.review_drill_down = async () => {
|
|
|
1185
1190
|
|
|
1186
1191
|
editor.setStatus(editor.t("status.diff_summary", { added: String(addedCount), removed: String(removedCount), modified: String(modifiedCount) }));
|
|
1187
1192
|
}
|
|
1188
|
-
}
|
|
1193
|
+
}
|
|
1194
|
+
registerHandler("review_drill_down", review_drill_down);
|
|
1189
1195
|
|
|
1190
1196
|
// Define the diff-view mode - inherits from "normal" for all standard navigation/selection/copy
|
|
1191
1197
|
// Only adds diff-specific keybindings (close, hunk navigation)
|
|
@@ -1237,7 +1243,7 @@ function getCurrentLineInfo(): PendingCommentInfo | null {
|
|
|
1237
1243
|
// Pending prompt state for event-based prompt handling
|
|
1238
1244
|
let pendingCommentInfo: PendingCommentInfo | null = null;
|
|
1239
1245
|
|
|
1240
|
-
|
|
1246
|
+
async function review_add_comment() {
|
|
1241
1247
|
const info = getCurrentLineInfo();
|
|
1242
1248
|
if (!info) {
|
|
1243
1249
|
editor.setStatus(editor.t("status.no_hunk_selected"));
|
|
@@ -1257,10 +1263,11 @@ globalThis.review_add_comment = async () => {
|
|
|
1257
1263
|
lineRef = `L${info.oldLine}`;
|
|
1258
1264
|
}
|
|
1259
1265
|
editor.startPrompt(editor.t("prompt.comment", { line: lineRef }), "review-comment");
|
|
1260
|
-
}
|
|
1266
|
+
}
|
|
1267
|
+
registerHandler("review_add_comment", review_add_comment);
|
|
1261
1268
|
|
|
1262
1269
|
// Prompt event handlers
|
|
1263
|
-
|
|
1270
|
+
function on_review_prompt_confirm(args: { prompt_type: string; input: string }): boolean {
|
|
1264
1271
|
if (args.prompt_type !== "review-comment") {
|
|
1265
1272
|
return true; // Not our prompt
|
|
1266
1273
|
}
|
|
@@ -1292,21 +1299,23 @@ globalThis.on_review_prompt_confirm = (args: { prompt_type: string; input: strin
|
|
|
1292
1299
|
}
|
|
1293
1300
|
pendingCommentInfo = null;
|
|
1294
1301
|
return true;
|
|
1295
|
-
}
|
|
1302
|
+
}
|
|
1303
|
+
registerHandler("on_review_prompt_confirm", on_review_prompt_confirm);
|
|
1296
1304
|
|
|
1297
|
-
|
|
1305
|
+
function on_review_prompt_cancel(args: { prompt_type: string }): boolean {
|
|
1298
1306
|
if (args.prompt_type === "review-comment") {
|
|
1299
1307
|
pendingCommentInfo = null;
|
|
1300
1308
|
editor.setStatus(editor.t("status.comment_cancelled"));
|
|
1301
1309
|
}
|
|
1302
1310
|
return true;
|
|
1303
|
-
}
|
|
1311
|
+
}
|
|
1312
|
+
registerHandler("on_review_prompt_cancel", on_review_prompt_cancel);
|
|
1304
1313
|
|
|
1305
1314
|
// Register prompt event handlers
|
|
1306
1315
|
editor.on("prompt_confirmed", "on_review_prompt_confirm");
|
|
1307
1316
|
editor.on("prompt_cancelled", "on_review_prompt_cancel");
|
|
1308
1317
|
|
|
1309
|
-
|
|
1318
|
+
async function review_approve_hunk() {
|
|
1310
1319
|
const hunkId = getCurrentHunkId();
|
|
1311
1320
|
if (!hunkId) return;
|
|
1312
1321
|
const h = state.hunks.find(x => x.id === hunkId);
|
|
@@ -1315,9 +1324,10 @@ globalThis.review_approve_hunk = async () => {
|
|
|
1315
1324
|
await updateReviewUI();
|
|
1316
1325
|
editor.setStatus(editor.t("status.hunk_approved"));
|
|
1317
1326
|
}
|
|
1318
|
-
}
|
|
1327
|
+
}
|
|
1328
|
+
registerHandler("review_approve_hunk", review_approve_hunk);
|
|
1319
1329
|
|
|
1320
|
-
|
|
1330
|
+
async function review_reject_hunk() {
|
|
1321
1331
|
const hunkId = getCurrentHunkId();
|
|
1322
1332
|
if (!hunkId) return;
|
|
1323
1333
|
const h = state.hunks.find(x => x.id === hunkId);
|
|
@@ -1326,9 +1336,10 @@ globalThis.review_reject_hunk = async () => {
|
|
|
1326
1336
|
await updateReviewUI();
|
|
1327
1337
|
editor.setStatus(editor.t("status.hunk_rejected"));
|
|
1328
1338
|
}
|
|
1329
|
-
}
|
|
1339
|
+
}
|
|
1340
|
+
registerHandler("review_reject_hunk", review_reject_hunk);
|
|
1330
1341
|
|
|
1331
|
-
|
|
1342
|
+
async function review_needs_changes() {
|
|
1332
1343
|
const hunkId = getCurrentHunkId();
|
|
1333
1344
|
if (!hunkId) return;
|
|
1334
1345
|
const h = state.hunks.find(x => x.id === hunkId);
|
|
@@ -1337,9 +1348,10 @@ globalThis.review_needs_changes = async () => {
|
|
|
1337
1348
|
await updateReviewUI();
|
|
1338
1349
|
editor.setStatus(editor.t("status.hunk_needs_changes"));
|
|
1339
1350
|
}
|
|
1340
|
-
}
|
|
1351
|
+
}
|
|
1352
|
+
registerHandler("review_needs_changes", review_needs_changes);
|
|
1341
1353
|
|
|
1342
|
-
|
|
1354
|
+
async function review_question_hunk() {
|
|
1343
1355
|
const hunkId = getCurrentHunkId();
|
|
1344
1356
|
if (!hunkId) return;
|
|
1345
1357
|
const h = state.hunks.find(x => x.id === hunkId);
|
|
@@ -1348,9 +1360,10 @@ globalThis.review_question_hunk = async () => {
|
|
|
1348
1360
|
await updateReviewUI();
|
|
1349
1361
|
editor.setStatus(editor.t("status.hunk_question"));
|
|
1350
1362
|
}
|
|
1351
|
-
}
|
|
1363
|
+
}
|
|
1364
|
+
registerHandler("review_question_hunk", review_question_hunk);
|
|
1352
1365
|
|
|
1353
|
-
|
|
1366
|
+
async function review_clear_status() {
|
|
1354
1367
|
const hunkId = getCurrentHunkId();
|
|
1355
1368
|
if (!hunkId) return;
|
|
1356
1369
|
const h = state.hunks.find(x => x.id === hunkId);
|
|
@@ -1359,17 +1372,19 @@ globalThis.review_clear_status = async () => {
|
|
|
1359
1372
|
await updateReviewUI();
|
|
1360
1373
|
editor.setStatus(editor.t("status.hunk_status_cleared"));
|
|
1361
1374
|
}
|
|
1362
|
-
}
|
|
1375
|
+
}
|
|
1376
|
+
registerHandler("review_clear_status", review_clear_status);
|
|
1363
1377
|
|
|
1364
|
-
|
|
1378
|
+
async function review_set_overall_feedback() {
|
|
1365
1379
|
const text = await editor.prompt(editor.t("prompt.overall_feedback"), state.overallFeedback || "");
|
|
1366
1380
|
if (text !== null) {
|
|
1367
1381
|
state.overallFeedback = text.trim();
|
|
1368
1382
|
editor.setStatus(text.trim() ? editor.t("status.feedback_set") : editor.t("status.feedback_cleared"));
|
|
1369
1383
|
}
|
|
1370
|
-
}
|
|
1384
|
+
}
|
|
1385
|
+
registerHandler("review_set_overall_feedback", review_set_overall_feedback);
|
|
1371
1386
|
|
|
1372
|
-
|
|
1387
|
+
async function review_export_session() {
|
|
1373
1388
|
const cwd = editor.getCwd();
|
|
1374
1389
|
const reviewDir = editor.pathJoin(cwd, ".review");
|
|
1375
1390
|
|
|
@@ -1440,9 +1455,10 @@ globalThis.review_export_session = async () => {
|
|
|
1440
1455
|
const filePath = editor.pathJoin(reviewDir, "session.md");
|
|
1441
1456
|
await editor.writeFile(filePath, md);
|
|
1442
1457
|
editor.setStatus(editor.t("status.exported", { path: filePath }));
|
|
1443
|
-
}
|
|
1458
|
+
}
|
|
1459
|
+
registerHandler("review_export_session", review_export_session);
|
|
1444
1460
|
|
|
1445
|
-
|
|
1461
|
+
async function review_export_json() {
|
|
1446
1462
|
const cwd = editor.getCwd();
|
|
1447
1463
|
const reviewDir = editor.pathJoin(cwd, ".review");
|
|
1448
1464
|
// writeFile creates parent directories
|
|
@@ -1476,9 +1492,10 @@ globalThis.review_export_json = async () => {
|
|
|
1476
1492
|
const filePath = editor.pathJoin(reviewDir, "session.json");
|
|
1477
1493
|
await editor.writeFile(filePath, JSON.stringify(session, null, 2));
|
|
1478
1494
|
editor.setStatus(editor.t("status.exported", { path: filePath }));
|
|
1479
|
-
}
|
|
1495
|
+
}
|
|
1496
|
+
registerHandler("review_export_json", review_export_json);
|
|
1480
1497
|
|
|
1481
|
-
|
|
1498
|
+
async function start_review_diff() {
|
|
1482
1499
|
editor.setStatus(editor.t("status.generating"));
|
|
1483
1500
|
editor.setContext("review-mode", true);
|
|
1484
1501
|
|
|
@@ -1497,27 +1514,31 @@ globalThis.start_review_diff = async () => {
|
|
|
1497
1514
|
editor.setStatus(editor.t("status.review_summary", { count: String(state.hunks.length) }));
|
|
1498
1515
|
editor.on("buffer_activated", "on_review_buffer_activated");
|
|
1499
1516
|
editor.on("buffer_closed", "on_review_buffer_closed");
|
|
1500
|
-
}
|
|
1517
|
+
}
|
|
1518
|
+
registerHandler("start_review_diff", start_review_diff);
|
|
1501
1519
|
|
|
1502
|
-
|
|
1520
|
+
function stop_review_diff() {
|
|
1503
1521
|
state.reviewBufferId = null;
|
|
1504
1522
|
editor.setContext("review-mode", false);
|
|
1505
1523
|
editor.off("buffer_activated", "on_review_buffer_activated");
|
|
1506
1524
|
editor.off("buffer_closed", "on_review_buffer_closed");
|
|
1507
1525
|
editor.setStatus(editor.t("status.stopped"));
|
|
1508
|
-
}
|
|
1526
|
+
}
|
|
1527
|
+
registerHandler("stop_review_diff", stop_review_diff);
|
|
1509
1528
|
|
|
1510
1529
|
|
|
1511
|
-
|
|
1530
|
+
function on_review_buffer_activated(data: any) {
|
|
1512
1531
|
if (data.buffer_id === state.reviewBufferId) refreshReviewData();
|
|
1513
|
-
}
|
|
1532
|
+
}
|
|
1533
|
+
registerHandler("on_review_buffer_activated", on_review_buffer_activated);
|
|
1514
1534
|
|
|
1515
|
-
|
|
1516
|
-
if (data.buffer_id === state.reviewBufferId)
|
|
1517
|
-
}
|
|
1535
|
+
function on_review_buffer_closed(data: any) {
|
|
1536
|
+
if (data.buffer_id === state.reviewBufferId) stop_review_diff();
|
|
1537
|
+
}
|
|
1538
|
+
registerHandler("on_review_buffer_closed", on_review_buffer_closed);
|
|
1518
1539
|
|
|
1519
1540
|
// Side-by-side diff for current file using composite buffers
|
|
1520
|
-
|
|
1541
|
+
async function side_by_side_diff_current_file() {
|
|
1521
1542
|
const bid = editor.getActiveBufferId();
|
|
1522
1543
|
const absolutePath = editor.getBufferPath(bid);
|
|
1523
1544
|
|
|
@@ -1613,10 +1634,8 @@ globalThis.side_by_side_diff_current_file = async () => {
|
|
|
1613
1634
|
const oldContent = gitShow.stdout;
|
|
1614
1635
|
|
|
1615
1636
|
// Read new file content (use absolute path for readFile)
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
newContent = await editor.readFile(absolutePath);
|
|
1619
|
-
} catch (e) {
|
|
1637
|
+
const newContent = await editor.readFile(absolutePath);
|
|
1638
|
+
if (newContent === null) {
|
|
1620
1639
|
editor.setStatus(editor.t("status.failed_new_version"));
|
|
1621
1640
|
return;
|
|
1622
1641
|
}
|
|
@@ -1740,7 +1759,8 @@ globalThis.side_by_side_diff_current_file = async () => {
|
|
|
1740
1759
|
const modifiedCount = Math.min(addedCount, removedCount);
|
|
1741
1760
|
|
|
1742
1761
|
editor.setStatus(editor.t("status.diff_summary", { added: String(addedCount), removed: String(removedCount), modified: String(modifiedCount) }));
|
|
1743
|
-
}
|
|
1762
|
+
}
|
|
1763
|
+
registerHandler("side_by_side_diff_current_file", side_by_side_diff_current_file);
|
|
1744
1764
|
|
|
1745
1765
|
// Register Modes and Commands
|
|
1746
1766
|
editor.registerCommand("%cmd.review_diff", "%cmd.review_diff_desc", "start_review_diff", null);
|
|
@@ -1760,7 +1780,7 @@ editor.registerCommand("%cmd.export_markdown", "%cmd.export_markdown_desc", "rev
|
|
|
1760
1780
|
editor.registerCommand("%cmd.export_json", "%cmd.export_json_desc", "review_export_json", "review-mode");
|
|
1761
1781
|
|
|
1762
1782
|
// Handler for when buffers are closed - cleans up scroll sync groups and composite buffers
|
|
1763
|
-
|
|
1783
|
+
function on_buffer_closed(data: any) {
|
|
1764
1784
|
// If one of the diff view buffers is closed, clean up the scroll sync group
|
|
1765
1785
|
if (activeSideBySideState) {
|
|
1766
1786
|
if (data.buffer_id === activeSideBySideState.oldBufferId ||
|
|
@@ -1787,7 +1807,8 @@ globalThis.on_buffer_closed = (data: any) => {
|
|
|
1787
1807
|
activeCompositeDiffState = null;
|
|
1788
1808
|
}
|
|
1789
1809
|
}
|
|
1790
|
-
}
|
|
1810
|
+
}
|
|
1811
|
+
registerHandler("on_buffer_closed", on_buffer_closed);
|
|
1791
1812
|
|
|
1792
1813
|
editor.on("buffer_closed", "on_buffer_closed");
|
|
1793
1814
|
|
package/plugins/check-types.sh
CHANGED
package/plugins/clangd-lsp.ts
CHANGED
|
@@ -54,7 +54,7 @@ let clangdLspError: {
|
|
|
54
54
|
/**
|
|
55
55
|
* Handle LSP server errors for C/C++
|
|
56
56
|
*/
|
|
57
|
-
|
|
57
|
+
function on_clangd_lsp_server_error(
|
|
58
58
|
data: LspServerErrorData
|
|
59
59
|
): void {
|
|
60
60
|
// Only handle C/C++ language errors
|
|
@@ -79,7 +79,8 @@ globalThis.on_clangd_lsp_server_error = function (
|
|
|
79
79
|
} else {
|
|
80
80
|
editor.setStatus(`C/C++ LSP error: ${data.message}`);
|
|
81
81
|
}
|
|
82
|
-
}
|
|
82
|
+
}
|
|
83
|
+
registerHandler("on_clangd_lsp_server_error", on_clangd_lsp_server_error);
|
|
83
84
|
|
|
84
85
|
// Register hook for LSP server errors
|
|
85
86
|
editor.on("lsp_server_error", "on_clangd_lsp_server_error");
|
|
@@ -87,7 +88,7 @@ editor.on("lsp_server_error", "on_clangd_lsp_server_error");
|
|
|
87
88
|
/**
|
|
88
89
|
* Handle status bar click when there's a C/C++ LSP error
|
|
89
90
|
*/
|
|
90
|
-
|
|
91
|
+
function on_clangd_lsp_status_clicked(
|
|
91
92
|
data: LspStatusClickedData
|
|
92
93
|
): void {
|
|
93
94
|
// Only handle C/C++ language clicks when there's an error
|
|
@@ -110,7 +111,8 @@ globalThis.on_clangd_lsp_status_clicked = function (
|
|
|
110
111
|
{ id: "dismiss", label: "Dismiss (ESC)" },
|
|
111
112
|
],
|
|
112
113
|
});
|
|
113
|
-
}
|
|
114
|
+
}
|
|
115
|
+
registerHandler("on_clangd_lsp_status_clicked", on_clangd_lsp_status_clicked);
|
|
114
116
|
|
|
115
117
|
// Register hook for status bar clicks
|
|
116
118
|
editor.on("lsp_status_clicked", "on_clangd_lsp_status_clicked");
|
|
@@ -118,7 +120,7 @@ editor.on("lsp_status_clicked", "on_clangd_lsp_status_clicked");
|
|
|
118
120
|
/**
|
|
119
121
|
* Handle action popup results for C/C++ LSP help
|
|
120
122
|
*/
|
|
121
|
-
|
|
123
|
+
function on_clangd_lsp_action_result(
|
|
122
124
|
data: ActionPopupResultData
|
|
123
125
|
): void {
|
|
124
126
|
// Only handle our popup
|
|
@@ -160,7 +162,8 @@ globalThis.on_clangd_lsp_action_result = function (
|
|
|
160
162
|
default:
|
|
161
163
|
editor.debug(`clangd-lsp: Unknown action: ${data.action_id}`);
|
|
162
164
|
}
|
|
163
|
-
}
|
|
165
|
+
}
|
|
166
|
+
registerHandler("on_clangd_lsp_action_result", on_clangd_lsp_action_result);
|
|
164
167
|
|
|
165
168
|
// Register hook for action popup results
|
|
166
169
|
editor.on("action_popup_result", "on_clangd_lsp_action_result");
|
|
@@ -50,7 +50,7 @@ function setClangdStatus(message: string): void {
|
|
|
50
50
|
editor.setStatus(message);
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
-
|
|
53
|
+
async function clangdSwitchSourceHeader() : Promise<void> {
|
|
54
54
|
const bufferId = editor.getActiveBufferId();
|
|
55
55
|
const path = editor.getBufferPath(bufferId);
|
|
56
56
|
if (!path) {
|
|
@@ -82,7 +82,8 @@ globalThis.clangdSwitchSourceHeader = async function(): Promise<void> {
|
|
|
82
82
|
setClangdStatus(editor.t("status.switch_failed", { error: String(err) }));
|
|
83
83
|
editor.debug(`clangdSwitchSourceHeader error: ${err}`);
|
|
84
84
|
}
|
|
85
|
-
}
|
|
85
|
+
}
|
|
86
|
+
registerHandler("clangdSwitchSourceHeader", clangdSwitchSourceHeader);
|
|
86
87
|
|
|
87
88
|
const projectPanel = new PanelManager(editor, "Clangd project setup", "clangd-project-setup");
|
|
88
89
|
|
|
@@ -226,7 +227,7 @@ function analyzeProject(root: string | null) {
|
|
|
226
227
|
return status;
|
|
227
228
|
}
|
|
228
229
|
|
|
229
|
-
|
|
230
|
+
async function clangdProjectSetup() : Promise<void> {
|
|
230
231
|
const projectRoot = detectProjectRoot();
|
|
231
232
|
const summary = analyzeProject(projectRoot);
|
|
232
233
|
const entries = summary.map((line) => ({
|
|
@@ -237,7 +238,8 @@ globalThis.clangdProjectSetup = async function (): Promise<void> {
|
|
|
237
238
|
entries,
|
|
238
239
|
ratio: 0.3,
|
|
239
240
|
});
|
|
240
|
-
}
|
|
241
|
+
}
|
|
242
|
+
registerHandler("clangdProjectSetup", clangdProjectSetup);
|
|
241
243
|
|
|
242
244
|
editor.registerCommand(
|
|
243
245
|
"%cmd.project_setup",
|
|
@@ -246,7 +248,7 @@ editor.registerCommand(
|
|
|
246
248
|
null
|
|
247
249
|
);
|
|
248
250
|
|
|
249
|
-
|
|
251
|
+
function clangdOpenProjectConfig() : void {
|
|
250
252
|
const bufferId = editor.getActiveBufferId();
|
|
251
253
|
const targets = new Set<string>();
|
|
252
254
|
const bufferPath = editor.getBufferPath(bufferId);
|
|
@@ -273,7 +275,8 @@ globalThis.clangdOpenProjectConfig = function(): void {
|
|
|
273
275
|
if (!opened) {
|
|
274
276
|
setClangdStatus(editor.t("status.config_not_found"));
|
|
275
277
|
}
|
|
276
|
-
}
|
|
278
|
+
}
|
|
279
|
+
registerHandler("clangdOpenProjectConfig", clangdOpenProjectConfig);
|
|
277
280
|
|
|
278
281
|
editor.registerCommand(
|
|
279
282
|
"%cmd.switch_source_header",
|
|
@@ -290,7 +293,7 @@ editor.registerCommand(
|
|
|
290
293
|
);
|
|
291
294
|
|
|
292
295
|
|
|
293
|
-
|
|
296
|
+
function onClangdCustomNotification(payload: {
|
|
294
297
|
language: string;
|
|
295
298
|
method: string;
|
|
296
299
|
params: Record<string, unknown> | null;
|
|
@@ -311,6 +314,7 @@ globalThis.onClangdCustomNotification = function(payload: {
|
|
|
311
314
|
const usage = (payload.params as any).used ?? "unknown";
|
|
312
315
|
editor.debug(`Clangd memory usage: ${usage}`);
|
|
313
316
|
}
|
|
314
|
-
}
|
|
317
|
+
}
|
|
318
|
+
registerHandler("onClangdCustomNotification", onClangdCustomNotification);
|
|
315
319
|
|
|
316
320
|
editor.on("lsp/custom_notification", "onClangdCustomNotification");
|
package/plugins/code-tour.ts
CHANGED
|
@@ -123,7 +123,7 @@ interface ActionPopupResultData {
|
|
|
123
123
|
action_id: string;
|
|
124
124
|
}
|
|
125
125
|
|
|
126
|
-
|
|
126
|
+
function tour_on_action_popup_result(data: ActionPopupResultData) : void {
|
|
127
127
|
if (data.popup_id !== TOUR_POPUP_ID) return;
|
|
128
128
|
|
|
129
129
|
switch (data.action_id) {
|
|
@@ -137,7 +137,8 @@ globalThis.tour_on_action_popup_result = function (data: ActionPopupResultData):
|
|
|
137
137
|
exitTour();
|
|
138
138
|
break;
|
|
139
139
|
}
|
|
140
|
-
}
|
|
140
|
+
}
|
|
141
|
+
registerHandler("tour_on_action_popup_result", tour_on_action_popup_result);
|
|
141
142
|
|
|
142
143
|
// ============================================================================
|
|
143
144
|
// Overlay Rendering
|
|
@@ -337,26 +338,30 @@ async function prevStep(): Promise<void> {
|
|
|
337
338
|
// Command Handlers
|
|
338
339
|
// ============================================================================
|
|
339
340
|
|
|
340
|
-
|
|
341
|
+
async function tour_load() : Promise<void> {
|
|
341
342
|
// Prompt for tour file
|
|
342
343
|
const result = await editor.prompt("Enter tour file path:", ".fresh-tour.json");
|
|
343
344
|
|
|
344
345
|
if (result) {
|
|
345
346
|
await loadTour(result);
|
|
346
347
|
}
|
|
347
|
-
}
|
|
348
|
+
}
|
|
349
|
+
registerHandler("tour_load", tour_load);
|
|
348
350
|
|
|
349
|
-
|
|
351
|
+
async function tour_next() : Promise<void> {
|
|
350
352
|
await nextStep();
|
|
351
|
-
}
|
|
353
|
+
}
|
|
354
|
+
registerHandler("tour_next", tour_next);
|
|
352
355
|
|
|
353
|
-
|
|
356
|
+
async function tour_prev() : Promise<void> {
|
|
354
357
|
await prevStep();
|
|
355
|
-
}
|
|
358
|
+
}
|
|
359
|
+
registerHandler("tour_prev", tour_prev);
|
|
356
360
|
|
|
357
|
-
|
|
361
|
+
function tour_exit() : void {
|
|
358
362
|
exitTour();
|
|
359
|
-
}
|
|
363
|
+
}
|
|
364
|
+
registerHandler("tour_exit", tour_exit);
|
|
360
365
|
|
|
361
366
|
// ============================================================================
|
|
362
367
|
// Registration
|