@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.
Files changed (51) hide show
  1. package/CHANGELOG.md +60 -0
  2. package/README.md +10 -0
  3. package/package.json +1 -1
  4. package/plugins/audit_mode.ts +79 -58
  5. package/plugins/check-types.sh +1 -0
  6. package/plugins/clangd-lsp.ts +9 -6
  7. package/plugins/clangd_support.ts +12 -8
  8. package/plugins/code-tour.ts +15 -10
  9. package/plugins/config-schema.json +40 -3
  10. package/plugins/csharp_support.ts +15 -10
  11. package/plugins/css-lsp.ts +9 -6
  12. package/plugins/diagnostics_panel.ts +25 -18
  13. package/plugins/examples/README.md +1 -2
  14. package/plugins/examples/async_demo.ts +28 -28
  15. package/plugins/examples/bookmarks.ts +34 -32
  16. package/plugins/examples/buffer_query_demo.ts +20 -20
  17. package/plugins/examples/hello_world.ts +46 -10
  18. package/plugins/examples/virtual_buffer_demo.ts +16 -12
  19. package/plugins/find_references.ts +7 -5
  20. package/plugins/git_blame.ts +13 -9
  21. package/plugins/git_explorer.ts +9 -6
  22. package/plugins/git_find_file.ts +7 -5
  23. package/plugins/git_grep.ts +3 -2
  24. package/plugins/git_gutter.ts +15 -10
  25. package/plugins/git_log.ts +27 -18
  26. package/plugins/go-lsp.ts +9 -6
  27. package/plugins/html-lsp.ts +9 -6
  28. package/plugins/java-lsp.ts +9 -6
  29. package/plugins/json-lsp.ts +9 -6
  30. package/plugins/latex-lsp.ts +9 -6
  31. package/plugins/lib/finder.ts +1 -0
  32. package/plugins/lib/fresh.d.ts +139 -14
  33. package/plugins/live_grep.ts +3 -2
  34. package/plugins/markdown_compose.ts +33 -23
  35. package/plugins/markdown_source.ts +15 -10
  36. package/plugins/marksman-lsp.ts +9 -6
  37. package/plugins/merge_conflict.ts +33 -22
  38. package/plugins/odin-lsp.ts +9 -6
  39. package/plugins/path_complete.ts +3 -2
  40. package/plugins/pkg.ts +70 -48
  41. package/plugins/python-lsp.ts +9 -6
  42. package/plugins/rust-lsp.ts +102 -6
  43. package/plugins/search_replace.ts +32 -21
  44. package/plugins/templ-lsp.ts +9 -6
  45. package/plugins/test_i18n.ts +3 -2
  46. package/plugins/theme_editor.i18n.json +28 -14
  47. package/plugins/theme_editor.ts +1230 -495
  48. package/plugins/typescript-lsp.ts +9 -6
  49. package/plugins/vi_mode.ts +487 -297
  50. package/plugins/welcome.ts +9 -6
  51. package/plugins/zig-lsp.ts +9 -6
@@ -73,7 +73,7 @@ function getCurrentLineCol(): { line: number; column: number } {
73
73
  }
74
74
 
75
75
  // Action: Add bookmark at current position
