@fresh-editor/fresh-editor 0.2.17 → 0.2.18

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 (41) hide show
  1. package/CHANGELOG.md +84 -0
  2. package/package.json +1 -1
  3. package/plugins/astro-lsp.ts +118 -0
  4. package/plugins/bash-lsp.ts +161 -0
  5. package/plugins/clojure-lsp.ts +125 -0
  6. package/plugins/cmake-lsp.ts +138 -0
  7. package/plugins/config-schema.json +33 -4
  8. package/plugins/dart-lsp.ts +144 -0
  9. package/plugins/elixir-lsp.ts +120 -0
  10. package/plugins/erlang-lsp.ts +121 -0
  11. package/plugins/fsharp-lsp.ts +125 -0
  12. package/plugins/gleam-lsp.ts +124 -0
  13. package/plugins/graphql-lsp.ts +139 -0
  14. package/plugins/haskell-lsp.ts +125 -0
  15. package/plugins/julia-lsp.ts +111 -0
  16. package/plugins/kotlin-lsp.ts +162 -0
  17. package/plugins/lib/fresh.d.ts +25 -0
  18. package/plugins/lua-lsp.ts +161 -0
  19. package/plugins/nim-lsp.ts +118 -0
  20. package/plugins/nix-lsp.ts +125 -0
  21. package/plugins/nushell-lsp.ts +144 -0
  22. package/plugins/ocaml-lsp.ts +119 -0
  23. package/plugins/perl-lsp.ts +118 -0
  24. package/plugins/php-lsp.ts +165 -0
  25. package/plugins/pkg.ts +33 -47
  26. package/plugins/protobuf-lsp.ts +144 -0
  27. package/plugins/r-lsp.ts +118 -0
  28. package/plugins/ruby-lsp.ts +165 -0
  29. package/plugins/scala-lsp.ts +119 -0
  30. package/plugins/solidity-lsp.ts +130 -0
  31. package/plugins/sql-lsp.ts +129 -0
  32. package/plugins/svelte-lsp.ts +119 -0
  33. package/plugins/swift-lsp.ts +120 -0
  34. package/plugins/tailwindcss-lsp.ts +119 -0
  35. package/plugins/terraform-lsp.ts +144 -0
  36. package/plugins/theme_editor.i18n.json +70 -14
  37. package/plugins/theme_editor.ts +71 -39
  38. package/plugins/toml-lsp.ts +162 -0
  39. package/plugins/typst-lsp.ts +165 -0
  40. package/plugins/vue-lsp.ts +118 -0
  41. package/plugins/yaml-lsp.ts +163 -0
@@ -38,6 +38,7 @@
38
38
  "show_menu_bar": true,
39
39
  "show_tab_bar": true,
40
40
  "show_status_bar": true,
41
+ "show_prompt_line": true,
41
42
  "show_vertical_scrollbar": true,
42
43
  "show_horizontal_scrollbar": false,
43
44
  "use_terminal_bg": false,
@@ -50,6 +51,7 @@
50
51
  "whitespace_tabs_leading": true,
51
52
  "whitespace_tabs_inner": true,
52
53
  "whitespace_tabs_trailing": true,
54
+ "use_tabs": false,
53
55
  "tab_size": 4,
54
56
  "auto_indent": true,
55
57
  "auto_close": true,
@@ -151,6 +153,18 @@
151
153
  },
152
154
  "default": {}
153
155
  },
156
+ "fallback": {
157
+ "description": "Fallback configuration for files whose type cannot be detected.\nApplied when no extension, filename, glob, or built-in detection matches.\nUseful for setting a default grammar (e.g., \"bash\") and comment_prefix\nfor unrecognized .conf, .rc, .rules, etc. files.",
158
+ "anyOf": [
159
+ {
160
+ "$ref": "#/$defs/LanguageConfig"
161
+ },
162
+ {
163
+ "type": "null"
164
+ }
165
+ ],
166
+ "default": null
167
+ },
154
168
  "lsp": {
155
169
  "description": "LSP server configurations by language",
156
170
  "type": "object",
@@ -269,6 +283,12 @@
269
283
  "default": true,
270
284
  "x-section": "Display"
271
285
  },
