@fresh-editor/fresh-editor 0.2.25 → 0.3.1

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 (82) hide show
  1. package/CHANGELOG.md +216 -0
  2. package/README.md +6 -0
  3. package/package.json +1 -1
  4. package/plugins/astro-lsp.ts +6 -12
  5. package/plugins/audit_mode.i18n.json +14 -14
  6. package/plugins/audit_mode.ts +182 -146
  7. package/plugins/bash-lsp.ts +15 -22
  8. package/plugins/clangd-lsp.ts +15 -24
  9. package/plugins/clojure-lsp.ts +9 -12
  10. package/plugins/cmake-lsp.ts +9 -12
  11. package/plugins/code-tour.ts +15 -16
  12. package/plugins/config-schema.json +79 -6
  13. package/plugins/csharp_support.ts +25 -30
  14. package/plugins/css-lsp.ts +15 -22
  15. package/plugins/dart-lsp.ts +9 -12
  16. package/plugins/dashboard.ts +1903 -0
  17. package/plugins/devcontainer.i18n.json +1472 -0
  18. package/plugins/devcontainer.ts +2793 -0
  19. package/plugins/diagnostics_panel.ts +10 -17
  20. package/plugins/elixir-lsp.ts +9 -12
  21. package/plugins/erlang-lsp.ts +9 -12
  22. package/plugins/examples/bookmarks.ts +10 -16
  23. package/plugins/find_references.ts +5 -9
  24. package/plugins/flash.ts +577 -0
  25. package/plugins/fsharp-lsp.ts +9 -12
  26. package/plugins/git_explorer.ts +16 -20
  27. package/plugins/git_gutter.ts +65 -79
  28. package/plugins/git_log.i18n.json +14 -42
  29. package/plugins/git_log.ts +19 -9
  30. package/plugins/gleam-lsp.ts +9 -12
  31. package/plugins/go-lsp.ts +15 -22
  32. package/plugins/graphql-lsp.ts +9 -12
  33. package/plugins/haskell-lsp.ts +9 -12
  34. package/plugins/html-lsp.ts +15 -24
  35. package/plugins/java-lsp.ts +9 -12
  36. package/plugins/json-lsp.ts +15 -24
  37. package/plugins/julia-lsp.ts +9 -12
  38. package/plugins/kotlin-lsp.ts +15 -22
  39. package/plugins/latex-lsp.ts +9 -12
  40. package/plugins/lib/fresh.d.ts +603 -0
  41. package/plugins/lua-lsp.ts +15 -22
  42. package/plugins/markdown_compose.ts +132 -128
  43. package/plugins/markdown_source.ts +8 -10
  44. package/plugins/marksman-lsp.ts +9 -12
  45. package/plugins/merge_conflict.ts +15 -17
  46. package/plugins/nim-lsp.ts +9 -12
  47. package/plugins/nix-lsp.ts +9 -12
  48. package/plugins/nushell-lsp.ts +9 -12
  49. package/plugins/ocaml-lsp.ts +9 -12
  50. package/plugins/odin-lsp.ts +15 -22
  51. package/plugins/path_complete.ts +5 -6
  52. package/plugins/perl-lsp.ts +9 -12
  53. package/plugins/php-lsp.ts +15 -22
  54. package/plugins/pkg.ts +10 -21
  55. package/plugins/protobuf-lsp.ts +9 -12
  56. package/plugins/python-lsp.ts +15 -24
  57. package/plugins/r-lsp.ts +9 -12
  58. package/plugins/ruby-lsp.ts +15 -22
  59. package/plugins/rust-lsp.ts +18 -28
  60. package/plugins/scala-lsp.ts +9 -12
  61. package/plugins/schemas/theme.schema.json +126 -0
  62. package/plugins/search_replace.ts +10 -13
  63. package/plugins/solidity-lsp.ts +9 -12
  64. package/plugins/sql-lsp.ts +9 -12
  65. package/plugins/svelte-lsp.ts +9 -12
  66. package/plugins/swift-lsp.ts +9 -12
  67. package/plugins/tailwindcss-lsp.ts +9 -12
  68. package/plugins/templ-lsp.ts +9 -12
  69. package/plugins/terraform-lsp.ts +9 -12
  70. package/plugins/theme_editor.i18n.json +98 -14
  71. package/plugins/theme_editor.ts +156 -209
  72. package/plugins/toml-lsp.ts +15 -22
  73. package/plugins/tsconfig.json +100 -0
  74. package/plugins/typescript-lsp.ts +15 -24
  75. package/plugins/typst-lsp.ts +15 -22
  76. package/plugins/vi_mode.ts +77 -290
  77. package/plugins/vue-lsp.ts +9 -12
  78. package/plugins/yaml-lsp.ts +15 -22
  79. package/plugins/zig-lsp.ts +9 -12
  80. package/themes/high-contrast.json +2 -2
  81. package/themes/nord.json +4 -0
  82. package/themes/solarized-dark.json +4 -0
@@ -51,9 +51,10 @@ let tsLspError: { serverCommand: string; message: string; language: string } | n
51
51
  /**
52
52
  * Handle LSP server errors for TypeScript/JavaScript
53
53
  */
