@fresh-editor/fresh-editor 0.1.65 → 0.1.67

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.
@@ -0,0 +1,143 @@
1
+ /// <reference path="./lib/fresh.d.ts" />
2
+
3
+ /**
4
+ * HTML LSP Helper Plugin
5
+ *
6
+ * Provides user-friendly error handling for HTML LSP server issues.
7
+ * When the HTML language server fails to start, this plugin shows an
8
+ * actionable popup with installation instructions.
9
+ *
10
+ * Features:
11
+ * - Detects HTML LSP server errors
12
+ * - Shows popup with install commands (npm)
13
+ * - Allows copying install commands to clipboard
14
+ * - Provides option to disable HTML LSP
15
+ */
16
+
17
+ interface LspServerErrorData {
18
+ language: string;
19
+ server_command: string;
20
+ error_type: string;
21
+ message: string;
22
+ }
23
+
24
+ interface LspStatusClickedData {
25
+ language: string;
26
+ has_error: boolean;
27
+ }
28
+
29
+ interface ActionPopupResultData {
30
+ popup_id: string;
31
+ action_id: string;
32
+ }
33
+
34
+ // Install commands for HTML LSP server
35
+ // vscode-langservers-extracted provides HTML, CSS, and JSON language servers
36
+ // See: https://www.npmjs.com/package/vscode-langservers-extracted
37
+ const INSTALL_COMMANDS = {
38
+ npm: "npm install -g vscode-langservers-extracted",
39
+ };
40
+
41
+ // Track error state for HTML LSP
42
+ let htmlLspError: { serverCommand: string; message: string } | null = null;
43
+
44
+ /**
45
+ * Handle LSP server errors for HTML
46
+ */
47
+ globalThis.on_html_lsp_server_error = function (
48
+ data: LspServerErrorData
49
+ ): void {
50
+ // Only handle HTML language errors
51
+ if (data.language !== "html") {
52
+ return;
53
+ }
54
+
55
+ editor.debug(`html-lsp: Server error - ${data.error_type}: ${data.message}`);
56
+
57
+ // Store error state for later reference
58
+ htmlLspError = {
59
+ serverCommand: data.server_command,
60
+ message: data.message,
61
+ };
62
+
63
+ // Show a status message for immediate feedback
64
+ if (data.error_type === "not_found") {
65
+ editor.setStatus(
66
+ `HTML LSP server '${data.server_command}' not found. Click status bar for help.`
67
+ );
68
+ } else {
69
+ editor.setStatus(`HTML LSP error: ${data.message}`);
70
+ }
71
+ };
72
+
73
+ // Register hook for LSP server errors
74
+ editor.on("lsp_server_error", "on_html_lsp_server_error");
75
+
76
+ /**
77
+ * Handle status bar click when there's an HTML LSP error
78
+ */
79
+ globalThis.on_html_lsp_status_clicked = function (
80
+ data: LspStatusClickedData
81
+ ): void {
82
+ // Only handle HTML language clicks when there's an error
83
+ if (data.language !== "html" || !htmlLspError) {
84
+ return;
85
+ }
86
+
87
+ editor.debug("html-lsp: Status clicked, showing help popup");
88
+
89
+ // Show action popup with install options
90
+ editor.showActionPopup({
91
+ id: "html-lsp-help",
92
+ title: "HTML Language Server Not Found",
93
+ message: `"${htmlLspError.serverCommand}" provides code completion, diagnostics, and formatting for HTML files. Copy the command below to install it.`,
94
+ actions: [
95
+ { id: "copy_npm", label: `Copy: ${INSTALL_COMMANDS.npm}` },
96
+ { id: "disable", label: "Disable HTML LSP" },
97
+ { id: "dismiss", label: "Dismiss (ESC)" },
98
+ ],
99
+ });
100
+ };
101
+
102
+ // Register hook for status bar clicks
103
+ editor.on("lsp_status_clicked", "on_html_lsp_status_clicked");
104
+
105
+ /**
106
+ * Handle action popup results for HTML LSP help
107
+ */
108
+ globalThis.on_html_lsp_action_result = function (
109
+ data: ActionPopupResultData
110
+ ): void {
111
+ // Only handle our popup
112
+ if (data.popup_id !== "html-lsp-help") {
113
+ return;
114
+ }
115
+
116
+ editor.debug(`html-lsp: Action selected - ${data.action_id}`);
117
+
118
+ switch (data.action_id) {
119
+ case "copy_npm":
120
+ editor.setClipboard(INSTALL_COMMANDS.npm);
121
+ editor.setStatus("Copied: " + INSTALL_COMMANDS.npm);
122
+ break;
123
+
124
+ case "disable":
125
+ editor.disableLspForLanguage("html");
126
+ editor.setStatus("HTML LSP disabled");
127
+ htmlLspError = null;
128
+ break;
129
+
130
+ case "dismiss":
131
+ case "dismissed":
132
+ // Just close the popup without action
133
+ break;
134
+
135
+ default:
136
+ editor.debug(`html-lsp: Unknown action: ${data.action_id}`);
137
+ }
138
+ };
139
+
140
+ // Register hook for action popup results
141
+ editor.on("action_popup_result", "on_html_lsp_action_result");
142
+
143
+ editor.debug("html-lsp: Plugin loaded");
@@ -0,0 +1,143 @@
1
+ /// <reference path="./lib/fresh.d.ts" />
2
+
3
+ /**
4
+ * JSON LSP Helper Plugin
5
+ *
6
+ * Provides user-friendly error handling for JSON LSP server issues.
7
+ * When the JSON language server fails to start, this plugin shows an
8
+ * actionable popup with installation instructions.
9
+ *
10
+ * Features:
11
+ * - Detects JSON LSP server errors
12
+ * - Shows popup with install commands (npm)
13
+ * - Allows copying install commands to clipboard
14
+ * - Provides option to disable JSON LSP
15
+ */
16
+
17
+ interface LspServerErrorData {
18
+ language: string;
19
+ server_command: string;
20
+ error_type: string;
21
+ message: string;
22
+ }
23
+
24
+ interface LspStatusClickedData {
25
+ language: string;
26
+ has_error: boolean;
27
+ }
28
+
29
+ interface ActionPopupResultData {
30
+ popup_id: string;
31
+ action_id: string;
32
+ }
33
+
34
+ // Install commands for JSON LSP server
35
+ // vscode-langservers-extracted provides HTML, CSS, and JSON language servers
36
+ // See: https://www.npmjs.com/package/vscode-langservers-extracted
37
+ const INSTALL_COMMANDS = {
38
+ npm: "npm install -g vscode-langservers-extracted",
39
+ };
40
+
41
+ // Track error state for JSON LSP
42
+ let jsonLspError: { serverCommand: string; message: string } | null = null;
43
+
44
+ /**
45
+ * Handle LSP server errors for JSON
46
+ */
47
+ globalThis.on_json_lsp_server_error = function (
48
+ data: LspServerErrorData
49
+ ): void {
50
+ // Only handle JSON language errors
51
+ if (data.language !== "json") {
52
+ return;
53
+ }
54
+
55
+ editor.debug(`json-lsp: Server error - ${data.error_type}: ${data.message}`);
56
+
57
+ // Store error state for later reference
58
+ jsonLspError = {
59
+ serverCommand: data.server_command,
60
+ message: data.message,
61
+ };
62
+
63
+ // Show a status message for immediate feedback
64
+ if (data.error_type === "not_found") {
65
+ editor.setStatus(
66
+ `JSON LSP server '${data.server_command}' not found. Click status bar for help.`
67
+ );
68
+ } else {
69
+ editor.setStatus(`JSON LSP error: ${data.message}`);
70
+ }
71
+ };
72
+
73
+ // Register hook for LSP server errors
74
+ editor.on("lsp_server_error", "on_json_lsp_server_error");
75
+
76
+ /**
77
+ * Handle status bar click when there's a JSON LSP error
78
+ */
79
+ globalThis.on_json_lsp_status_clicked = function (
80
+ data: LspStatusClickedData
81
+ ): void {
82
+ // Only handle JSON language clicks when there's an error
83
+ if (data.language !== "json" || !jsonLspError) {
84
+ return;
85
+ }
86
+
87
+ editor.debug("json-lsp: Status clicked, showing help popup");
88
+
89
+ // Show action popup with install options
90
+ editor.showActionPopup({
91
+ id: "json-lsp-help",
92
+ title: "JSON Language Server Not Found",
93
+ message: `"${jsonLspError.serverCommand}" provides code completion, validation, and formatting for JSON files. Copy the command below to install it.`,
94
+ actions: [
95
+ { id: "copy_npm", label: `Copy: ${INSTALL_COMMANDS.npm}` },
96
+ { id: "disable", label: "Disable JSON LSP" },
97
+ { id: "dismiss", label: "Dismiss (ESC)" },
98
+ ],
99
+ });
100
+ };
101
+
102
+ // Register hook for status bar clicks
103
+ editor.on("lsp_status_clicked", "on_json_lsp_status_clicked");
104
+
105
+ /**
106
+ * Handle action popup results for JSON LSP help
107
+ */
108
+ globalThis.on_json_lsp_action_result = function (
109
+ data: ActionPopupResultData
110
+ ): void {
111
+ // Only handle our popup
112
+ if (data.popup_id !== "json-lsp-help") {
113
+ return;
114
+ }
115
+
116
+ editor.debug(`json-lsp: Action selected - ${data.action_id}`);
117
+
118
+ switch (data.action_id) {
119
+ case "copy_npm":
120
+ editor.setClipboard(INSTALL_COMMANDS.npm);
121
+ editor.setStatus("Copied: " + INSTALL_COMMANDS.npm);
122
+ break;
123
+
124
+ case "disable":
125
+ editor.disableLspForLanguage("json");
126
+ editor.setStatus("JSON LSP disabled");
127
+ jsonLspError = null;
128
+ break;
129
+
130
+ case "dismiss":
131
+ case "dismissed":
132
+ // Just close the popup without action
133
+ break;
134
+
135
+ default:
136
+ editor.debug(`json-lsp: Unknown action: ${data.action_id}`);
137
+ }
138
+ };
139
+
140
+ // Register hook for action popup results
141
+ editor.on("action_popup_result", "on_json_lsp_action_result");
142
+
143
+ editor.debug("json-lsp: Plugin loaded");
@@ -294,6 +294,26 @@ interface CreateVirtualBufferInCurrentSplitOptions {
294
294
  editing_disabled?: boolean | null;
295
295
  }