286
+ "show_prompt_line": {
287
+ "description": "Whether the prompt line is visible by default.\nThe prompt line is the bottom-most line used for command input, search, file open, etc.\nWhen hidden, the prompt line only appears when a prompt is active.\nCan be toggled at runtime via command palette or keybinding.\nDefault: true",
288
+ "type": "boolean",
289
+ "default": true,
290
+ "x-section": "Display"
291
+ },
272
292
  "show_vertical_scrollbar": {
273
293
  "description": "Whether the vertical scrollbar is visible in each split pane.\nCan be toggled at runtime via command palette or keybinding.\nDefault: true",
274
294
  "type": "boolean",
@@ -346,6 +366,12 @@
346
366
  "default": true,
347
367
  "x-section": "Whitespace"
348
368
  },
369
+ "use_tabs": {
370
+ "description": "Whether pressing Tab inserts a tab character instead of spaces.\nThis is the global default; individual languages can override it\nvia their own `use_tabs` setting.\nDefault: false (insert spaces)",
371
+ "type": "boolean",
372
+ "default": false,
373
+ "x-section": "Editing"
374
+ },
349
375
  "tab_size": {
350
376
  "description": "Number of spaces per tab character",
351
377
  "type": "integer",
@@ -455,7 +481,7 @@
455
481
  "x-section": "Diagnostics"
456
482
  },
457
483
  "mouse_hover_enabled": {
458
- "description": "Whether mouse hover triggers LSP hover requests.\nWhen enabled, hovering over code with the mouse will show documentation.\nDefault: true",
484
+ "description": "Whether mouse hover triggers LSP hover requests.\nWhen enabled, hovering over code with the mouse will show documentation.\nOn Windows, this also controls the mouse tracking mode: when disabled,\nthe editor uses xterm mode 1002 (cell motion — click, drag, release only);\nwhen enabled, it uses mode 1003 (all motion — full mouse movement tracking).\nMode 1003 generates high event volume on Windows and may cause input\ncorruption on some systems. On macOS and Linux this setting only controls\nLSP hover; the mouse tracking mode is always full motion.\nDefault: true (macOS/Linux), false (Windows)",
459
485
  "type": "boolean",
460
486
  "default": true,
461
487
  "x-section": "Mouse"
@@ -879,9 +905,12 @@
879
905
  "default": true
880
906
  },
881
907
  "use_tabs": {
882
- "description": "Whether pressing Tab should insert a tab character instead of spaces.\nDefaults to false (insert spaces based on tab_size).\nSet to true for languages like Go and Makefile that require tabs.",
883
- "type": "boolean",
884
- "default": false
908
+ "description": "Whether pressing Tab should insert a tab character instead of spaces.\nIf not specified (`null`), falls back to the global `editor.use_tabs` setting.\nSet to true for languages like Go and Makefile that require tabs.",
909
+ "type": [
910
+ "boolean",
911
+ "null"
912
+ ],
913
+ "default": null
885
914
  },
