@fresh-editor/fresh-editor 0.2.11 → 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 +89 -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 +70 -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 +141 -16
  33. package/plugins/live_grep.ts +3 -2
  34. package/plugins/markdown_compose.ts +33 -23
  35. package/plugins/markdown_source.ts +24 -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
@@ -33,9 +33,11 @@
33
33
  "line_numbers": true,
34
34
  "relative_line_numbers": false,
35
35
  "line_wrap": true,
36
+ "wrap_indent": true,
36
37
  "syntax_highlighting": true,
37
38
  "show_menu_bar": true,
38
39
  "show_tab_bar": true,
40
+ "show_status_bar": true,
39
41
  "show_vertical_scrollbar": true,
40
42
  "show_horizontal_scrollbar": false,
41
43
  "use_terminal_bg": false,
@@ -50,6 +52,8 @@
50
52
  "whitespace_tabs_trailing": true,
51
53
  "tab_size": 4,
52
54
  "auto_indent": true,
55
+ "auto_close": true,
56
+ "auto_surround": true,
53
57
  "scroll_offset": 3,
54
58
  "default_line_ending": "lf",
55
59
  "trim_trailing_whitespace_on_save": false,
@@ -57,11 +61,12 @@
57
61
  "highlight_matching_brackets": true,
58
62
  "rainbow_brackets": true,
59
63
  "quick_suggestions": true,
60
- "quick_suggestions_delay_ms": 10,
64
+ "quick_suggestions_delay_ms": 150,
61
65
  "suggest_on_trigger_characters": true,
62
66
  "accept_suggestion_on_enter": "on",
63
67
  "enable_inlay_hints": true,
64
68
  "enable_semantic_tokens_full": false,
69
+ "diagnostics_inline_text": false,
65
70
  "mouse_hover_enabled": true,
66
71
  "mouse_hover_delay_ms": 500,
67
72
  "double_click_time_ms": 500,
@@ -233,6 +238,12 @@
233
238
  "default": true,
234
239
  "x-section": "Display"
235
240
  },
241
+ "wrap_indent": {
242
+ "description": "Indent wrapped continuation lines to match the leading whitespace of the original line",
243
+ "type": "boolean",
244
+ "default": true,
245
+ "x-section": "Display"
246
+ },
236
247
  "syntax_highlighting": {
237
248
  "description": "Enable syntax highlighting for code files",
238
249
  "type": "boolean",
@@ -251,6 +262,12 @@
251
262
  "default": true,
252
263
  "x-section": "Display"
253
264
  },
265
+ "show_status_bar": {
266
+ "description": "Whether the status bar is visible by default.\nThe status bar shows file info, cursor position, and editor status at the bottom of the screen.\nCan be toggled at runtime via command palette or keybinding.\nDefault: true",
267
+ "type": "boolean",
268
+ "default": true,
269
+ "x-section": "Display"
270
+ },
254
271
  "show_vertical_scrollbar": {
255
272
  "description": "Whether the vertical scrollbar is visible in each split pane.\nCan be toggled at runtime via command palette or keybinding.\nDefault: true",
256
273
  "type": "boolean",
@@ -342,6 +359,18 @@
342
359
  "default": true,
343
360
  "x-section": "Editing"
344
361
  },
362
+ "auto_close": {
363
+ "description": "Automatically close brackets, parentheses, and quotes when typing.\nWhen enabled, typing an opening delimiter like `(`, `[`, `{`, `\"`, `'`, or `` ` ``\nwill automatically insert the matching closing delimiter.\nAlso enables skip-over (moving past existing closing delimiters) and\npair deletion (deleting both delimiters when backspacing between them).\nDefault: true",
364
+ "type": "boolean",
365
+ "default": true,
366
+ "x-section": "Editing"
367
+ },
368
+ "auto_surround": {
369
+ "description": "Automatically surround selected text with matching pairs when typing\nan opening delimiter. When enabled and text is selected, typing `(`, `[`,\n`{`, `\"`, `'`, or `` ` `` wraps the selection instead of replacing it.\nDefault: true",
370
+ "type": "boolean",
371
+ "default": true,
372
+ "x-section": "Editing"
373
+ },
345
374
  "scroll_offset": {
346
375
  "description": "Minimum lines to keep visible above/below cursor when scrolling",
347
376
  "type": "integer",
@@ -387,11 +416,11 @@
387
416
  "x-section": "Completion"
388
417
  },