54
- function on_typescript_lsp_server_error(
55
- data: LspServerErrorData
56
- ): void {
54
+
55
+
56
+ // Register hook for LSP server errors
57
+ editor.on("lsp_server_error", (data) => {
57
58
  // Only handle TypeScript/JavaScript language errors
58
59
  if (!HANDLED_LANGUAGES.includes(data.language)) {
59
60
  return;
@@ -78,18 +79,15 @@ function on_typescript_lsp_server_error(
78
79
  } else {
79
80
  editor.setStatus(`TypeScript LSP error: ${data.message}`);
80
81
  }
81
- }
82
- registerHandler("on_typescript_lsp_server_error", on_typescript_lsp_server_error);
83
-
84
- // Register hook for LSP server errors
85
- editor.on("lsp_server_error", "on_typescript_lsp_server_error");
82
+ });
86
83
 
87
84
  /**
88
85
  * Handle status bar click when there's a TypeScript LSP error
89
86
  */
90
- function on_typescript_lsp_status_clicked(
91
- data: LspStatusClickedData
92
- ): void {
87
+
88
+
89
+ // Register hook for status bar clicks
90
+ editor.on("lsp_status_clicked", (data) => {
93
91
  // Only handle TypeScript/JavaScript language clicks when there's an error
94
92
  if (!HANDLED_LANGUAGES.includes(data.language) || !tsLspError) {
95
93
  return;
@@ -110,18 +108,15 @@ function on_typescript_lsp_status_clicked(
110
108
  { id: "dismiss", label: "Dismiss (ESC)" },
111
109
  ],
112
110
  });
113
- }
114
- registerHandler("on_typescript_lsp_status_clicked", on_typescript_lsp_status_clicked);
115
-
116
- // Register hook for status bar clicks
117
- editor.on("lsp_status_clicked", "on_typescript_lsp_status_clicked");
111
+ });
118
112
 
119
113
  /**
120
114
  * Handle action popup results for TypeScript LSP help
121
115
  */