886
915
  "tab_size": {
887
916
  "description": "Tab size (number of spaces per tab) for this language.\nIf not specified, falls back to the global editor.tab_size setting.",
@@ -0,0 +1,144 @@
1
+ /// <reference path="./lib/fresh.d.ts" />
2
+ const editor = getEditor();
3
+
4
+ /**
5
+ * Dart LSP Helper Plugin
6
+ *
7
+ * Provides user-friendly error handling for Dart LSP server issues.
8
+ * The Dart language server is included with the Dart SDK.
9
+ *
10
+ * Features:
11
+ * - Detects Dart LSP server errors
12
+ * - Shows popup with install instructions for Dart SDK
13
+ * - Provides option to disable Dart LSP
14
+ *
15
+ * VS Code: "Dart" extension by Dart Code (uses bundled analysis server)
16
+ * Neovim: nvim-lspconfig dartls
17
+ * Note: The analysis server is bundled with Dart SDK and Flutter SDK
18
+ * For Flutter: Install Flutter SDK which includes Dart
19
+ */
20
+
21
+ interface LspServerErrorData {
22
+ language: string;
23
+ server_command: string;
24
+ error_type: string;
25
+ message: string;
26
+ }
27
+
28
+ interface LspStatusClickedData {
29
+ language: string;
30
+ has_error: boolean;
31
+ }
32
+
33
+ interface ActionPopupResultData {
34
+ popup_id: string;
35
+ action_id: string;
36
+ }
37
+
38
+ // Install commands for Dart SDK (which includes the language server)
39
+ // See: https://dart.dev/get-dart
40
+ const INSTALL_COMMANDS = {
41
+ brew: "brew install dart",
42
+ apt: "sudo apt install dart",
43
+ choco: "choco install dart-sdk",
44
+ };
45
+
46
+ // Track error state for Dart LSP
47
+ let dartLspError: { serverCommand: string; message: string } | null = null;
48
+
49
+ /**
50
+ * Handle LSP server errors for Dart
51
+ */
52
+ function on_dart_lsp_server_error(data: LspServerErrorData): void {
53
+ if (data.language !== "dart") {
54
+ return;
55
+ }
56
+
57
+ editor.debug(`dart-lsp: Server error - ${data.error_type}: ${data.message}`);
58
+
59
+ dartLspError = {
60
+ serverCommand: data.server_command,
61
+ message: data.message,
62
+ };
63
+
64
+ if (data.error_type === "not_found") {
65
+ editor.setStatus(
66
+ `Dart LSP server '${data.server_command}' not found. Click status bar for help.`
67
+ );
68
+ } else {
69
+ editor.setStatus(`Dart LSP error: ${data.message}`);
70
+ }
71
+ }
72
+ registerHandler("on_dart_lsp_server_error", on_dart_lsp_server_error);
73
+ editor.on("lsp_server_error", "on_dart_lsp_server_error");
74
+
75
+ /**
76
+ * Handle status bar click when there's a Dart LSP error
77
+ */
78
+ function on_dart_lsp_status_clicked(data: LspStatusClickedData): void {
79
+ if (data.language !== "dart" || !dartLspError) {
80
+ return;
81
+ }
82
+
83
+ editor.debug("dart-lsp: Status clicked, showing help popup");
84
+
85
+ editor.showActionPopup({
86
+ id: "dart-lsp-help",
87
+ title: "Dart Language Server Not Found",
88
+ message: `The Dart language server is included with the Dart SDK. Install the Dart SDK (or Flutter SDK) to get LSP support. Visit https://dart.dev/get-dart for platform-specific instructions.`,
89
+ actions: [
90
+ { id: "copy_brew", label: `Copy: ${INSTALL_COMMANDS.brew}` },
91
+ { id: "copy_apt", label: `Copy: ${INSTALL_COMMANDS.apt}` },
92
+ { id: "copy_choco", label: `Copy: ${INSTALL_COMMANDS.choco} (Windows)` },
93
+ { id: "disable", label: "Disable Dart LSP" },
94
+ { id: "dismiss", label: "Dismiss (ESC)" },
95
+ ],
96
+ });
97
+ }
98
+ registerHandler("on_dart_lsp_status_clicked", on_dart_lsp_status_clicked);
99
+ editor.on("lsp_status_clicked", "on_dart_lsp_status_clicked");
100
+
101
+ /**
102
+ * Handle action popup results for Dart LSP help
103
+ */
104
+ function on_dart_lsp_action_result(data: ActionPopupResultData): void {
105
+ if (data.popup_id !== "dart-lsp-help") {
106
+ return;
107
+ }
108
+
109
+ editor.debug(`dart-lsp: Action selected - ${data.action_id}`);
110
+
111
+ switch (data.action_id) {
112
+ case "copy_brew":
113
+ editor.setClipboard(INSTALL_COMMANDS.brew);
114
+ editor.setStatus("Copied: " + INSTALL_COMMANDS.brew);
115
+ break;
116
+
117
+ case "copy_apt":
118
+ editor.setClipboard(INSTALL_COMMANDS.apt);
119
+ editor.setStatus("Copied: " + INSTALL_COMMANDS.apt);
120
+ break;
121
+
122
+ case "copy_choco":
123
+ editor.setClipboard(INSTALL_COMMANDS.choco);
124
+ editor.setStatus("Copied: " + INSTALL_COMMANDS.choco);
125
+ break;
126
+
127
+ case "disable":
128
+ editor.disableLspForLanguage("dart");
129
+ editor.setStatus("Dart LSP disabled");
130
+ dartLspError = null;
131
+ break;
132
+
133
+ case "dismiss":
134
+ case "dismissed":
135
+ break;
136
+
137
+ default:
138
+ editor.debug(`dart-lsp: Unknown action: ${data.action_id}`);
139
+ }
140
+ }
141
+ registerHandler("on_dart_lsp_action_result", on_dart_lsp_action_result);
142
+ editor.on("action_popup_result", "on_dart_lsp_action_result");
143
+
144
+ editor.debug("dart-lsp: Plugin loaded");
@@ -0,0 +1,120 @@
1
+ /// <reference path="./lib/fresh.d.ts" />
2
+ const editor = getEditor();
3
+
4
+ /**
5
+ * Elixir LSP Helper Plugin
6
+ *
7
+ * Server: elixir-ls (github.com/elixir-lsp/elixir-ls)
8
+ * VS Code: "ElixirLS" extension
9
+ * Neovim: nvim-lspconfig elixirls
10
+ * Requires: Elixir and Erlang/OTP installed
11
+ * Note: The Elixir ecosystem is consolidating around Expert
12
+ * (github.com/elixir-lang/expert) as the new official LSP server
13
+ */
14
+
15
+ interface LspServerErrorData {
16
+ language: string;
17
+ server_command: string;
18
+ error_type: string;
19
+ message: string;
20
+ }
21
+
22
+ interface LspStatusClickedData {
23
+ language: string;
24
+ has_error: boolean;
25
+ }
26
+
27
+ interface ActionPopupResultData {
28
+ popup_id: string;
29
+ action_id: string;
30
+ }
31
+
32
+ const INSTALL_COMMANDS = {
33
+ github: "# Download from https://github.com/elixir-lsp/elixir-ls/releases",
34
+ brew: "brew install elixir-ls",
35
+ nix: "nix-env -iA nixpkgs.elixir-ls",
36
+ };
37
+
38
+ let elixirLspError: { serverCommand: string; message: string } | null = null;
39
+
40
+ function on_elixir_lsp_server_error(data: LspServerErrorData): void {
41
+ if (data.language !== "elixir") {
42
+ return;
43
+ }
44
+
45
+ editor.debug(`elixir-lsp: Server error - ${data.error_type}: ${data.message}`);
46
+
47
+ elixirLspError = {
48
+ serverCommand: data.server_command,
49
+ message: data.message,
50
+ };
51
+
52
+ if (data.error_type === "not_found") {
53
+ editor.setStatus(
54
+ `Elixir LSP server '${data.server_command}' not found. Click status bar for help.`
55
+ );
56
+ } else {
57
+ editor.setStatus(`Elixir LSP error: ${data.message}`);
58
+ }
59
+ }
60
+ registerHandler("on_elixir_lsp_server_error", on_elixir_lsp_server_error);
61
+ editor.on("lsp_server_error", "on_elixir_lsp_server_error");
62
+
63
+ function on_elixir_lsp_status_clicked(data: LspStatusClickedData): void {
64
+ if (data.language !== "elixir" || !elixirLspError) {
65
+ return;
66
+ }
67
+
68
+ editor.debug("elixir-lsp: Status clicked, showing help popup");
69
+
70
+ editor.showActionPopup({
71
+ id: "elixir-lsp-help",
72
+ title: "Elixir Language Server Not Found",
73
+ message: `"${elixirLspError.serverCommand}" provides completion, diagnostics, go-to-definition, Dialyzer integration, and debugging for Elixir. Requires Elixir and Erlang/OTP.\n\nNew: Expert (https://expert-lsp.org) is the upcoming official Elixir LSP, merging ElixirLS, Lexical, and Next LS.\nVS Code users: Install the "ElixirLS" extension.\nSee: https://github.com/elixir-lsp/elixir-ls`,
74
+ actions: [
75
+ { id: "copy_brew", label: `Copy: ${INSTALL_COMMANDS.brew}` },
76
+ { id: "copy_nix", label: `Copy: ${INSTALL_COMMANDS.nix}` },
77
+ { id: "disable", label: "Disable Elixir LSP" },
78
+ { id: "dismiss", label: "Dismiss (ESC)" },
79
+ ],
80
+ });
81
+ }
82
+ registerHandler("on_elixir_lsp_status_clicked", on_elixir_lsp_status_clicked);
83
+ editor.on("lsp_status_clicked", "on_elixir_lsp_status_clicked");
84
+
85
+ function on_elixir_lsp_action_result(data: ActionPopupResultData): void {
86
+ if (data.popup_id !== "elixir-lsp-help") {
87
+ return;
88
+ }
89
+
90
+ editor.debug(`elixir-lsp: Action selected - ${data.action_id}`);
91
+
92
+ switch (data.action_id) {
93
+ case "copy_brew":
94
+ editor.setClipboard(INSTALL_COMMANDS.brew);
95
+ editor.setStatus("Copied: " + INSTALL_COMMANDS.brew);
96
+ break;
97
+
98
+ case "copy_nix":
99
+ editor.setClipboard(INSTALL_COMMANDS.nix);
100
+ editor.setStatus("Copied: " + INSTALL_COMMANDS.nix);
101
+ break;
102
+
103
+ case "disable":
104
+ editor.disableLspForLanguage("elixir");
105
+ editor.setStatus("Elixir LSP disabled");
106
+ elixirLspError = null;
107
+ break;
108
+
109
+ case "dismiss":
110
+ case "dismissed":
111
+ break;
112
+
113
+ default:
114
+ editor.debug(`elixir-lsp: Unknown action: ${data.action_id}`);
115
+ }
116
+ }
117
+ registerHandler("on_elixir_lsp_action_result", on_elixir_lsp_action_result);
118
+ editor.on("action_popup_result", "on_elixir_lsp_action_result");
119
+
120
+ editor.debug("elixir-lsp: Plugin loaded");
@@ -0,0 +1,121 @@
1
+ /// <reference path="./lib/fresh.d.ts" />
2
+ const editor = getEditor();
3
+
4
+ /**
5
+ * Erlang LSP Helper Plugin
6
+ *
7
+ * Server: erlang_ls (github.com/erlang-ls/erlang_ls)
8
+ * VS Code: "Erlang LS" extension
9
+ * Neovim: nvim-lspconfig erlangls
10
+ * Requires: Erlang/OTP 24+, rebar3
11
+ * Note: erlang_ls is archived; consider ELP (Erlang Language Platform)
12
+ * by WhatsApp as the recommended successor
13
+ * ELP: github.com/WhatsApp/erlang-language-platform
14
+ */
15
+
16
+ interface LspServerErrorData {
17
+ language: string;
18
+ server_command: string;
19
+ error_type: string;
20
+ message: string;
21
+ }
22
+
23
+ interface LspStatusClickedData {
24
+ language: string;
25
+ has_error: boolean;
26
+ }
27
+
28
+ interface ActionPopupResultData {
29
+ popup_id: string;
30
+ action_id: string;
31
+ }
32
+
33
+ const INSTALL_COMMANDS = {
34
+ brew: "brew install erlang_ls",
35
+ build: "git clone https://github.com/erlang-ls/erlang_ls && cd erlang_ls && make && make install",
36
+ nix: "nix-env -iA nixpkgs.erlang-ls",
37
+ };
38
+
39
+ let erlangLspError: { serverCommand: string; message: string } | null = null;
40
+
41
+ function on_erlang_lsp_server_error(data: LspServerErrorData): void {
42
+ if (data.language !== "erlang") {
43
+ return;
44
+ }
45
+
46
+ editor.debug(`erlang-lsp: Server error - ${data.error_type}: ${data.message}`);
47
+
48
+ erlangLspError = {
49
+ serverCommand: data.server_command,
50
+ message: data.message,
51
+ };
52
+
53
+ if (data.error_type === "not_found") {
54
+ editor.setStatus(
55
+ `Erlang LSP server '${data.server_command}' not found. Click status bar for help.`
56
+ );
57
+ } else {
58
+ editor.setStatus(`Erlang LSP error: ${data.message}`);
59
+ }
60
+ }
61
+ registerHandler("on_erlang_lsp_server_error", on_erlang_lsp_server_error);
62
+ editor.on("lsp_server_error", "on_erlang_lsp_server_error");
63
+
64
+ function on_erlang_lsp_status_clicked(data: LspStatusClickedData): void {
65
+ if (data.language !== "erlang" || !erlangLspError) {
66
+ return;
67
+ }
68
+
69
+ editor.debug("erlang-lsp: Status clicked, showing help popup");
70
+
71
+ editor.showActionPopup({
72
+ id: "erlang-lsp-help",
73
+ title: "Erlang Language Server Not Found",
74
+ message: `"${erlangLspError.serverCommand}" provides completion, diagnostics, navigation, and code actions for Erlang. Requires Erlang/OTP 24+.\n\nNote: erlang_ls is archived. Consider ELP (Erlang Language Platform) by WhatsApp as the successor: https://github.com/WhatsApp/erlang-language-platform\nConfigure via erlang_ls.config in your project root.\nVS Code users: Install "Erlang LS" or "Erlang Language Platform" extension.\nSee: https://github.com/erlang-ls/erlang_ls`,
75
+ actions: [
76
+ { id: "copy_brew", label: `Copy: ${INSTALL_COMMANDS.brew}` },
77
+ { id: "copy_nix", label: `Copy: ${INSTALL_COMMANDS.nix}` },
78
+ { id: "disable", label: "Disable Erlang LSP" },
79
+ { id: "dismiss", label: "Dismiss (ESC)" },
80
+ ],
81
+ });
82
+ }
83
+ registerHandler("on_erlang_lsp_status_clicked", on_erlang_lsp_status_clicked);
84
+ editor.on("lsp_status_clicked", "on_erlang_lsp_status_clicked");
85
+
86
+ function on_erlang_lsp_action_result(data: ActionPopupResultData): void {
87
+ if (data.popup_id !== "erlang-lsp-help") {
88
+ return;
89
+ }
90
+
91
+ editor.debug(`erlang-lsp: Action selected - ${data.action_id}`);
92
+
93
+ switch (data.action_id) {
94
+ case "copy_brew":
95
+ editor.setClipboard(INSTALL_COMMANDS.brew);
96
+ editor.setStatus("Copied: " + INSTALL_COMMANDS.brew);
97
+ break;
98
+
99
+ case "copy_nix":
100
+ editor.setClipboard(INSTALL_COMMANDS.nix);
101
+ editor.setStatus("Copied: " + INSTALL_COMMANDS.nix);
102
+ break;
103
+
104
+ case "disable":
105
+ editor.disableLspForLanguage("erlang");
106
+ editor.setStatus("Erlang LSP disabled");
107
+ erlangLspError = null;
108
+ break;
109
+
110
+ case "dismiss":
111
+ case "dismissed":
112
+ break;
113
+
114
+ default:
115
+ editor.debug(`erlang-lsp: Unknown action: ${data.action_id}`);
116
+ }
117
+ }
118
+ registerHandler("on_erlang_lsp_action_result", on_erlang_lsp_action_result);
119
+ editor.on("action_popup_result", "on_erlang_lsp_action_result");
120
+
121
+ editor.debug("erlang-lsp: Plugin loaded");
@@ -0,0 +1,125 @@
1
+ /// <reference path="./lib/fresh.d.ts" />
2
+ const editor = getEditor();
3
+
4
+ /**
5
+ * F# LSP Helper Plugin
6
+ *
7
+ * Server: fsautocomplete (FsAutoComplete)
8
+ * VS Code: "Ionide-fsharp" extension (bundles fsautocomplete)
9
+ * Neovim: nvim-lspconfig fsautocomplete
10
+ * Install via: dotnet tool, brew, or nix
11
+ * Requires: .NET SDK installed
12
+ */
13
+
14
+ interface LspServerErrorData {
15
+ language: string;
16
+ server_command: string;
17
+ error_type: string;
18
+ message: string;
19
+ }
20
+
21
+ interface LspStatusClickedData {
22
+ language: string;
23
+ has_error: boolean;
24
+ }
25
+
26
+ interface ActionPopupResultData {
27
+ popup_id: string;
28
+ action_id: string;
29
+ }
30
+
31
+ const INSTALL_COMMANDS = {
32
+ dotnet: "dotnet tool install -g fsautocomplete",
33
+ brew: "brew install fsautocomplete",
34
+ nix: "nix-env -iA nixpkgs.fsautocomplete",
35
+ };
36
+
37
+ let fsharpLspError: { serverCommand: string; message: string } | null = null;
38
+
39
+ function on_fsharp_lsp_server_error(data: LspServerErrorData): void {
40
+ if (data.language !== "fsharp") {
41
+ return;
42
+ }
43
+
44
+ editor.debug(`fsharp-lsp: Server error - ${data.error_type}: ${data.message}`);
45
+
46
+ fsharpLspError = {
47
+ serverCommand: data.server_command,
48
+ message: data.message,
49
+ };
50
+
51
+ if (data.error_type === "not_found") {
52
+ editor.setStatus(
53
+ `F# LSP server '${data.server_command}' not found. Click status bar for help.`
54
+ );
55
+ } else {
56
+ editor.setStatus(`F# LSP error: ${data.message}`);
57
+ }
58
+ }
59
+ registerHandler("on_fsharp_lsp_server_error", on_fsharp_lsp_server_error);
60
+ editor.on("lsp_server_error", "on_fsharp_lsp_server_error");
61
+
62
+ function on_fsharp_lsp_status_clicked(data: LspStatusClickedData): void {
63
+ if (data.language !== "fsharp" || !fsharpLspError) {
64
+ return;
65
+ }
66
+
67
+ editor.debug("fsharp-lsp: Status clicked, showing help popup");
68
+
69
+ editor.showActionPopup({
70
+ id: "fsharp-lsp-help",
71
+ title: "F# Language Server Not Found",
72
+ message: `"${fsharpLspError.serverCommand}" (FsAutoComplete) provides completion, diagnostics, code actions, and refactoring for F#. Requires .NET SDK.\n\nVS Code users: Install "Ionide-fsharp" (bundles fsautocomplete).\nSee: https://github.com/fsharp/FsAutoComplete`,
73
+ actions: [
74
+ { id: "copy_dotnet", label: `Copy: ${INSTALL_COMMANDS.dotnet}` },
75
+ { id: "copy_brew", label: `Copy: ${INSTALL_COMMANDS.brew}` },
76
+ { id: "copy_nix", label: `Copy: ${INSTALL_COMMANDS.nix}` },
77
+ { id: "disable", label: "Disable F# LSP" },
78
+ { id: "dismiss", label: "Dismiss (ESC)" },
79
+ ],
80
+ });
81
+ }
82
+ registerHandler("on_fsharp_lsp_status_clicked", on_fsharp_lsp_status_clicked);
83
+ editor.on("lsp_status_clicked", "on_fsharp_lsp_status_clicked");
84
+
85
+ function on_fsharp_lsp_action_result(data: ActionPopupResultData): void {
86
+ if (data.popup_id !== "fsharp-lsp-help") {
87
+ return;
88
+ }
89
+
90
+ editor.debug(`fsharp-lsp: Action selected - ${data.action_id}`);
91
+
92
+ switch (data.action_id) {
93
+ case "copy_dotnet":
94
+ editor.setClipboard(INSTALL_COMMANDS.dotnet);
95
+ editor.setStatus("Copied: " + INSTALL_COMMANDS.dotnet);
96
+ break;
97
+
98
+ case "copy_brew":
99
+ editor.setClipboard(INSTALL_COMMANDS.brew);
100
+ editor.setStatus("Copied: " + INSTALL_COMMANDS.brew);
101
+ break;
102
+
103
+ case "copy_nix":
104
+ editor.setClipboard(INSTALL_COMMANDS.nix);
105
+ editor.setStatus("Copied: " + INSTALL_COMMANDS.nix);
106
+ break;
107
+
108
+ case "disable":
109
+ editor.disableLspForLanguage("fsharp");
110
+ editor.setStatus("F# LSP disabled");
111
+ fsharpLspError = null;
112
+ break;
113
+
114
+ case "dismiss":
115
+ case "dismissed":
116
+ break;
117
+
118
+ default:
119
+ editor.debug(`fsharp-lsp: Unknown action: ${data.action_id}`);
120
+ }
121
+ }
122
+ registerHandler("on_fsharp_lsp_action_result", on_fsharp_lsp_action_result);
123
+ editor.on("action_popup_result", "on_fsharp_lsp_action_result");
124
+
125
+ editor.debug("fsharp-lsp: Plugin loaded");