389
418
  "quick_suggestions_delay_ms": {
390
- "description": "Delay in milliseconds before showing completion suggestions.\nLower values (10-50ms) feel more responsive but may be distracting.\nHigher values (100-500ms) reduce noise while typing.\nTrigger characters (like `.`) bypass this delay.\nDefault: 10 (matches VS Code)",
419
+ "description": "Delay in milliseconds before showing completion suggestions.\nLower values (10-50ms) feel more responsive but may be distracting.\nHigher values (100-500ms) reduce noise while typing.\nTrigger characters (like `.`) bypass this delay.\nDefault: 150",
391
420
  "type": "integer",
392
421
  "format": "uint64",
393
422
  "minimum": 0,
394
- "default": 10,
423
+ "default": 150,
395
424
  "x-section": "Completion"
396
425
  },
397
426
  "suggest_on_trigger_characters": {
@@ -418,6 +447,12 @@
418
447
  "default": false,
419
448
  "x-section": "LSP"
420
449
  },
450
+ "diagnostics_inline_text": {
451
+ "description": "Whether to show inline diagnostic text at the end of lines with errors/warnings.\nWhen enabled, the highest-severity diagnostic message is rendered after the\nsource code on each affected line.\nDefault: false",
452
+ "type": "boolean",
453
+ "default": false,
454
+ "x-section": "Diagnostics"
455
+ },
421
456
  "mouse_hover_enabled": {
422
457
  "description": "Whether mouse hover triggers LSP hover requests.\nWhen enabled, hovering over code with the mouse will show documentation.\nDefault: true",
423
458
  "type": "boolean",
@@ -802,6 +837,22 @@
802
837
  "type": "boolean",
803
838
  "default": true
804
839
  },
840
+ "auto_close": {
841
+ "description": "Whether to auto-close brackets, parentheses, and quotes for this language.\nIf not specified (`null`), falls back to the global `editor.auto_close` setting.",
842
+ "type": [
843
+ "boolean",
844
+ "null"
845
+ ],
846
+ "default": null
847
+ },
848
+ "auto_surround": {
849
+ "description": "Whether to auto-surround selected text with matching pairs for this language.\nIf not specified (`null`), falls back to the global `editor.auto_surround` setting.",
850
+ "type": [
851
+ "boolean",
852
+ "null"
853
+ ],
854
+ "default": null
855
+ },
805
856
  "highlighter": {
806
857
  "description": "Preferred highlighter backend (auto, tree-sitter, or textmate)",
807
858
  "$ref": "#/$defs/HighlighterPreference",
@@ -1003,6 +1054,22 @@
1003
1054
  "initialization_options": {
1004
1055
  "description": "Custom initialization options to send to the server\nThese are passed in the `initializationOptions` field of the LSP Initialize request",
1005
1056
  "default": null
1057
+ },
1058
+ "env": {
1059
+ "description": "Environment variables to set for the LSP server process.\nThese are added to (or override) the inherited parent environment.",
1060
+ "type": "object",
1061
+ "additionalProperties": {
1062
+ "type": "string"
1063
+ },
1064
+ "default": {}
1065
+ },
1066
+ "language_id_overrides": {
1067
+ "description": "Override the LSP languageId sent in textDocument/didOpen based on file extension.\nMaps file extension (without dot) to LSP language ID string.\nFor example: `{\"tsx\": \"typescriptreact\", \"jsx\": \"javascriptreact\"}`",
1068
+ "type": "object",
1069
+ "additionalProperties": {
1070
+ "type": "string"
1071
+ },
1072
+ "default": {}
1006
1073
  }
1007
1074
  },
1008
1075
  "x-display-field": "/command"
@@ -169,7 +169,7 @@ async function restoreProject(projectPath: string): Promise<void> {
169
169
  /**
170
170
  * Handle file open - set project root and restore packages
171
171
  */
172
- globalThis.on_csharp_file_open = async function (data: AfterFileOpenData): Promise<void> {
172
+ async function on_csharp_file_open(data: AfterFileOpenData) : Promise<void> {
173
173
  // Only handle .cs files
174
174
  if (!data.path.endsWith(".cs")) {
175
175
  return;
@@ -206,7 +206,8 @@ globalThis.on_csharp_file_open = async function (data: AfterFileOpenData): Promi
206
206
  await restoreProject(dir);
207
207
  }
208
208
  }
209
- };
209
+ }
210
+ registerHandler("on_csharp_file_open", on_csharp_file_open);
210
211
 
211
212
  // Register hook for file open
212
213
  editor.on("after_file_open", "on_csharp_file_open");