122
- function on_typescript_lsp_action_result(
123
- data: ActionPopupResultData
124
- ): void {
116
+
117
+
118
+ // Register hook for action popup results
119
+ editor.on("action_popup_result", (data) => {
125
120
  // Only handle our popup
126
121
  if (data.popup_id !== "typescript-lsp-help") {
127
122
  return;
@@ -161,10 +156,6 @@ function on_typescript_lsp_action_result(
161
156
  default:
162
157
  editor.debug(`typescript-lsp: Unknown action: ${data.action_id}`);
163
158
  }
164
- }
165
- registerHandler("on_typescript_lsp_action_result", on_typescript_lsp_action_result);
166
-
167
- // Register hook for action popup results
168
- editor.on("action_popup_result", "on_typescript_lsp_action_result");
159
+ });
169
160
 
170
161
  editor.debug("typescript-lsp: Plugin loaded");
@@ -53,7 +53,10 @@ let typstLspError: { serverCommand: string; message: string } | null = null;
53
53
  /**
54
54
  * Handle LSP server errors for Typst
55
55
  */
56
- function on_typst_lsp_server_error(data: LspServerErrorData): void {
56
+
57
+
58
+ // Register hook for LSP server errors
59
+ editor.on("lsp_server_error", (data) => {
57
60
  // Only handle Typst language errors
58
61
  if (data.language !== "typst") {
59
62
  return;
@@ -75,18 +78,15 @@ function on_typst_lsp_server_error(data: LspServerErrorData): void {
75
78
  } else {
76
79
  editor.setStatus(`Typst LSP error: ${data.message}`);
77
80
  }
78
- }
79
- registerHandler("on_typst_lsp_server_error", on_typst_lsp_server_error);
80
-
81
- // Register hook for LSP server errors
82
- editor.on("lsp_server_error", "on_typst_lsp_server_error");
81
+ });
83
82
 
84
83
  /**
85
84
  * Handle status bar click when there's a Typst LSP error
86
85
  */
87
- function on_typst_lsp_status_clicked(
88
- data: LspStatusClickedData
89
- ): void {
86
+
87
+
88
+ // Register hook for status bar clicks
89
+ editor.on("lsp_status_clicked", (data) => {
90
90
  // Only handle Typst language clicks when there's an error
91
91
  if (data.language !== "typst" || !typstLspError) {
92
92
  return;
@@ -107,18 +107,15 @@ function on_typst_lsp_status_clicked(
107
107
  { id: "dismiss", label: "Dismiss (ESC)" },
108
108
  ],
109
109
  });
110
- }
111
- registerHandler("on_typst_lsp_status_clicked", on_typst_lsp_status_clicked);
112
-
113
- // Register hook for status bar clicks
114
- editor.on("lsp_status_clicked", "on_typst_lsp_status_clicked");
110
+ });
115
111
 
116
112
  /**
117
113
  * Handle action popup results for Typst LSP help
118
114
  */
119
- function on_typst_lsp_action_result(
120
- data: ActionPopupResultData
121
- ): void {
115
+
116
+
117
+ // Register hook for action popup results
118
+ editor.on("action_popup_result", (data) => {
122
119
  // Only handle our popup
123
120
  if (data.popup_id !== "typst-lsp-help") {
124
121
  return;
@@ -156,10 +153,6 @@ function on_typst_lsp_action_result(
156
153
  default:
157
154
  editor.debug(`typst-lsp: Unknown action: ${data.action_id}`);
158
155
  }
159
- }
160
- registerHandler("on_typst_lsp_action_result", on_typst_lsp_action_result);
161
-
162
- // Register hook for action popup results
163
- editor.on("action_popup_result", "on_typst_lsp_action_result");
156
+ });
164
157
 
165
158
  editor.debug("typst-lsp: Plugin loaded");
@@ -586,27 +586,38 @@ function vi_delete_char_before() : void {
586
586
  }
587
587
  registerHandler("vi_delete_char_before", vi_delete_char_before);
588
588
 
589
- function vi_replace_char() : void {
590
- // Enter replace-char mode to read the replacement character
591
- state.mode = "find-char"; // Reuse find-char mode mechanism
589
+ // Replace-char (`r<char>`): wait for one keypress and replace the
590
+ // character(s) under the cursor with it. Uses `editor.getNextKey()`
591
+ // (plugin API #1) same pattern as find-char above.
592
+ async function vi_replace_char(): Promise<void> {
593
+ state.mode = "find-char"; // reuse find-char state slot for status
592
594
  editor.setEditorMode("vi-replace-char");
593
595
  editor.setStatus("-- REPLACE CHAR --");
594
- }
595
- registerHandler("vi_replace_char", vi_replace_char);
596
596
 
597
- // Handler for replacement character input
598
- async function vi_replace_char_handler(char: string): Promise<void> {
597
+ editor.beginKeyCapture();
598
+ let ev;
599
+ try {
600
+ ev = await editor.getNextKey();
601
+ } finally {
602
+ editor.endKeyCapture();
603
+ }
604
+
605
+ // Escape / non-character keys cancel the replacement.
606
+ if (ev.key.length !== 1) {
607
+ switchMode("normal");
608
+ return;
609
+ }
610
+
599
611
  const count = consumeCount();
600
- // Replace character(s) under cursor without moving
601
612
  for (let i = 0; i < count; i++) {
602
613
  editor.executeAction("delete_forward");
603
- editor.insertAtCursor(char);
614
+ editor.insertAtCursor(ev.key);
604
615
  }
605
- // Move cursor back to stay on the replaced char (vim behavior)
616
+ // Move cursor back to stay on the replaced char (vim behavior).
606
617
  editor.executeAction("move_left");
607
618
  switchMode("normal");
608
619
  }
609
- registerHandler("vi_replace_char_handler", vi_replace_char_handler);
620
+ registerHandler("vi_replace_char", vi_replace_char);
610
621
 
611
622
  // Substitute (delete char and enter insert mode)
612
623
  function vi_substitute() : void {
@@ -1442,12 +1453,34 @@ registerHandler("vi_to_cancel", vi_to_cancel);
1442
1453
  // Find Character Motions (f/t/F/T)
1443
1454
  // ============================================================================
1444
1455
 
1445
- // Enter find-char mode waiting for the target character
1446
- function enterFindCharMode(findType: FindCharType): void {
1456
+ // Enter find-char mode, await one keypress, then dispatch.
1457
+ //
1458
+ // Implemented via `editor.getNextKey()` (plugin API #1) — the editor
1459
+ // hands the next keypress to this awaiting handler before any other
1460
+ // dispatch, which means the mode itself does not need any per-key
1461
+ // bindings. Keeps `setEditorMode("vi-find-char")` set across the
1462
+ // await purely for the status-bar indicator.
1463
+ async function enterFindCharMode(findType: FindCharType): Promise<void> {
1447
1464
  state.pendingFindChar = findType;
1448
1465
  state.mode = "find-char";
1449
1466
  editor.setEditorMode("vi-find-char");
1450
1467
  editor.setStatus(getModeIndicator("find-char"));
1468
+
1469
+ // Capture the key losslessly — without this, a user pressing the
1470
+ // target character very quickly after `f`/`t`/`F`/`T` could see the
1471
+ // key fall through to the buffer.
1472
+ editor.beginKeyCapture();
1473
+ try {
1474
+ const ev = await editor.getNextKey();
1475
+ state.pendingFindChar = null;
1476
+ // Escape (or any non-character key) cancels the motion.
1477
+ if (ev.key.length === 1) {
1478
+ await executeFindChar(findType, ev.key);
1479
+ }
1480
+ } finally {
1481
+ editor.endKeyCapture();
1482
+ }
1483
+ switchMode("normal");
1451
1484
  }
1452
1485
 
1453
1486
  // Execute find char motion (async because getBufferText is async)
@@ -1530,36 +1563,17 @@ async function executeFindChar(findType: FindCharType, char: string): Promise<vo
1530
1563
  }
1531
1564
  }
1532
1565
 
1533
- // Handler for when a character is typed in find-char mode (async)
1534
- async function vi_find_char_handler(char: string): Promise<void> {
1535
- if (state.pendingFindChar) {
1536
- await executeFindChar(state.pendingFindChar, char);
1537
- }
1538
- // Return to normal mode
1539
- state.pendingFindChar = null;
1540
- switchMode("normal");
1541
- }
1542
- registerHandler("vi_find_char_handler", vi_find_char_handler);
1543
-
1544
- // Commands to enter find-char mode
1545
- function vi_find_char_f(): void {
1546
- enterFindCharMode("f");
1547
- }
1566
+ // Commands to enter find-char mode (async; await getNextKey internally)
1567
+ async function vi_find_char_f(): Promise<void> { return enterFindCharMode("f"); }
1548
1568
  registerHandler("vi_find_char_f", vi_find_char_f);
1549
1569
 
1550
- function vi_find_char_t(): void {
1551
- enterFindCharMode("t");
1552
- }
1570
+ async function vi_find_char_t(): Promise<void> { return enterFindCharMode("t"); }
1553
1571
  registerHandler("vi_find_char_t", vi_find_char_t);
1554
1572
 
1555
- function vi_find_char_F(): void {
1556
- enterFindCharMode("F");
1557
- }
1573
+ async function vi_find_char_F(): Promise<void> { return enterFindCharMode("F"); }
1558
1574
  registerHandler("vi_find_char_F", vi_find_char_F);
1559
1575
 
1560
- function vi_find_char_T(): void {
1561
- enterFindCharMode("T");
1562
- }
1576
+ async function vi_find_char_T(): Promise<void> { return enterFindCharMode("T"); }
1563
1577
  registerHandler("vi_find_char_T", vi_find_char_T);
1564
1578
 
1565
1579
  // Repeat last find char (async)
@@ -1582,13 +1596,6 @@ async function vi_find_char_repeat_reverse(): Promise<void> {
1582
1596
  }
1583
1597
  registerHandler("vi_find_char_repeat_reverse", vi_find_char_repeat_reverse);
1584
1598
 
1585
- // Cancel find-char mode
1586
- function vi_find_char_cancel(): void {
1587
- state.pendingFindChar = null;
1588
- switchMode("normal");
1589
- }
1590
- registerHandler("vi_find_char_cancel", vi_find_char_cancel);
1591
-
1592
1599
  // ============================================================================
1593
1600
  // Operator-Pending Mode Commands
1594
1601
  // ============================================================================
@@ -1771,229 +1778,10 @@ editor.defineMode("vi-insert", [
1771
1778
  ["C-q", "quit"],
1772
1779
  ], false); // read_only = false to allow normal typing
1773
1780
 
1774
- // Define vi-find-char mode - binds all printable chars to the handler
1775
- // This mode waits for a single character input for f/t/F/T motions
1776
-
1777
- // Explicitly define handlers for each character to ensure they're accessible
1778
- // These return Promises so the runtime can await them
1779
- async function vi_fc_a(): Promise<void> { return vi_find_char_handler("a"); }
1780
- registerHandler("vi_fc_a", vi_fc_a);
1781
- async function vi_fc_b(): Promise<void> { return vi_find_char_handler("b"); }
1782
- registerHandler("vi_fc_b", vi_fc_b);
1783
- async function vi_fc_c(): Promise<void> { return vi_find_char_handler("c"); }
1784
- registerHandler("vi_fc_c", vi_fc_c);
1785
- async function vi_fc_d(): Promise<void> { return vi_find_char_handler("d"); }
1786
- registerHandler("vi_fc_d", vi_fc_d);
1787
- async function vi_fc_e(): Promise<void> { return vi_find_char_handler("e"); }
1788
- registerHandler("vi_fc_e", vi_fc_e);
1789
- async function vi_fc_f(): Promise<void> { return vi_find_char_handler("f"); }
1790
- registerHandler("vi_fc_f", vi_fc_f);
1791
- async function vi_fc_g(): Promise<void> { return vi_find_char_handler("g"); }
1792
- registerHandler("vi_fc_g", vi_fc_g);
1793
- async function vi_fc_h(): Promise<void> { return vi_find_char_handler("h"); }
1794
- registerHandler("vi_fc_h", vi_fc_h);
1795
- async function vi_fc_i(): Promise<void> { return vi_find_char_handler("i"); }
1796
- registerHandler("vi_fc_i", vi_fc_i);
1797
- async function vi_fc_j(): Promise<void> { return vi_find_char_handler("j"); }
1798
- registerHandler("vi_fc_j", vi_fc_j);
1799
- async function vi_fc_k(): Promise<void> { return vi_find_char_handler("k"); }
1800
- registerHandler("vi_fc_k", vi_fc_k);
1801
- async function vi_fc_l(): Promise<void> { return vi_find_char_handler("l"); }
1802
- registerHandler("vi_fc_l", vi_fc_l);
1803
- async function vi_fc_m(): Promise<void> { return vi_find_char_handler("m"); }
1804
- registerHandler("vi_fc_m", vi_fc_m);
1805
- async function vi_fc_n(): Promise<void> { return vi_find_char_handler("n"); }
1806
- registerHandler("vi_fc_n", vi_fc_n);
1807
- async function vi_fc_o(): Promise<void> { return vi_find_char_handler("o"); }
1808
- registerHandler("vi_fc_o", vi_fc_o);
1809
- async function vi_fc_p(): Promise<void> { return vi_find_char_handler("p"); }
1810
- registerHandler("vi_fc_p", vi_fc_p);
1811
- async function vi_fc_q(): Promise<void> { return vi_find_char_handler("q"); }
1812
- registerHandler("vi_fc_q", vi_fc_q);
1813
- async function vi_fc_r(): Promise<void> { return vi_find_char_handler("r"); }
1814
- registerHandler("vi_fc_r", vi_fc_r);
1815
- async function vi_fc_s(): Promise<void> { return vi_find_char_handler("s"); }
1816
- registerHandler("vi_fc_s", vi_fc_s);
1817
- async function vi_fc_t(): Promise<void> { return vi_find_char_handler("t"); }
1818
- registerHandler("vi_fc_t", vi_fc_t);
1819
- async function vi_fc_u(): Promise<void> { return vi_find_char_handler("u"); }
1820
- registerHandler("vi_fc_u", vi_fc_u);
1821
- async function vi_fc_v(): Promise<void> { return vi_find_char_handler("v"); }
1822
- registerHandler("vi_fc_v", vi_fc_v);
1823
- async function vi_fc_w(): Promise<void> { return vi_find_char_handler("w"); }
1824
- registerHandler("vi_fc_w", vi_fc_w);
1825
- async function vi_fc_x(): Promise<void> { return vi_find_char_handler("x"); }
1826
- registerHandler("vi_fc_x", vi_fc_x);
1827
- async function vi_fc_y(): Promise<void> { return vi_find_char_handler("y"); }
1828
- registerHandler("vi_fc_y", vi_fc_y);
1829
- async function vi_fc_z(): Promise<void> { return vi_find_char_handler("z"); }
1830
- registerHandler("vi_fc_z", vi_fc_z);
1831
- async function vi_fc_A(): Promise<void> { return vi_find_char_handler("A"); }
1832
- registerHandler("vi_fc_A", vi_fc_A);
1833
- async function vi_fc_B(): Promise<void> { return vi_find_char_handler("B"); }
1834
- registerHandler("vi_fc_B", vi_fc_B);
1835
- async function vi_fc_C(): Promise<void> { return vi_find_char_handler("C"); }
1836
- registerHandler("vi_fc_C", vi_fc_C);
1837
- async function vi_fc_D(): Promise<void> { return vi_find_char_handler("D"); }
1838
- registerHandler("vi_fc_D", vi_fc_D);
1839
- async function vi_fc_E(): Promise<void> { return vi_find_char_handler("E"); }
1840
- registerHandler("vi_fc_E", vi_fc_E);
1841
- async function vi_fc_F(): Promise<void> { return vi_find_char_handler("F"); }
1842
- registerHandler("vi_fc_F", vi_fc_F);
1843
- async function vi_fc_G(): Promise<void> { return vi_find_char_handler("G"); }
1844
- registerHandler("vi_fc_G", vi_fc_G);
1845
- async function vi_fc_H(): Promise<void> { return vi_find_char_handler("H"); }
1846
- registerHandler("vi_fc_H", vi_fc_H);
1847
- async function vi_fc_I(): Promise<void> { return vi_find_char_handler("I"); }
1848
- registerHandler("vi_fc_I", vi_fc_I);
1849
- async function vi_fc_J(): Promise<void> { return vi_find_char_handler("J"); }
1850
- registerHandler("vi_fc_J", vi_fc_J);
1851
- async function vi_fc_K(): Promise<void> { return vi_find_char_handler("K"); }
1852
- registerHandler("vi_fc_K", vi_fc_K);
1853
- async function vi_fc_L(): Promise<void> { return vi_find_char_handler("L"); }
1854
- registerHandler("vi_fc_L", vi_fc_L);
1855
- async function vi_fc_M(): Promise<void> { return vi_find_char_handler("M"); }
1856
- registerHandler("vi_fc_M", vi_fc_M);
1857
- async function vi_fc_N(): Promise<void> { return vi_find_char_handler("N"); }
1858
- registerHandler("vi_fc_N", vi_fc_N);
1859
- async function vi_fc_O(): Promise<void> { return vi_find_char_handler("O"); }
1860
- registerHandler("vi_fc_O", vi_fc_O);
1861
- async function vi_fc_P(): Promise<void> { return vi_find_char_handler("P"); }
1862
- registerHandler("vi_fc_P", vi_fc_P);
1863
- async function vi_fc_Q(): Promise<void> { return vi_find_char_handler("Q"); }
1864
- registerHandler("vi_fc_Q", vi_fc_Q);
1865
- async function vi_fc_R(): Promise<void> { return vi_find_char_handler("R"); }
1866
- registerHandler("vi_fc_R", vi_fc_R);
1867
- async function vi_fc_S(): Promise<void> { return vi_find_char_handler("S"); }
1868
- registerHandler("vi_fc_S", vi_fc_S);
1869
- async function vi_fc_T(): Promise<void> { return vi_find_char_handler("T"); }
1870
- registerHandler("vi_fc_T", vi_fc_T);
1871
- async function vi_fc_U(): Promise<void> { return vi_find_char_handler("U"); }
1872
- registerHandler("vi_fc_U", vi_fc_U);
1873
- async function vi_fc_V(): Promise<void> { return vi_find_char_handler("V"); }
1874
- registerHandler("vi_fc_V", vi_fc_V);
1875
- async function vi_fc_W(): Promise<void> { return vi_find_char_handler("W"); }
1876
- registerHandler("vi_fc_W", vi_fc_W);
1877
- async function vi_fc_X(): Promise<void> { return vi_find_char_handler("X"); }
1878
- registerHandler("vi_fc_X", vi_fc_X);
1879
- async function vi_fc_Y(): Promise<void> { return vi_find_char_handler("Y"); }
1880
- registerHandler("vi_fc_Y", vi_fc_Y);
1881
- async function vi_fc_Z(): Promise<void> { return vi_find_char_handler("Z"); }
1882
- registerHandler("vi_fc_Z", vi_fc_Z);
1883
- async function vi_fc_0(): Promise<void> { return vi_find_char_handler("0"); }
1884
- registerHandler("vi_fc_0", vi_fc_0);
1885
- async function vi_fc_1(): Promise<void> { return vi_find_char_handler("1"); }
1886
- registerHandler("vi_fc_1", vi_fc_1);
1887
- async function vi_fc_2(): Promise<void> { return vi_find_char_handler("2"); }
1888
- registerHandler("vi_fc_2", vi_fc_2);
1889
- async function vi_fc_3(): Promise<void> { return vi_find_char_handler("3"); }
1890
- registerHandler("vi_fc_3", vi_fc_3);
1891
- async function vi_fc_4(): Promise<void> { return vi_find_char_handler("4"); }
1892
- registerHandler("vi_fc_4", vi_fc_4);
1893
- async function vi_fc_5(): Promise<void> { return vi_find_char_handler("5"); }
1894
- registerHandler("vi_fc_5", vi_fc_5);
1895
- async function vi_fc_6(): Promise<void> { return vi_find_char_handler("6"); }
1896
- registerHandler("vi_fc_6", vi_fc_6);
1897
- async function vi_fc_7(): Promise<void> { return vi_find_char_handler("7"); }
1898
- registerHandler("vi_fc_7", vi_fc_7);
1899
- async function vi_fc_8(): Promise<void> { return vi_find_char_handler("8"); }
1900
- registerHandler("vi_fc_8", vi_fc_8);
1901
- async function vi_fc_9(): Promise<void> { return vi_find_char_handler("9"); }
1902
- registerHandler("vi_fc_9", vi_fc_9);
1903
- async function vi_fc_space(): Promise<void> { return vi_find_char_handler(" "); }
1904
- registerHandler("vi_fc_space", vi_fc_space);
1905
-
1906
- // Punctuation character handlers for find-char mode
1907
- const punctuationChars: [string, string][] = [
1908
- ["!", "excl"], ["@", "at"], ["#", "hash"], ["$", "dollar"], ["%", "percent"],
1909
- ["^", "caret"], ["&", "amp"], ["*", "star"], ["(", "lparen"], [")", "rparen"],
1910
- ["-", "minus"], ["_", "underscore"], ["=", "equals"], ["+", "plus"],
1911
- ["[", "lbracket"], ["]", "rbracket"], ["{", "lbrace"], ["}", "rbrace"],
1912
- ["\\", "backslash"], ["|", "pipe"], [";", "semi"], [":", "colon"],
1913
- ["'", "squote"], ["\"", "dquote"], [",", "comma"], [".", "dot"],
1914
- ["<", "lt"], [">", "gt"], ["/", "slash"], ["?", "question"], ["`", "backtick"],
1915
- ["~", "tilde"],
1916
- ];
1917
-
1918
- for (const [char, name] of punctuationChars) {
1919
- const handlerName = `vi_fc_p_${name}`;
1920
- const handler = async (): Promise<void> => { return vi_find_char_handler(char); };
1921
- registerHandler(handlerName, handler);
1922
- }
1923
-
1924
- // Define vi-find-char mode with all the character bindings
1925
- editor.defineMode("vi-find-char", [
1926
- ["Escape", "vi_find_char_cancel"],
1927
- // Letters
1928
- ["a", "vi_fc_a"], ["b", "vi_fc_b"], ["c", "vi_fc_c"], ["d", "vi_fc_d"],
1929
- ["e", "vi_fc_e"], ["f", "vi_fc_f"], ["g", "vi_fc_g"], ["h", "vi_fc_h"],
1930
- ["i", "vi_fc_i"], ["j", "vi_fc_j"], ["k", "vi_fc_k"], ["l", "vi_fc_l"],
1931
- ["m", "vi_fc_m"], ["n", "vi_fc_n"], ["o", "vi_fc_o"], ["p", "vi_fc_p"],
1932
- ["q", "vi_fc_q"], ["r", "vi_fc_r"], ["s", "vi_fc_s"], ["t", "vi_fc_t"],
1933
- ["u", "vi_fc_u"], ["v", "vi_fc_v"], ["w", "vi_fc_w"], ["x", "vi_fc_x"],
1934
- ["y", "vi_fc_y"], ["z", "vi_fc_z"],
1935
- ["A", "vi_fc_A"], ["B", "vi_fc_B"], ["C", "vi_fc_C"], ["D", "vi_fc_D"],
1936
- ["E", "vi_fc_E"], ["F", "vi_fc_F"], ["G", "vi_fc_G"], ["H", "vi_fc_H"],
1937
- ["I", "vi_fc_I"], ["J", "vi_fc_J"], ["K", "vi_fc_K"], ["L", "vi_fc_L"],
1938
- ["M", "vi_fc_M"], ["N", "vi_fc_N"], ["O", "vi_fc_O"], ["P", "vi_fc_P"],
1939
- ["Q", "vi_fc_Q"], ["R", "vi_fc_R"], ["S", "vi_fc_S"], ["T", "vi_fc_T"],
1940
- ["U", "vi_fc_U"], ["V", "vi_fc_V"], ["W", "vi_fc_W"], ["X", "vi_fc_X"],
1941
- ["Y", "vi_fc_Y"], ["Z", "vi_fc_Z"],
1942
- // Digits
1943
- ["0", "vi_fc_0"], ["1", "vi_fc_1"], ["2", "vi_fc_2"], ["3", "vi_fc_3"],
1944
- ["4", "vi_fc_4"], ["5", "vi_fc_5"], ["6", "vi_fc_6"], ["7", "vi_fc_7"],
1945
- ["8", "vi_fc_8"], ["9", "vi_fc_9"],
1946
- // Space and punctuation
1947
- ["Space", "vi_fc_space"],
1948
- ["!", "vi_fc_p_excl"], ["@", "vi_fc_p_at"], ["#", "vi_fc_p_hash"],
1949
- ["$", "vi_fc_p_dollar"], ["%", "vi_fc_p_percent"], ["^", "vi_fc_p_caret"],
1950
- ["&", "vi_fc_p_amp"], ["*", "vi_fc_p_star"], ["(", "vi_fc_p_lparen"],
1951
- [")", "vi_fc_p_rparen"], ["-", "vi_fc_p_minus"], ["_", "vi_fc_p_underscore"],
1952
- ["=", "vi_fc_p_equals"], ["+", "vi_fc_p_plus"], ["[", "vi_fc_p_lbracket"],
1953
- ["]", "vi_fc_p_rbracket"], ["{", "vi_fc_p_lbrace"], ["}", "vi_fc_p_rbrace"],
1954
- ["\\", "vi_fc_p_backslash"], ["|", "vi_fc_p_pipe"], [";", "vi_fc_p_semi"],
1955
- [":", "vi_fc_p_colon"], ["'", "vi_fc_p_squote"], ["\"", "vi_fc_p_dquote"],
1956
- [",", "vi_fc_p_comma"], [".", "vi_fc_p_dot"], ["<", "vi_fc_p_lt"],
1957
- [">", "vi_fc_p_gt"], ["/", "vi_fc_p_slash"], ["?", "vi_fc_p_question"],
1958
- ["`", "vi_fc_p_backtick"], ["~", "vi_fc_p_tilde"],
1959
- ], true);
1960
-
1961
- // Define vi-replace-char mode — reuses find-char handlers but calls vi_replace_char_handler
1962
- // We create replace-char specific handlers that delegate to the replace handler
1963
- const rcHandlers: [string, string][] = [];
1964
- for (const c of "abcdefghijklmnopqrstuvwxyz") {
1965
- const name = `vi_rc_${c}`;
1966
- const handler = async (): Promise<void> => { return vi_replace_char_handler(c); };
1967
- registerHandler(name, handler);
1968
- rcHandlers.push([c, name]);
1969
- }
1970
- for (const c of "ABCDEFGHIJKLMNOPQRSTUVWXYZ") {
1971
- const name = `vi_rc_${c}`;
1972
- const handler = async (): Promise<void> => { return vi_replace_char_handler(c); };
1973
- registerHandler(name, handler);
1974
- rcHandlers.push([c, name]);
1975
- }
1976
- for (const c of "0123456789") {
1977
- const name = `vi_rc_d${c}`;
1978
- const handler = async (): Promise<void> => { return vi_replace_char_handler(c); };
1979
- registerHandler(name, handler);
1980
- rcHandlers.push([c, name]);
1981
- }
1982
- // Space and common punctuation for replace-char mode
1983
- const rcSpaceHandler = async (): Promise<void> => { return vi_replace_char_handler(" "); };
1984
- registerHandler("vi_rc_space", rcSpaceHandler);
1985
- for (const [char, pname] of punctuationChars) {
1986
- const name = `vi_rc_p_${pname}`;
1987
- const handler = async (): Promise<void> => { return vi_replace_char_handler(char); };
1988
- registerHandler(name, handler);
1989
- }
1990
-
1991
- editor.defineMode("vi-replace-char", [
1992
- ["Escape", "vi_find_char_cancel"],
1993
- ...rcHandlers.map(([key, name]): [string, string] => [key, name]),
1994
- ["Space", "vi_rc_space"],
1995
- ...punctuationChars.map(([char, pname]): [string, string] => [char, `vi_rc_p_${pname}`]),
1996
- ], true);
1781
+ // vi-find-char and vi-replace-char modes do not need bindings:
1782
+ // their entry-point handlers (vi_find_char_f/t/F/T, vi_replace_char) call
1783
+ // editor.getNextKey() to read the next character. setEditorMode(...) is
1784
+ // still set across the await purely so the status bar shows the mode.
1997
1785
 
1998
1786
  // Define vi-operator-pending mode
1999
1787
  editor.defineMode("vi-operator-pending", [
@@ -2278,28 +2066,7 @@ function vi_command_mode(): void {
2278
2066
  registerHandler("vi_command_mode", vi_command_mode);
2279
2067
 
2280
2068
  // Handle command execution when user presses Enter
2281
- async function vi_command_handler(args: { prompt_type: string; input: string }): Promise<boolean> {
2282
- if (args.prompt_type !== "vi-command") {
2283
- return false; // Not our prompt, let other handlers process it
2284
- }
2285
2069
 
2286
- const input = args.input.trim();
2287
- if (!input) {
2288
- return true; // Empty command, just dismiss
2289
- }
2290
-
2291
- // Parse the command
2292
- const result = await executeViCommand(input);
2293
-
2294
- if (result.error) {
2295
- editor.setStatus(`E: ${result.error}`);
2296
- } else if (result.message) {
2297
- editor.setStatus(result.message);
2298
- }
2299
-
2300
- return true; // We handled it
2301
- }
2302
- registerHandler("vi_command_handler", vi_command_handler);
2303
2070
 
2304
2071
  interface CommandResult {
2305
2072
  error?: string;
@@ -3094,7 +2861,27 @@ function handleSetCommand(args: string): CommandResult {
3094
2861
  }
3095
2862
 
3096
2863
  // Register event handler for prompt confirmation
3097
- editor.on("prompt_confirmed", "vi_command_handler");
2864
+ editor.on("prompt_confirmed", async (args) => {
2865
+ if (args.prompt_type !== "vi-command") {
2866
+ return false; // Not our prompt, let other handlers process it
2867
+ }
2868
+
2869
+ const input = args.input.trim();
2870
+ if (!input) {
2871
+ return true; // Empty command, just dismiss
2872
+ }
2873
+
2874
+ // Parse the command
2875
+ const result = await executeViCommand(input);
2876
+
2877
+ if (result.error) {
2878
+ editor.setStatus(`E: ${result.error}`);
2879
+ } else if (result.message) {
2880
+ editor.setStatus(result.message);
2881
+ }
2882
+
2883
+ return true; // We handled it
2884
+ });
3098
2885
 
3099
2886
  // ============================================================================
3100
2887
  // Toggle Command
@@ -3135,4 +2922,4 @@ editor.registerCommand(
3135
2922
  // ============================================================================
3136
2923
 
3137
2924
 
3138
- registerHandler("vi_to_brace", vi_to_brace);
2925
+ registerHandler("vi_to_brace", vi_to_brace);
@@ -35,7 +35,8 @@ const INSTALL_COMMANDS = {
35
35
 
36
36
  let vueLspError: { serverCommand: string; message: string } | null = null;
37
37
 
38
- function on_vue_lsp_server_error(data: LspServerErrorData): void {
38
+
39
+ editor.on("lsp_server_error", (data) => {
39
40
  if (data.language !== "vue") {
40
41
  return;
41
42
  }
@@ -54,11 +55,10 @@ function on_vue_lsp_server_error(data: LspServerErrorData): void {
54
55
  } else {
55
56
  editor.setStatus(`Vue LSP error: ${data.message}`);
56
57
  }
57
- }
58
- registerHandler("on_vue_lsp_server_error", on_vue_lsp_server_error);
59
- editor.on("lsp_server_error", "on_vue_lsp_server_error");
58
+ });
59
+
60
60
 
61
- function on_vue_lsp_status_clicked(data: LspStatusClickedData): void {
61
+ editor.on("lsp_status_clicked", (data) => {
62
62
  if (data.language !== "vue" || !vueLspError) {
63
63
  return;
64
64
  }
@@ -76,11 +76,10 @@ function on_vue_lsp_status_clicked(data: LspStatusClickedData): void {
76
76
  { id: "dismiss", label: "Dismiss (ESC)" },
77
77
  ],
78
78
  });
79
- }
80
- registerHandler("on_vue_lsp_status_clicked", on_vue_lsp_status_clicked);
81
- editor.on("lsp_status_clicked", "on_vue_lsp_status_clicked");
79
+ });
80
+
82
81
 
83
- function on_vue_lsp_action_result(data: ActionPopupResultData): void {
82
+ editor.on("action_popup_result", (data) => {
84
83
  if (data.popup_id !== "vue-lsp-help") {
85
84
  return;
86
85
  }
@@ -111,8 +110,6 @@ function on_vue_lsp_action_result(data: ActionPopupResultData): void {
111
110
  default:
112
111
  editor.debug(`vue-lsp: Unknown action: ${data.action_id}`);
113
112
  }
114
- }
115
- registerHandler("on_vue_lsp_action_result", on_vue_lsp_action_result);
116
- editor.on("action_popup_result", "on_vue_lsp_action_result");
113
+ });
117
114
 
118
115
  editor.debug("vue-lsp: Plugin loaded");