296
296
 
297
+ /** JavaScript representation of ActionSpec (with optional count) */
298
+ interface ActionSpecJs {
299
+ action: string;
300
+ count?: number | null;
301
+ }
302
+
303
+ /** TypeScript struct for action popup action */
304
+ interface TsActionPopupAction {
305
+ id: string;
306
+ label: string;
307
+ }
308
+
309
+ /** TypeScript struct for action popup options */
310
+ interface TsActionPopupOptions {
311
+ id: string;
312
+ title: string;
313
+ message: string;
314
+ actions: TsActionPopupAction[];
315
+ }
316
+
297
317
  /**
298
318
  * Main editor API interface
299
319
  */
@@ -402,6 +422,8 @@ interface EditorAPI {
402
422
  * @returns true if process is running, false if not found or exited
403
423
  */
404
424
  isProcessRunning(#[bigint] process_id: number): boolean;
425
+ /** Compute syntax highlighting for a buffer range */
426
+ getHighlights(buffer_id: number, start: number, end: number): Promise<TsHighlightSpan[]>;
405
427
  /** Get diff vs last saved snapshot for a buffer */
406
428
  getBufferSavedDiff(buffer_id: number): TsBufferSavedDiff | null;
407
429
  /**
@@ -409,6 +431,22 @@ interface EditorAPI {
409
431
  * @returns Array of Diagnostic objects with file URI, severity, message, and range
410
432
  */
411
433
  getAllDiagnostics(): TsDiagnostic[];
434
+ /**
435
+ * Get text from a buffer range
436
+ *
437
+ * Used by vi mode plugin for yank operations - reads text without deleting.
438
+ * @param buffer_id - Buffer ID
439
+ * @param start - Start byte offset
440
+ * @param end - End byte offset
441
+ * @returns Text content of the range, or empty string on error
442
+ */
443
+ getBufferText(buffer_id: number, start: number, end: number): Promise<string>;
444
+ /**
445
+ * Get the current global editor mode
446
+ *
447
+ * @returns Current mode name or null if no mode is active
448
+ */
449
+ getEditorMode(): string;
412
450
 
413
451
  // === Buffer Info Queries ===
414
452
  /**
@@ -661,6 +699,8 @@ interface EditorAPI {
661
699
  * await editor.delay(100); // Wait 100ms
662
700
  */
663
701
  delay(#[bigint] ms: number): Promise<[]>;
702
+ /** Find a buffer ID by its file path */
703
+ findBufferByPath(path: string): number;
664
704
  /**
665
705
  * Start a prompt with pre-filled initial value
666
706
  * @param label - Label to display (e.g., "Git grep: ")
@@ -677,6 +717,13 @@ interface EditorAPI {
677
717
  * @returns Promise resolving to the JSON response value
678
718
  */
679
719
  sendLspRequest(language: string, method: string, params?: unknown | null): Promise<unknown>;
720
+ /**
721
+ * Set the scroll position of a specific split
722
+ * @param split_id - The split ID
723
+ * @param top_byte - The byte offset of the top visible line
724
+ * @returns true if successful
725
+ */
726
+ setSplitScroll(split_id: number, top_byte: number): boolean;
680
727
  /**
681
728
  * Set the ratio of a split container
682
729
  * @param split_id - ID of the split
@@ -697,6 +744,55 @@ interface EditorAPI {
697
744
  * @returns true if the command was sent successfully
698
745
  */
699
746
  setBufferCursor(buffer_id: number, position: number): boolean;
747
+ /**
748
+ * Execute a built-in editor action by name
749
+ *
750
+ * This is used by vi mode plugin to run motions and then check cursor position.
751
+ * For example, to implement "dw" (delete word), the plugin:
752
+ * 1. Saves current cursor position
753
+ * 2. Calls executeAction("move_word_right") - cursor moves
754
+ * 3. Gets new cursor position
755
+ * 4. Deletes from old to new position
756
+ *
757
+ * @param action_name - Action name (e.g., "move_word_right", "move_line_end")
758
+ * @returns true if action was sent successfully
759
+ */
760
+ executeAction(action_name: string): boolean;
761
+ /**
762
+ * Execute multiple actions in sequence, each with an optional repeat count
763
+ *
764
+ * Used by vi mode for count prefix (e.g., "3dw" = delete 3 words).
765
+ * All actions execute atomically with no plugin roundtrips between them.
766
+ *
767
+ * @param actions - Array of {action: string, count?: number} objects
768
+ * @returns true if actions were sent successfully
769
+ */
770
+ executeActions(actions: ActionSpecJs[]): boolean;
771
+ /**
772
+ * Set the global editor mode (for modal editing like vi mode)
773
+ *
774
+ * When a mode is set, its keybindings take precedence over normal key handling.
775
+ * Pass null/undefined to clear the mode and return to normal editing.
776
+ *
777
+ * @param mode - Mode name (e.g., "vi-normal") or null to clear
778
+ * @returns true if command was sent successfully
779
+ */
780
+ setEditorMode(mode?: string | null): boolean;
781
+ /**
782
+ * Show an action popup with buttons for user interaction
783
+ *
784
+ * When the user selects an action, the ActionPopupResult hook is fired.
785
+ * @param options - Popup configuration with id, title, message, and actions
786
+ */
787
+ showActionPopup(options: TsActionPopupOptions): boolean;
788
+ /**
789
+ * Disable LSP for a specific language and persist to config
790
+ *
791
+ * This is used by LSP helper plugins to let users disable LSP for languages
792
+ * where the server is not available or not working.
793
+ * @param language - The language to disable LSP for (e.g., "python", "rust")
794
+ */
795
+ disableLspForLanguage(language: string): boolean;
700
796
 
701
797
  /**
702
798
  * Spawn an external process and return a cancellable handle
@@ -736,7 +832,7 @@ interface EditorAPI {
736
832
  * @param italic - Use italic text
737
833
  * @returns true if overlay was added
738
834
  */
739
- addOverlay(buffer_id: number, namespace: string, start: number, end: number, r: number, g: number, b: number, underline: boolean, bold: boolean, italic: boolean): boolean;
835
+ addOverlay(buffer_id: number, namespace: string, start: number, end: number, r: number, g: number, b: number, bg_r: i16, bg_g: i16, bg_b: i16, underline: boolean, bold: boolean, italic: boolean): boolean;
740
836
  /**
741
837
  * Remove a specific overlay by its handle
742
838
  * @param buffer_id - The buffer ID
@@ -1011,7 +1107,7 @@ interface EditorAPI {
1011
1107
  * ["q", "close_buffer"]
1012
1108
  * ], true);
1013
1109
  */
1014
- defineMode(name: string, parent?: string | null, bindings: Vec<(String, String): boolean;
1110
+ defineMode(name: string, parent: string, bindings: Vec<(String, String): boolean;
1015
1111
  /**
1016
1112
  * Switch the current split to display a buffer
1017
1113
  * @param buffer_id - ID of the buffer to show
@@ -0,0 +1,160 @@
1
+ /// <reference path="./lib/fresh.d.ts" />
2
+
3
+ /**
4
+ * Python LSP Helper Plugin
5
+ *
6
+ * Provides user-friendly error handling for Python LSP server issues.
7
+ * When the Python LSP server fails to start, this plugin shows an
8
+ * actionable popup with installation instructions.
9
+ *
10
+ * Features:
11
+ * - Detects Python LSP server errors (pylsp, python-lsp-server)
12
+ * - Shows popup with install commands (pip, pipx)
13
+ * - Allows copying install commands to clipboard
14
+ * - Provides option to disable Python LSP
15
+ */
16
+
17
+ interface LspServerErrorData {
18
+ language: string;
19
+ server_command: string;
20
+ error_type: string;
21
+ message: string;
22
+ }
23
+
24
+ interface LspStatusClickedData {
25
+ language: string;
26
+ has_error: boolean;
27
+ }
28
+
29
+ interface ActionPopupResultData {
30
+ popup_id: string;
31
+ action_id: string;
32
+ }
33
+
34
+ // Install commands for Python LSP server (python-lsp-server / pylsp)
35
+ // pipx provides isolated installation (recommended)
36
+ // pip_all includes all optional dependencies (rope, pyflakes, etc.)
37
+ // See: https://github.com/python-lsp/python-lsp-server
38
+ const INSTALL_COMMANDS = {
39
+ pipx: "pipx install python-lsp-server",
40
+ pip: "pip install python-lsp-server",
41
+ pip_all: "pip install 'python-lsp-server[all]'",
42
+ };
43
+
44
+ // Track error state for Python LSP
45
+ let pythonLspError: { serverCommand: string; message: string } | null = null;
46
+
47
+ /**
48
+ * Handle LSP server errors for Python
49
+ */
50
+ globalThis.on_python_lsp_server_error = function (
51
+ data: LspServerErrorData
52
+ ): void {
53
+ // Only handle Python language errors
54
+ if (data.language !== "python") {
55
+ return;
56
+ }
57
+
58
+ editor.debug(
59
+ `python-lsp: Server error - ${data.error_type}: ${data.message}`
60
+ );
61
+
62
+ // Store error state for later reference
63
+ pythonLspError = {
64
+ serverCommand: data.server_command,
65
+ message: data.message,
66
+ };
67
+
68
+ // Show a status message for immediate feedback
69
+ if (data.error_type === "not_found") {
70
+ editor.setStatus(
71
+ `Python LSP server '${data.server_command}' not found. Click status bar for help.`
72
+ );
73
+ } else {
74
+ editor.setStatus(`Python LSP error: ${data.message}`);
75
+ }
76
+ };
77
+
78
+ // Register hook for LSP server errors
79
+ editor.on("lsp_server_error", "on_python_lsp_server_error");
80
+
81
+ /**
82
+ * Handle status bar click when there's a Python LSP error
83
+ */
84
+ globalThis.on_python_lsp_status_clicked = function (
85
+ data: LspStatusClickedData
86
+ ): void {
87
+ // Only handle Python language clicks when there's an error
88
+ if (data.language !== "python" || !pythonLspError) {
89
+ return;
90
+ }
91
+
92
+ editor.debug("python-lsp: Status clicked, showing help popup");
93
+
94
+ // Show action popup with install options
95
+ editor.showActionPopup({
96
+ id: "python-lsp-help",
97
+ title: "Python Language Server Not Found",
98
+ message: `"${pythonLspError.serverCommand}" provides code completion, diagnostics, and navigation for Python files. Copy a command below to install it, or search online for your platform.`,
99
+ actions: [
100
+ { id: "copy_pipx", label: `Copy: ${INSTALL_COMMANDS.pipx}` },
101
+ { id: "copy_pip", label: `Copy: ${INSTALL_COMMANDS.pip}` },
102
+ { id: "copy_pip_all", label: `Copy: ${INSTALL_COMMANDS.pip_all}` },
103
+ { id: "disable", label: "Disable Python LSP" },
104
+ { id: "dismiss", label: "Dismiss (ESC)" },
105
+ ],
106
+ });
107
+ };
108
+
109
+ // Register hook for status bar clicks
110
+ editor.on("lsp_status_clicked", "on_python_lsp_status_clicked");
111
+
112
+ /**
113
+ * Handle action popup results for Python LSP help
114
+ */
115
+ globalThis.on_python_lsp_action_result = function (
116
+ data: ActionPopupResultData
117
+ ): void {
118
+ // Only handle our popup
119
+ if (data.popup_id !== "python-lsp-help") {
120
+ return;
121
+ }
122
+
123
+ editor.debug(`python-lsp: Action selected - ${data.action_id}`);
124
+
125
+ switch (data.action_id) {
126
+ case "copy_pipx":
127
+ editor.setClipboard(INSTALL_COMMANDS.pipx);
128
+ editor.setStatus("Copied: " + INSTALL_COMMANDS.pipx);
129
+ break;
130
+
131
+ case "copy_pip":
132
+ editor.setClipboard(INSTALL_COMMANDS.pip);
133
+ editor.setStatus("Copied: " + INSTALL_COMMANDS.pip);
134
+ break;
135
+
136
+ case "copy_pip_all":
137
+ editor.setClipboard(INSTALL_COMMANDS.pip_all);
138
+ editor.setStatus("Copied: " + INSTALL_COMMANDS.pip_all);
139
+ break;
140
+
141
+ case "disable":
142
+ editor.disableLspForLanguage("python");
143
+ editor.setStatus("Python LSP disabled");
144
+ pythonLspError = null;
145
+ break;
146
+
147
+ case "dismiss":
148
+ case "dismissed":
149
+ // Just close the popup without action
150
+ break;
151
+
152
+ default:
153
+ editor.debug(`python-lsp: Unknown action: ${data.action_id}`);
154
+ }
155
+ };
156
+
157
+ // Register hook for action popup results
158
+ editor.on("action_popup_result", "on_python_lsp_action_result");
159
+
160
+ editor.debug("python-lsp: Plugin loaded");