76
- globalThis.bookmark_add = function (): void {
76
+ function bookmark_add() : void {
77
77
  const { path, position, splitId } = getCurrentLocation();
78
78
  const { line, column } = getCurrentLineCol();
79
79
 
@@ -105,10 +105,11 @@ globalThis.bookmark_add = function (): void {
105
105
 
106
106
  editor.setStatus(`Added ${name} at ${path}:${line}:${column}`);
107
107
  editor.debug(`Bookmark ${id} created: ${JSON.stringify(bookmark)}`);
108
- };
108
+ }
109
+ registerHandler("bookmark_add", bookmark_add);
109
110
 
110
111
  // Action: List all bookmarks
111
- globalThis.bookmark_list = function (): void {
112
+ function bookmark_list() : void {
112
113
  if (bookmarks.size === 0) {
113
114
  editor.setStatus("No bookmarks");
114
115
  return;
@@ -121,10 +122,11 @@ globalThis.bookmark_list = function (): void {
121
122
 
122
123
  editor.setStatus(`Bookmarks: ${list.join(" | ")}`);
123
124
  editor.debug(`All bookmarks: ${JSON.stringify([...bookmarks.values()])}`);
124
- };
125
+ }
126
+ registerHandler("bookmark_list", bookmark_list);
125
127
 
126
128
  // Action: Jump to bookmark by ID
127
- globalThis.bookmark_goto = function (): void {
129
+ function bookmark_goto() : void {
128
130
  if (bookmarks.size === 0) {
129
131
  editor.setStatus("No bookmarks to jump to");
130
132
  return;
@@ -147,10 +149,11 @@ globalThis.bookmark_goto = function (): void {
147
149
  editor.setStatus(`Failed to open ${firstBookmark.path}`);
148
150
  }
149
151
  }
150
- };
152
+ }
153
+ registerHandler("bookmark_goto", bookmark_goto);
151
154
 
152
155
  // Action: Jump to bookmark in same split (split-aware)
153
- globalThis.bookmark_goto_split = function (): void {
156
+ function bookmark_goto_split() : void {
154
157
  if (bookmarks.size === 0) {
155
158
  editor.setStatus("No bookmarks");
156
159
  return;
@@ -176,10 +179,11 @@ globalThis.bookmark_goto_split = function (): void {
176
179
  editor.setStatus(`Failed to open in split ${currentSplit}`);
177
180
  }
178
181
  }
179
- };
182
+ }
183
+ registerHandler("bookmark_goto_split", bookmark_goto_split);
180
184
 
181
185
  // Action: Remove all bookmarks
182
- globalThis.bookmark_clear = function (): void {
186
+ function bookmark_clear() : void {
183
187
  const bufferId = editor.getActiveBufferId();
184
188
 
185
189
  // Remove all bookmark overlays using namespace
@@ -189,21 +193,23 @@ globalThis.bookmark_clear = function (): void {
189
193
  bookmarks.clear();
190
194
 
191
195
  editor.setStatus(`Cleared ${count} bookmark(s)`);
192
- };
196
+ }
197
+ registerHandler("bookmark_clear", bookmark_clear);
193
198
 
194
199
  // Action: Show current split info
195
- globalThis.show_split_info = function (): void {
200
+ function show_split_info() : void {
196
201
  const splitId = editor.getActiveSplitId();
197
202
  const bufferId = editor.getActiveBufferId();
198
203
  const path = editor.getBufferPath(bufferId);
199
204
 
200
205
  editor.setStatus(`Split ${splitId} | Buffer ${bufferId} | ${path || "[untitled]"}`);
201
- };
206
+ }
207
+ registerHandler("show_split_info", show_split_info);
202
208
 
203
209
  // Interactive bookmark selection using prompt API
204
210
  let bookmarkSuggestionIds: number[] = [];
205
211
 
206
- globalThis.bookmark_select = function (): void {
212
+ function bookmark_select() : void {
207
213
  if (bookmarks.size === 0) {
208
214
  editor.setStatus("No bookmarks to select");
209
215
  return;
@@ -227,10 +233,11 @@ globalThis.bookmark_select = function (): void {
227
233
  editor.startPrompt("Select bookmark: ", "bookmark-select");
228
234
  editor.setPromptSuggestions(suggestions);
229
235
  editor.setStatus(`${bookmarks.size} bookmark(s) available`);
230
- };
236
+ }
237
+ registerHandler("bookmark_select", bookmark_select);
231
238
 
232
239
  // Handle bookmark selection confirmation
233
- globalThis.onBookmarkSelectConfirmed = function (args: {
240
+ function onBookmarkSelectConfirmed(args: {
234
241
  prompt_type: string;
235
242
  selected_index: number | null;
236
243
  input: string;
@@ -252,17 +259,19 @@ globalThis.onBookmarkSelectConfirmed = function (args: {
252
259
  }
253
260
 
254
261
  return true;
255
- };
262
+ }
263
+ registerHandler("onBookmarkSelectConfirmed", onBookmarkSelectConfirmed);
256
264
 
257
265
  // Handle bookmark selection cancellation
258
- globalThis.onBookmarkSelectCancelled = function (args: { prompt_type: string }): boolean {
266
+ function onBookmarkSelectCancelled(args: { prompt_type: string }) : boolean {
259
267
  if (args.prompt_type !== "bookmark-select") {
260
268
  return true;
261
269
  }
262
270
 
263
271
  editor.setStatus("Bookmark selection cancelled");
264
272
  return true;
265
- };
273
+ }
274
+ registerHandler("onBookmarkSelectCancelled", onBookmarkSelectCancelled);
266
275
 
267
276
  // Register bookmark event handlers
268
277
  editor.on("prompt_confirmed", "onBookmarkSelectConfirmed");
@@ -272,50 +281,43 @@ editor.on("prompt_cancelled", "onBookmarkSelectCancelled");
272
281
  editor.registerCommand(
273
282
  "Add Bookmark",
274
283
  "Add a bookmark at the current cursor position",
275
- "bookmark_add",
276
- "normal"
284
+ "bookmark_add"
277
285
  );
278
286
 
279
287
  editor.registerCommand(
280
288
  "List Bookmarks",
281
289
  "Show all bookmarks",
282
- "bookmark_list",
283
- "normal"
290
+ "bookmark_list"
284
291
  );
285
292
 
286
293
  editor.registerCommand(
287
294
  "Go to Bookmark",
288
295
  "Jump to the first bookmark",
289
- "bookmark_goto",
290
- "normal"
296
+ "bookmark_goto"
291
297
  );
292
298
 
293
299
  editor.registerCommand(
294
300
  "Go to Bookmark (Current Split)",
295
301
  "Jump to bookmark in current split",
296
- "bookmark_goto_split",
297
- "normal"
302
+ "bookmark_goto_split"
298
303
  );
299
304
 
300
305
  editor.registerCommand(
301
306
  "Clear Bookmarks",
302
307
  "Remove all bookmarks",
303
- "bookmark_clear",
304
- "normal"
308
+ "bookmark_clear"
305
309
  );
306
310
 
307
311
  editor.registerCommand(
308
312
  "Show Split Info",
309
313
  "Display current split and buffer information",
310
- "show_split_info",
311
- "" // Available in all contexts
314
+ "show_split_info"
312
315
  );
313
316
 
314
317
  editor.registerCommand(
315
318
  "Select Bookmark",
316
319
  "Interactively select and jump to a bookmark",
317
- "bookmark_select",
318
- "normal"
320
+ "bookmark_select"
319
321
  );
320
322
 
321
323
  // Plugin initialized
@@ -6,7 +6,7 @@
6
6
  */
7
7
 
8
8
  // Show buffer info
9
- globalThis.show_buffer_info_demo = function(): void {
9
+ function show_buffer_info_demo() : void {
10
10
  const bufferId = editor.getActiveBufferId();
11
11
  const info = editor.getBufferInfo(bufferId);
12
12
 
@@ -18,17 +18,17 @@ globalThis.show_buffer_info_demo = function(): void {
18
18
  } else {
19
19
  editor.setStatus("No buffer info available");
20
20
  }
21
- };
21
+ }
22
+ registerHandler("show_buffer_info_demo", show_buffer_info_demo);
22
23
 
23
24
  editor.registerCommand(
24
25
  "Query Demo: Show Buffer Info",
25
26
  "Display information about the current buffer",
26
- "show_buffer_info_demo",
27
- "normal"
27
+ "show_buffer_info_demo"
28
28
  );
29
29
 
30
30
  // Show cursor position with selection info
31
- globalThis.show_cursor_info_demo = function(): void {
31
+ function show_cursor_info_demo() : void {
32
32
  const cursor = editor.getPrimaryCursor();
33
33
 
34
34
  if (cursor) {
@@ -44,30 +44,30 @@ globalThis.show_cursor_info_demo = function(): void {
44
44
  } else {
45
45
  editor.setStatus("No cursor info available");
46
46
  }
47
- };
47
+ }
48
+ registerHandler("show_cursor_info_demo", show_cursor_info_demo);
48
49
 
49
50
  editor.registerCommand(
50
51
  "Query Demo: Show Cursor Position",
51
52
  "Display cursor position and selection info",
52
- "show_cursor_info_demo",
53
- "normal"
53
+ "show_cursor_info_demo"
54
54
  );
55
55
 
56
56
  // Count all cursors (multi-cursor support)
57
- globalThis.count_cursors_demo = function(): void {
57
+ function count_cursors_demo() : void {
58
58
  const cursors = editor.getAllCursors();
59
59
  editor.setStatus(`Active cursors: ${cursors.length}`);
60
- };
60
+ }
61
+ registerHandler("count_cursors_demo", count_cursors_demo);
61
62
 
62
63
  editor.registerCommand(
63
64
  "Query Demo: Count All Cursors",
64
65
  "Display the number of active cursors",
65
- "count_cursors_demo",
66
- "normal"
66
+ "count_cursors_demo"
67
67
  );
68
68
 
69
69
  // List all buffers
70
- globalThis.list_all_buffers_demo = function(): void {
70
+ function list_all_buffers_demo() : void {
71
71
  const buffers = editor.listBuffers();
72
72
  let modifiedCount = 0;
73
73
 
@@ -78,17 +78,17 @@ globalThis.list_all_buffers_demo = function(): void {
78
78
  }
79
79
 
80
80
  editor.setStatus(`Open buffers: ${buffers.length} (${modifiedCount} modified)`);
81
- };
81
+ }
82
+ registerHandler("list_all_buffers_demo", list_all_buffers_demo);
82
83
 
83
84
  editor.registerCommand(
84
85
  "Query Demo: List All Buffers",
85
86
  "Show count of open buffers",
86
- "list_all_buffers_demo",
87
- "normal"
87
+ "list_all_buffers_demo"
88
88
  );
89
89
 
90
90
  // Show viewport info
91
- globalThis.show_viewport_demo = function(): void {
91
+ function show_viewport_demo() : void {
92
92
  const vp = editor.getViewport();
93
93
 
94
94
  if (vp) {
@@ -97,13 +97,13 @@ globalThis.show_viewport_demo = function(): void {
97
97
  } else {
98
98
  editor.setStatus("No viewport info available");
99
99
  }
100
- };
100
+ }
101
+ registerHandler("show_viewport_demo", show_viewport_demo);
101
102
 
102
103
  editor.registerCommand(
103
104
  "Query Demo: Show Viewport Info",
104
105
  "Display viewport dimensions and scroll position",
105
- "show_viewport_demo",
106
- "normal"
106
+ "show_viewport_demo"
107
107
  );
108
108
 
109
109
  editor.setStatus("Buffer Query Demo plugin loaded! Try the 'Query Demo' commands.");
@@ -10,7 +10,7 @@
10
10
  */
11
11
 
12
12
  // Global action: Display buffer information
13
- globalThis.show_buffer_info = function (): void {
13
+ function show_buffer_info() : void {
14
14
  const bufferId = editor.getActiveBufferId();
15
15
  const path = editor.getBufferPath(bufferId);
16
16
  const length = editor.getBufferLength(bufferId);
@@ -23,10 +23,11 @@ globalThis.show_buffer_info = function (): void {
23
23
 
24
24
  editor.setStatus(status);
25
25
  editor.debug(`Buffer info: ${status}`);
26
- };
26
+ }
27
+ registerHandler("show_buffer_info", show_buffer_info);
27
28
 
28
29
  // Global action: Insert timestamp at cursor
29
- globalThis.insert_timestamp = function (): void {
30
+ function insert_timestamp() : void {
30
31
  const bufferId = editor.getActiveBufferId();
31
32
  const cursorPos = editor.getCursorPosition();
32
33
  const timestamp = new Date().toISOString();
@@ -37,10 +38,11 @@ globalThis.insert_timestamp = function (): void {
37
38
  } else {
38
39
  editor.setStatus("Failed to insert timestamp");
39
40
  }
40
- };
41
+ }
42
+ registerHandler("insert_timestamp", insert_timestamp);
41
43
 
42
44
  // Global action: Highlight current line (demo overlay)
43
- globalThis.highlight_region = function (): void {
45
+ function highlight_region() : void {
44
46
  const bufferId = editor.getActiveBufferId();
45
47
  const cursorPos = editor.getCursorPosition();
46
48
 
@@ -56,20 +58,22 @@ globalThis.highlight_region = function (): void {
56
58
  if (success) {
57
59
  editor.setStatus(`Highlighted region ${start}-${end}`);
58
60
  }
59
- };
61
+ }
62
+ registerHandler("highlight_region", highlight_region);
60
63
 
61
64
  // Global action: Remove highlight
62
- globalThis.clear_highlight = function (): void {
65
+ function clear_highlight() : void {
63
66
  const bufferId = editor.getActiveBufferId();
64
67
  // Clear all overlays in the "demo" namespace
65
68
  const success = editor.clearNamespace(bufferId, "demo");
66
69
  if (success) {
67
70
  editor.setStatus("Cleared highlight");
68
71
  }
69
- };
72
+ }
73
+ registerHandler("clear_highlight", clear_highlight);
70
74
 
71
75
  // Global async action: Demonstrate async/await
72
- globalThis.async_demo = async function (): Promise<void> {
76
+ async function async_demo() : Promise<void> {
73
77
  editor.setStatus("Starting async operation...");
74
78
 
75
79
  // Simulate some async work
@@ -79,7 +83,39 @@ globalThis.async_demo = async function (): Promise<void> {
79
83
  const length = editor.getBufferLength(bufferId);
80
84
 
81
85
  editor.setStatus(`Async operation complete! Buffer has ${length} bytes`);
82
- };
86
+ }
87
+ registerHandler("async_demo", async_demo);
88
+
89
+ // Register commands so they appear in the command palette (Ctrl+P)
90
+ editor.registerCommand(
91
+ "Hello: Show Buffer Info",
92
+ "Display active buffer information",
93
+ "show_buffer_info"
94
+ );
95
+
96
+ editor.registerCommand(
97
+ "Hello: Insert Timestamp",
98
+ "Insert an ISO timestamp at the cursor",
99
+ "insert_timestamp"
100
+ );
101
+
102
+ editor.registerCommand(
103
+ "Hello: Highlight Region",
104
+ "Highlight 10 characters around cursor",
105
+ "highlight_region"
106
+ );
107
+
108
+ editor.registerCommand(
109
+ "Hello: Clear Highlight",
110
+ "Remove demo highlights",
111
+ "clear_highlight"
112
+ );
113
+
114
+ editor.registerCommand(
115
+ "Hello: Async Demo",
116
+ "Demonstrate async/await",
117
+ "async_demo"
118
+ );
83
119
 
84
120
  // Log that plugin loaded
85
121
  editor.debug("Hello World plugin loaded!");
@@ -5,8 +5,7 @@
5
5
  editor.registerCommand(
6
6
  "Virtual Buffer Demo",
7
7
  "Show a demo virtual buffer with sample diagnostics",
8
- "show_virtual_buffer_demo",
9
- "normal"
8
+ "show_virtual_buffer_demo"
10
9
  );
11
10
 
12
11
  // Define a custom mode for the demo buffer
@@ -23,7 +22,7 @@ editor.defineMode(
23
22
  );
24
23
 
25
24
  // Register actions for the mode
26
- globalThis.demo_goto_item = () => {
25
+ function demo_goto_item() {
27
26
  const bufferId = editor.getActiveBufferId();
28
27
  const props = editor.getTextPropertiesAtCursor(bufferId);
29
28
 
@@ -38,22 +37,26 @@ globalThis.demo_goto_item = () => {
38
37
  } else {
39
38
  editor.setStatus("No properties at cursor position");
40
39
  }
41
- };
40
+ }
41
+ registerHandler("demo_goto_item", demo_goto_item);
42
42
 
43
- globalThis.demo_next_item = () => {
43
+ function demo_next_item() {
44
44
  editor.setStatus("Next item (not implemented in demo)");
45
- };
45
+ }
46
+ registerHandler("demo_next_item", demo_next_item);
46
47
 
47
- globalThis.demo_prev_item = () => {
48
+ function demo_prev_item() {
48
49
  editor.setStatus("Previous item (not implemented in demo)");
49
- };
50
+ }
51
+ registerHandler("demo_prev_item", demo_prev_item);
50
52
 
51
- globalThis.demo_close_buffer = () => {
53
+ function demo_close_buffer() {
52
54
  editor.setStatus("Close buffer (not implemented in demo)");
53
- };
55
+ }
56
+ registerHandler("demo_close_buffer", demo_close_buffer);
54
57
 
55
58
  // Main action: show the virtual buffer
56
- globalThis.show_virtual_buffer_demo = async () => {
59
+ async function show_virtual_buffer_demo() {
57
60
  editor.setStatus("Creating virtual buffer demo...");
58
61
 
59
62
  // Create sample diagnostic entries
@@ -110,7 +113,8 @@ globalThis.show_virtual_buffer_demo = async () => {
110
113
  const errorMessage = error instanceof Error ? error.message : String(error);
111
114
  editor.setStatus(`Failed to create virtual buffer: ${errorMessage}`);
112
115
  }
113
- };
116
+ }
117
+ registerHandler("show_virtual_buffer_demo", show_virtual_buffer_demo);
114
118
 
115
119
  // Log that the plugin loaded
116
120
  editor.debug("Virtual buffer demo plugin loaded");
@@ -62,7 +62,7 @@ async function loadLineContent(
62
62
  } else {
63
63
  try {
64
64
  const content = await editor.readFile(ref.file);
65
- lines = content.split("\n");
65
+ lines = content ? content.split("\n") : [];
66
66
  } catch {
67
67
  lines = [];
68
68
  }
@@ -80,7 +80,7 @@ async function loadLineContent(
80
80
  }
81
81
 
82
82
  // Handle lsp_references hook
83
- globalThis.on_lsp_references = async function (data: {
83
+ async function on_lsp_references(data: {
84
84
  symbol: string;
85
85
  locations: ReferenceLocation[];
86
86
  }): Promise<void> {
@@ -104,14 +104,16 @@ globalThis.on_lsp_references = async function (data: {
104
104
  load: async () => pendingRefs,
105
105
  },
106
106
  });
107
- };
107
+ }
108
+ registerHandler("on_lsp_references", on_lsp_references);
108
109
 
109
110
  // Register the hook handler
110
111
  editor.on("lsp_references", "on_lsp_references");
111
112
 
112
113
  // Close function for command palette
113
- globalThis.close_references = function (): void {
114
+ function close_references() : void {
114
115
  finder.close();
115
- };
116
+ }
117
+ registerHandler("close_references", close_references);
116
118
 
117
119
  editor.debug("Find References plugin loaded (using Finder abstraction)");
@@ -253,7 +253,7 @@ async function fetchFileContent(filePath: string, commit: string | null): Promis
253
253
 
254
254
  // Get current file content using editor API (cross-platform)
255
255
  try {
256
- return await editor.readFile(filePath);
256
+ return await editor.readFile(filePath) ?? "";
257
257
  } catch {
258
258
  return "";
259
259
  }
@@ -404,7 +404,7 @@ function addBlameHeaders(): void {
404
404
  /**
405
405
  * Show git blame for the current file
406
406
  */
407
- globalThis.show_git_blame = async function(): Promise<void> {
407
+ async function show_git_blame() : Promise<void> {
408
408
  if (blameState.isOpen) {
409
409
  editor.setStatus(editor.t("status.already_open"));
410
410
  return;
@@ -502,7 +502,8 @@ globalThis.show_git_blame = async function(): Promise<void> {
502
502
  resetState();
503
503
  editor.setStatus(editor.t("status.failed_open"));
504
504
  }
505
- };
505
+ }
506
+ registerHandler("show_git_blame", show_git_blame);
506
507
 
507
508
  /**
508
509
  * Reset blame state
@@ -521,7 +522,7 @@ function resetState(): void {
521
522
  /**
522
523
  * Close the git blame view
523
524
  */
524
- globalThis.git_blame_close = function(): void {
525
+ function git_blame_close() : void {
525
526
  if (!blameState.isOpen) {
526
527
  return;
527
528
  }
@@ -541,7 +542,8 @@ globalThis.git_blame_close = function(): void {
541
542
  resetState();
542
543
 
543
544
  editor.setStatus(editor.t("status.closed"));
544
- };
545
+ }
546
+ registerHandler("git_blame_close", git_blame_close);
545
547
 
546
548
  /**
547
549
  * Get the commit hash at the current cursor position
@@ -564,7 +566,7 @@ function getCommitAtCursor(): string | null {
564
566
  /**
565
567
  * Navigate to blame at the parent commit of the current line's commit
566
568
  */
567
- globalThis.git_blame_go_back = async function(): Promise<void> {
569
+ async function git_blame_go_back() : Promise<void> {
568
570
  if (!blameState.isOpen || !blameState.sourceFilePath) {
569
571
  return;
570
572
  }
@@ -644,12 +646,13 @@ globalThis.git_blame_go_back = async function(): Promise<void> {
644
646
 
645
647
  const depth = blameState.commitStack.length;
646
648
  editor.setStatus(editor.t("status.blame_at_parent", { hash: currentHash.slice(0, 7), depth: String(depth) }));
647
- };
649
+ }
650
+ registerHandler("git_blame_go_back", git_blame_go_back);
648
651
 
649
652
  /**
650
653
  * Copy the commit hash at cursor to clipboard
651
654
  */
652
- globalThis.git_blame_copy_hash = function(): void {
655
+ function git_blame_copy_hash() : void {
653
656
  if (!blameState.isOpen) return;
654
657
 
655
658
  const hash = getCommitAtCursor();
@@ -667,7 +670,8 @@ globalThis.git_blame_copy_hash = function(): void {
667
670
  // Copy hash to clipboard
668
671
  editor.copyToClipboard(hash);
669
672
  editor.setStatus(editor.t("status.hash_copied", { short: hash.slice(0, 7), full: hash }));
670
- };
673
+ }
674
+ registerHandler("git_blame_copy_hash", git_blame_copy_hash);
671
675
 
672
676
  // =============================================================================
673
677
  // Command Registration
@@ -141,17 +141,20 @@ async function refreshGitExplorerDecorations() {
141
141
  }
142
142
  }
143
143
 
144
- globalThis.onGitExplorerAfterFileOpen = () => {
144
+ function onGitExplorerAfterFileOpen() {
145
145
  refreshGitExplorerDecorations();
146
- };
146
+ }
147
+ registerHandler("onGitExplorerAfterFileOpen", onGitExplorerAfterFileOpen);
147
148
 
148
- globalThis.onGitExplorerAfterFileSave = () => {
149
+ function onGitExplorerAfterFileSave() {
149
150
  refreshGitExplorerDecorations();
150
- };
151
+ }
152
+ registerHandler("onGitExplorerAfterFileSave", onGitExplorerAfterFileSave);
151
153
 
152
- globalThis.onGitExplorerEditorInitialized = () => {
154
+ function onGitExplorerEditorInitialized() {
153
155
  refreshGitExplorerDecorations();
154
- };
156
+ }
157
+ registerHandler("onGitExplorerEditorInitialized", onGitExplorerEditorInitialized);
155
158
 
156
159
  editor.on("after_file_open", "onGitExplorerAfterFileOpen");
157
160
  editor.on("after_file_save", "onGitExplorerAfterFileSave");
@@ -39,7 +39,7 @@ async function loadGitFiles(): Promise<string[]> {
39
39
  }
40
40
 
41
41
  // Global function to start file finder
42
- globalThis.start_git_find_file = function (): void {
42
+ function start_git_find_file() : void {
43
43
  finder.prompt({
44
44
  title: editor.t("prompt.find_file"),
45
45
  source: {
@@ -48,14 +48,16 @@ globalThis.start_git_find_file = function (): void {
48
48
  // Uses built-in fuzzy filter by default
49
49
  },
50
50
  });
51
- };
51
+ }
52
+ registerHandler("start_git_find_file", start_git_find_file);
52
53
 
53
54
  // Reload git files command
54
- globalThis.git_reload_files = async function (): Promise<void> {
55
+ async function git_reload_files() : Promise<void> {
55
56
  // Just re-trigger the prompt which will reload
56
- globalThis.start_git_find_file();
57
+ start_git_find_file();
57
58
  editor.setStatus(editor.t("status.reloading"));
58
- };
59
+ }
60
+ registerHandler("git_reload_files", git_reload_files);
59
61
 
60
62
  // Register commands
61
63
  editor.registerCommand(
@@ -54,7 +54,7 @@ async function searchWithGitGrep(query: string): Promise<GrepMatch[]> {
54
54
  }
55
55
 
56
56
  // Global function to start git grep
57
- globalThis.start_git_grep = function (): void {
57
+ function start_git_grep() : void {
58
58
  finder.prompt({
59
59
  title: editor.t("prompt.grep"),
60
60
  source: {
@@ -64,7 +64,8 @@ globalThis.start_git_grep = function (): void {
64
64
  minQueryLength: 1,
65
65
  },
66
66
  });
67
- };
67
+ }
68
+ registerHandler("start_git_grep", start_git_grep);
68
69
 
69
70
  // Register command
70
71
  editor.registerCommand("%cmd.grep", "%cmd.grep_desc", "start_git_grep", null);