@@ -214,7 +215,7 @@ editor.on("after_file_open", "on_csharp_file_open");
214
215
  /**
215
216
  * Handle LSP server requests from C# language servers (Roslyn-based)
216
217
  */
217
- globalThis.on_csharp_lsp_server_request = function (data: LspServerRequestData): void {
218
+ function on_csharp_lsp_server_request(data: LspServerRequestData) : void {
218
219
  // Only handle requests from C# language servers
219
220
  if (data.server_command !== "csharp-ls" && data.server_command !== "csharp-language-server") {
220
221
  return;
@@ -242,7 +243,8 @@ globalThis.on_csharp_lsp_server_request = function (data: LspServerRequestData):
242
243
  // Log unhandled requests for debugging
243
244
  editor.debug(`csharp_support: Unhandled LSP request: ${data.method}`);
244
245
  }
245
- };
246
+ }
247
+ registerHandler("on_csharp_lsp_server_request", on_csharp_lsp_server_request);
246
248
 
247
249
  // Register hook for LSP server requests
248
250
  editor.on("lsp_server_request", "on_csharp_lsp_server_request");
@@ -250,7 +252,7 @@ editor.on("lsp_server_request", "on_csharp_lsp_server_request");
250
252
  /**
251
253
  * Handle LSP server errors for C#
252
254
  */
253
- globalThis.on_csharp_lsp_server_error = function (data: LspServerErrorData): void {
255
+ function on_csharp_lsp_server_error(data: LspServerErrorData) : void {
254
256
  // Only handle C# language errors
255
257
  if (data.language !== "csharp") {
256
258
  return;
@@ -272,7 +274,8 @@ globalThis.on_csharp_lsp_server_error = function (data: LspServerErrorData): voi
272
274
  } else {
273
275
  editor.setStatus(`C# LSP error: ${data.message}`);
274
276
  }
275
- };
277
+ }
278
+ registerHandler("on_csharp_lsp_server_error", on_csharp_lsp_server_error);
276
279
 
277
280
  // Register hook for LSP server errors
278
281
  editor.on("lsp_server_error", "on_csharp_lsp_server_error");
@@ -280,7 +283,7 @@ editor.on("lsp_server_error", "on_csharp_lsp_server_error");
280
283
  /**
281
284
  * Handle status bar click when there's a C# LSP error
282
285
  */
283
- globalThis.on_csharp_lsp_status_clicked = function (data: LspStatusClickedData): void {
286
+ function on_csharp_lsp_status_clicked(data: LspStatusClickedData) : void {
284
287
  // Only handle C# language clicks when there's an error
285
288
  if (data.language !== "csharp" || !csharpLspError) {
286
289
  return;
@@ -299,7 +302,8 @@ globalThis.on_csharp_lsp_status_clicked = function (data: LspStatusClickedData):
299
302
  { id: "dismiss", label: "Dismiss (ESC)" },
300
303
  ],
301
304
  });
302
- };
305
+ }
306
+ registerHandler("on_csharp_lsp_status_clicked", on_csharp_lsp_status_clicked);
303
307
 
304
308
  // Register hook for status bar clicks
305
309
  editor.on("lsp_status_clicked", "on_csharp_lsp_status_clicked");
@@ -307,7 +311,7 @@ editor.on("lsp_status_clicked", "on_csharp_lsp_status_clicked");
307
311
  /**
308
312
  * Handle action popup results for C# LSP help
309
313
  */
310
- globalThis.on_csharp_lsp_action_result = function (data: ActionPopupResultData): void {
314
+ function on_csharp_lsp_action_result(data: ActionPopupResultData) : void {
311
315
  // Only handle our popup
312
316
  if (data.popup_id !== "csharp-lsp-help") {
313
317
  return;
@@ -335,7 +339,8 @@ globalThis.on_csharp_lsp_action_result = function (data: ActionPopupResultData):
335
339
  default:
336
340
  editor.debug(`csharp_support: Unknown action: ${data.action_id}`);
337
341
  }
338
- };
342
+ }
343
+ registerHandler("on_csharp_lsp_action_result", on_csharp_lsp_action_result);
339
344
 
340
345
  // Register hook for action popup results
341
346
  editor.on("action_popup_result", "on_csharp_lsp_action_result");
@@ -46,7 +46,7 @@ let cssLspError: { serverCommand: string; message: string } | null = null;
46
46
  /**
47
47
  * Handle LSP server errors for CSS
48
48
  */
49
- globalThis.on_css_lsp_server_error = function (data: LspServerErrorData): void {
49
+ function on_css_lsp_server_error(data: LspServerErrorData) : void {
50
50
  // Only handle CSS language errors
51
51
  if (data.language !== "css") {
52
52
  return;
@@ -68,7 +68,8 @@ globalThis.on_css_lsp_server_error = function (data: LspServerErrorData): void {
68
68
  } else {
69
69
  editor.setStatus(`CSS LSP error: ${data.message}`);
70
70
  }
71
- };
71
+ }
72
+ registerHandler("on_css_lsp_server_error", on_css_lsp_server_error);
72
73
 
73
74
  // Register hook for LSP server errors
74
75
  editor.on("lsp_server_error", "on_css_lsp_server_error");
@@ -76,7 +77,7 @@ editor.on("lsp_server_error", "on_css_lsp_server_error");
76
77
  /**
77
78
  * Handle status bar click when there's a CSS LSP error
78
79
  */
79
- globalThis.on_css_lsp_status_clicked = function (
80
+ function on_css_lsp_status_clicked(
80
81
  data: LspStatusClickedData
81
82
  ): void {
82
83
  // Only handle CSS language clicks when there's an error
@@ -97,7 +98,8 @@ globalThis.on_css_lsp_status_clicked = function (
97
98
  { id: "dismiss", label: "Dismiss (ESC)" },
98
99
  ],
99
100
  });
100
- };
101
+ }
102
+ registerHandler("on_css_lsp_status_clicked", on_css_lsp_status_clicked);
101
103
 
102
104
  // Register hook for status bar clicks
103
105
  editor.on("lsp_status_clicked", "on_css_lsp_status_clicked");
@@ -105,7 +107,7 @@ editor.on("lsp_status_clicked", "on_css_lsp_status_clicked");
105
107
  /**
106
108
  * Handle action popup results for CSS LSP help
107
109
  */
108
- globalThis.on_css_lsp_action_result = function (
110
+ function on_css_lsp_action_result(
109
111
  data: ActionPopupResultData
110
112
  ): void {
111
113
  // Only handle our popup
@@ -135,7 +137,8 @@ globalThis.on_css_lsp_action_result = function (
135
137
  default:
136
138
  editor.debug(`css-lsp: Unknown action: ${data.action_id}`);
137
139
  }
138
- };
140
+ }
141
+ registerHandler("on_css_lsp_action_result", on_css_lsp_action_result);
139
142
 
140
143
  // Register hook for action popup results
141
144
  editor.on("action_popup_result", "on_css_lsp_action_result");
@@ -92,7 +92,7 @@ function getDiagnostics(): DiagnosticItem[] {
92
92
  const lineDiff = a.range.start.line - b.range.start.line;
93
93
  if (lineDiff !== 0) return lineDiff;
94
94
  // Severity comparison
95
- return a.severity - b.severity;
95
+ return (a.severity ?? 4) - (b.severity ?? 4);
96
96
  });
97
97
 
98
98
  // Convert to DiagnosticItem
@@ -102,7 +102,7 @@ function getDiagnostics(): DiagnosticItem[] {
102
102
  line: diag.range.start.line + 1,
103
103
  column: diag.range.start.character + 1,
104
104
  message: diag.message.split("\n")[0], // First line only
105
- severity: diag.severity,
105
+ severity: diag.severity ?? 4,
106
106
  source: diag.source ?? undefined,
107
107
  }));
108
108
  }
@@ -137,7 +137,7 @@ function getTitle(): string {
137
137
  }
138
138
 
139
139
  // Commands
140
- globalThis.show_diagnostics_panel = async function (): Promise<void> {
140
+ async function show_diagnostics_panel() : Promise<void> {
141
141
  if (isOpen) {
142
142
  // Already open - just notify to refresh
143
143
  provider.notify();
@@ -161,16 +161,18 @@ globalThis.show_diagnostics_panel = async function (): Promise<void> {
161
161
  editor.setStatus(
162
162
  editor.t("status.diagnostics_count", { count: String(diagnostics.length) })
163
163
  );
164
- };
164
+ }
165
+ registerHandler("show_diagnostics_panel", show_diagnostics_panel);
165
166
 
166
- globalThis.diagnostics_close = function (): void {
167
+ function diagnostics_close() : void {
167
168
  finder.close();
168
169
  isOpen = false;
169
170
  sourceBufferId = null;
170
171
  editor.setStatus(editor.t("status.closed"));
171
- };
172
+ }
173
+ registerHandler("diagnostics_close", diagnostics_close);
172
174
 
173
- globalThis.diagnostics_toggle_all = function (): void {
175
+ function diagnostics_toggle_all() : void {
174
176
  if (!isOpen) return;
175
177
 
176
178
  showAllFiles = !showAllFiles;
@@ -183,37 +185,41 @@ globalThis.diagnostics_toggle_all = function (): void {
183
185
  ? editor.t("panel.all_files")
184
186
  : editor.t("panel.current_file");
185
187
  editor.setStatus(editor.t("status.showing", { label }));
186
- };
188
+ }
189
+ registerHandler("diagnostics_toggle_all", diagnostics_toggle_all);
187
190
 
188
- globalThis.diagnostics_refresh = function (): void {
191
+ function diagnostics_refresh() : void {
189
192
  if (!isOpen) return;
190
193
 
191
194
  provider.notify();
192
195
  editor.setStatus(editor.t("status.refreshed"));
193
- };
196
+ }
197
+ registerHandler("diagnostics_refresh", diagnostics_refresh);
194
198
 
195
- globalThis.toggle_diagnostics_panel = function (): void {
199
+ function toggle_diagnostics_panel() : void {
196
200
  if (isOpen) {
197
- globalThis.diagnostics_close();
201
+ diagnostics_close();
198
202
  } else {
199
- globalThis.show_diagnostics_panel();
203
+ show_diagnostics_panel();
200
204
  }
201
- };
205
+ }
206
+ registerHandler("toggle_diagnostics_panel", toggle_diagnostics_panel);
202
207
 
203
208
  // Event Handlers
204
209
 
205
210
  // When diagnostics update, notify the provider
206
- globalThis.on_diagnostics_updated = function (_data: {
211
+ function on_diagnostics_updated(_data: {
207
212
  uri: string;
208
213
  count: number;
209
214
  }): void {
210
215
  if (isOpen) {
211
216
  provider.notify();
212
217
  }
213
- };
218
+ }
219
+ registerHandler("on_diagnostics_updated", on_diagnostics_updated);
214
220
 
215
221
  // When a different buffer becomes active, update filter context
216
- globalThis.on_diagnostics_buffer_activated = function (data: {
222
+ function on_diagnostics_buffer_activated(data: {
217
223
  buffer_id: number;
218
224
  }): void {
219
225
  if (!isOpen) return;
@@ -231,7 +237,8 @@ globalThis.on_diagnostics_buffer_activated = function (data: {
231
237
  provider.notify();
232
238
  finder.updateTitle(getTitle());
233
239
  }
234
- };
240
+ }
241
+ registerHandler("on_diagnostics_buffer_activated", on_diagnostics_buffer_activated);
235
242
 
236
243
  // Register event handlers
237
244
  editor.on("diagnostics_updated", "on_diagnostics_updated");
@@ -71,8 +71,7 @@ globalThis.my_command = function(): void {
71
71
  editor.registerCommand(
72
72
  "My Custom Command",
73
73
  "Does something cool",
74
- "my_command",
75
- "normal"
74
+ "my_command"
76
75
  );
77
76
 
78
77
  // Initialization message
@@ -6,7 +6,7 @@
6
6
  */
7
7
 
8
8
  // Git status
9
- globalThis.async_git_status = async function(): Promise<void> {
9
+ async function async_git_status() : Promise<void> {
10
10
  editor.setStatus("Running git status...");
11
11
 
12
12
  try {
@@ -24,17 +24,17 @@ globalThis.async_git_status = async function(): Promise<void> {
24
24
  } catch (e) {
25
25
  editor.setStatus(`Git status error: ${e}`);
26
26
  }
27
- };
27
+ }
28
+ registerHandler("async_git_status", async_git_status);
28
29
 
29
30
  editor.registerCommand(
30
31
  "Async Demo: Git Status",
31
32
  "Run git status and show output",
32
- "async_git_status",
33
- "normal"
33
+ "async_git_status"
34
34
  );
35
35
 
36
36
  // Current directory
37
- globalThis.async_pwd = async function(): Promise<void> {
37
+ async function async_pwd() : Promise<void> {
38
38
  try {
39
39
  const result = await editor.spawnProcess("pwd");
40
40
  if (result.exit_code === 0) {
@@ -46,17 +46,17 @@ globalThis.async_pwd = async function(): Promise<void> {
46
46
  } catch (e) {
47
47
  editor.setStatus(`pwd error: ${e}`);
48
48
  }
49
- };
49
+ }
50
+ registerHandler("async_pwd", async_pwd);
50
51
 
51
52
  editor.registerCommand(
52
53
  "Async Demo: Current Directory",
53
54
  "Show current directory using pwd",
54
- "async_pwd",
55
- "normal"
55
+ "async_pwd"
56
56
  );
57
57
 
58
58
  // List files
59
- globalThis.async_ls = async function(): Promise<void> {
59
+ async function async_ls() : Promise<void> {
60
60
  editor.setStatus("Listing files...");
61
61
 
62
62
  try {
@@ -70,17 +70,17 @@ globalThis.async_ls = async function(): Promise<void> {
70
70
  } catch (e) {
71
71
  editor.setStatus(`ls error: ${e}`);
72
72
  }
73
- };
73
+ }
74
+ registerHandler("async_ls", async_ls);
74
75
 
75
76
  editor.registerCommand(
76
77
  "Async Demo: List Files",
77
78
  "List files in current directory",
78
- "async_ls",
79
- "normal"
79
+ "async_ls"
80
80
  );
81
81
 
82
82
  // Git branch
83
- globalThis.async_git_branch = async function(): Promise<void> {
83
+ async function async_git_branch() : Promise<void> {
84
84
  try {
85
85
  const result = await editor.spawnProcess("git", ["branch", "--show-current"]);
86
86
  if (result.exit_code === 0) {
@@ -96,34 +96,34 @@ globalThis.async_git_branch = async function(): Promise<void> {
96
96
  } catch (e) {
97
97
  editor.setStatus(`Git branch error: ${e}`);
98
98
  }
99
- };
99
+ }
100
+ registerHandler("async_git_branch", async_git_branch);
100
101
 
101
102
  editor.registerCommand(
102
103
  "Async Demo: Git Branch",
103
104
  "Show current git branch",
104
- "async_git_branch",
105
- "normal"
105
+ "async_git_branch"
106
106
  );
107
107
 
108
108
  // Echo test
109
- globalThis.async_echo = async function(): Promise<void> {
109
+ async function async_echo() : Promise<void> {
110
110
  try {
111
111
  const result = await editor.spawnProcess("echo", ["Hello from async process!"]);
112
112
  editor.setStatus(`Echo output: ${result.stdout.trim()}`);
113
113
  } catch (e) {
114
114
  editor.setStatus(`Echo error: ${e}`);
115
115
  }
116
- };
116
+ }
117
+ registerHandler("async_echo", async_echo);
117
118
 
118
119
  editor.registerCommand(
119
120
  "Async Demo: Echo Test",
120
121
  "Test with simple echo command",
121
- "async_echo",
122
- "normal"
122
+ "async_echo"
123
123
  );
124
124
 
125
125
  // With working directory
126
- globalThis.async_with_cwd = async function(): Promise<void> {
126
+ async function async_with_cwd() : Promise<void> {
127
127
  try {
128
128
  const result = await editor.spawnProcess("pwd", [], "/tmp");
129
129
  const dir = result.stdout.trim();
@@ -131,17 +131,17 @@ globalThis.async_with_cwd = async function(): Promise<void> {
131
131
  } catch (e) {
132
132
  editor.setStatus(`pwd error: ${e}`);
133
133
  }
134
- };
134
+ }
135
+ registerHandler("async_with_cwd", async_with_cwd);
135
136
 
136
137
  editor.registerCommand(
137
138
  "Async Demo: With Working Dir",
138
139
  "Run command in /tmp directory",
139
- "async_with_cwd",
140
- "normal"
140
+ "async_with_cwd"
141
141
  );
142
142
 
143
143
  // Error handling
144
- globalThis.async_error = async function(): Promise<void> {
144
+ async function async_error() : Promise<void> {
145
145
  try {
146
146
  const result = await editor.spawnProcess("this_command_does_not_exist");
147
147
  if (result.exit_code !== 0) {
@@ -152,13 +152,13 @@ globalThis.async_error = async function(): Promise<void> {
152
152
  } catch (e) {
153
153
  editor.setStatus(`Command failed with error: ${e}`);
154
154
  }
155
- };
155
+ }
156
+ registerHandler("async_error", async_error);
156
157
 
157
158
  editor.registerCommand(
158
159
  "Async Demo: Error Handling",
159
160
  "Demonstrate error handling with non-existent command",
160
- "async_error",
161
- "normal"
161
+ "async_error"
162
162
  );
163
163
 
164
164
  editor.setStatus("Async Demo plugin loaded! Try the 'Async Demo' commands.");