@fresh-editor/fresh-editor 0.1.86 → 0.1.87

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.
@@ -110,20 +110,20 @@ export class PanelManager {
110
110
  const result = await this.editor.createVirtualBufferInSplit({
111
111
  name: this.panelName,
112
112
  mode: this.modeName,
113
- read_only: true,
113
+ readOnly: true,
114
114
  entries,
115
115
  ratio,
116
- panel_id: this.panelName,
117
- show_line_numbers: showLineNumbers,
118
- editing_disabled: editingDisabled,
116
+ panelId: this.panelName,
117
+ showLineNumbers: showLineNumbers,
118
+ editingDisabled: editingDisabled,
119
119
  });
120
120
 
121
121
  // Track state
122
- this.state.bufferId = result.buffer_id;
123
- this.state.splitId = result.split_id ?? this.editor.getActiveSplitId();
122
+ this.state.bufferId = result.bufferId;
123
+ this.state.splitId = result.splitId ?? this.editor.getActiveSplitId();
124
124
  this.state.isOpen = true;
125
125
 
126
- return result.buffer_id;
126
+ return result.bufferId;
127
127
  }
128
128
 
129
129
  /**
@@ -41,14 +41,14 @@ interface EditorApi {
41
41
  createVirtualBufferInSplit(options: {
42
42
  name: string;
43
43
  mode: string;
44
- read_only: boolean;
44
+ readOnly: boolean;
45
45
  entries: TextPropertyEntry[];
46
46
  ratio: number;
47
47
  direction: string;
48
- panel_id: string;
49
- show_line_numbers: boolean;
50
- editing_disabled: boolean;
51
- }): Promise<{ buffer_id: number; split_id?: number }>;
48
+ panelId: string;
49
+ showLineNumbers: boolean;
50
+ editingDisabled: boolean;
51
+ }): Promise<{ bufferId: number; splitId?: number }>;
52
52
  setVirtualBufferContent(bufferId: number, entries: TextPropertyEntry[]): void;
53
53
  closeBuffer(bufferId: number): void;
54
54
  closeSplit(splitId: number): void;
@@ -137,17 +137,17 @@ export class SearchPreview {
137
137
  const result = await this.editor.createVirtualBufferInSplit({
138
138
  name: "*Preview*",
139
139
  mode: this.modeName,
140
- read_only: true,
140
+ readOnly: true,
141
141
  entries,
142
142
  ratio: 0.5,
143
143
  direction: "vertical",
144
- panel_id: this.panelId,
145
- show_line_numbers: false,
146
- editing_disabled: true,
144
+ panelId: this.panelId,
145
+ showLineNumbers: false,
146
+ editingDisabled: true,
147
147
  });
148
148
 
149
- this.bufferId = result.buffer_id;
150
- this.splitId = result.split_id ?? null;
149
+ this.bufferId = result.bufferId;
150
+ this.splitId = result.splitId ?? null;
151
151
 
152
152
  // Return focus to original split so prompt stays active
153
153
  if (this.originalSplitId !== null) {
@@ -196,7 +196,7 @@ export class SearchPreview {
196
196
  * - Tracks search version to discard stale results
197
197
  */
198
198
  export class DebouncedSearch {
199
- private currentSearch: ProcessHandle | null = null;
199
+ private currentSearch: ProcessHandle<SpawnResult> | null = null;
200
200
  private pendingKill: Promise<boolean> | null = null;
201
201
  private searchVersion = 0;
202
202
  private lastQuery = "";
@@ -216,7 +216,7 @@ export class DebouncedSearch {
216
216
  */
217
217
  async search(
218
218
  query: string,
219
- executor: () => ProcessHandle,
219
+ executor: () => ProcessHandle<SpawnResult>,
220
220
  onResults: (result: SpawnResult) => void
221
221
  ): Promise<void> {
222
222
  const thisVersion = ++this.searchVersion;
@@ -59,14 +59,15 @@ export function createVirtualBufferFactory(editor: EditorAPI) {
59
59
  readOnly = true,
60
60
  } = options;
61
61
 
62
- return await editor.createVirtualBuffer({
62
+ const result = await editor.createVirtualBuffer({
63
63
  name,
64
64
  mode,
65
- read_only: readOnly,
65
+ readOnly,
66
66
  entries,
67
- show_line_numbers: showLineNumbers,
68
- editing_disabled: editingDisabled,
67
+ showLineNumbers,
68
+ editingDisabled,
69
69
  });
70
+ return result.bufferId;
70
71
  },
71
72
 
72
73
  /**
@@ -82,15 +83,16 @@ export function createVirtualBufferFactory(editor: EditorAPI) {
82
83
  readOnly = true,
83
84
  } = options;
84
85
 
85
- return await editor.createVirtualBufferInExistingSplit({
86
+ const result = await editor.createVirtualBufferInExistingSplit({
86
87
  name,
87
88
  mode,
88
- read_only: readOnly,
89
+ readOnly,
89
90
  entries,
90
- split_id: splitId,
91
- show_line_numbers: showLineNumbers,
92
- editing_disabled: editingDisabled,
91
+ splitId,
92
+ showLineNumbers,
93
+ editingDisabled,
93
94
  });
95
+ return result.bufferId;
94
96
  },
95
97
 
96
98
  /**
@@ -111,14 +113,14 @@ export function createVirtualBufferFactory(editor: EditorAPI) {
111
113
  const result = await editor.createVirtualBufferInSplit({
112
114
  name,
113
115
  mode,
114
- read_only: readOnly,
116
+ readOnly,
115
117
  entries,
116
118
  ratio,
117
- panel_id: panelId,
118
- show_line_numbers: showLineNumbers,
119
- editing_disabled: editingDisabled,
119
+ panelId,
120
+ showLineNumbers,
121
+ editingDisabled,
120
122
  });
121
- return result.buffer_id;
123
+ return result.bufferId;
122
124
  },
123
125
 
124
126
  /**
@@ -334,7 +334,7 @@ function disableMarkdownCompose(bufferId: number): void {
334
334
  editor.setLineNumbers(bufferId, true);
335
335
 
336
336
  // Clear view transform to return to normal rendering
337
- editor.clearViewTransform(bufferId);
337
+ editor.clearViewTransform(bufferId, null);
338
338
 
339
339
  editor.refreshLines(bufferId);
340
340
  editor.debug(`Markdown compose disabled for buffer ${bufferId}`);
@@ -535,10 +535,10 @@ globalThis.onMarkdownViewTransform = function(data: {
535
535
  data.viewport_start
536
536
  );
537
537
 
538
- // Submit the transformed tokens - keep compose_width for margins/centering
538
+ // Submit the transformed tokens - keep composeWidth for margins/centering
539
539
  const layoutHints: LayoutHints = {
540
- compose_width: config.composeWidth,
541
- column_guides: null,
540
+ composeWidth: config.composeWidth,
541
+ columnGuides: null,
542
542
  };
543
543
 
544
544
  editor.submitViewTransform(
@@ -0,0 +1,65 @@
1
+ /// <reference path="./lib/fresh.d.ts" />
2
+ // Provides installation help when marksman (Markdown LSP) is not found
3
+ const editor = getEditor();
4
+
5
+ interface LspServerErrorData {
6
+ language: string;
7
+ server_command: string;
8
+ error_type: string;
9
+ message: string;
10
+ }
11
+
12
+ interface LspStatusClickedData {
13
+ language: string;
14
+ has_error: boolean;
15
+ }
16
+
17
+ interface ActionPopupResultData {
18
+ popup_id: string;
19
+ action_id: string;
20
+ }
21
+
22
+ const INSTALL_URL = "https://github.com/artempyanykh/marksman#how-to-install";
23
+ let markdownLspError: { serverCommand: string; message: string } | null = null;
24
+
25
+ globalThis.on_markdown_lsp_server_error = function (data: LspServerErrorData): void {
26
+ if (data.language !== "markdown") return;
27
+ markdownLspError = { serverCommand: data.server_command, message: data.message };
28
+ if (data.error_type === "not_found") {
29
+ editor.setStatus(`Markdown LSP '${data.server_command}' not found. Click status bar for help.`);
30
+ } else {
31
+ editor.setStatus(`Markdown LSP error: ${data.message}`);
32
+ }
33
+ };
34
+ editor.on("lsp_server_error", "on_markdown_lsp_server_error");
35
+
36
+ globalThis.on_markdown_lsp_status_clicked = function (data: LspStatusClickedData): void {
37
+ if (data.language !== "markdown" || !markdownLspError) return;
38
+ editor.showActionPopup({
39
+ id: "marksman-lsp-help",
40
+ title: "Markdown Language Server Not Found",
41
+ message: `Install marksman for wiki-links and navigation. Visit ${INSTALL_URL}`,
42
+ actions: [
43
+ { id: "copy_url", label: "Copy install URL" },
44
+ { id: "disable", label: "Disable Markdown LSP" },
45
+ { id: "dismiss", label: "Dismiss (ESC)" },
46
+ ],
47
+ });
48
+ };
49
+ editor.on("lsp_status_clicked", "on_markdown_lsp_status_clicked");
50
+
51
+ globalThis.on_markdown_lsp_action_result = function (data: ActionPopupResultData): void {
52
+ if (data.popup_id !== "marksman-lsp-help") return;
53
+ switch (data.action_id) {
54
+ case "copy_url":
55
+ editor.setClipboard(INSTALL_URL);
56
+ editor.setStatus("Copied: " + INSTALL_URL);
57
+ break;
58
+ case "disable":
59
+ editor.disableLspForLanguage("markdown");
60
+ editor.setStatus("Markdown LSP disabled");
61
+ markdownLspError = null;
62
+ break;
63
+ }
64
+ };
65
+ editor.on("action_popup_result", "on_markdown_lsp_action_result");
@@ -1335,18 +1335,18 @@ async function createMergePanels(): Promise<void> {
1335
1335
 
1336
1336
  // Create OURS panel first (takes over current view)
1337
1337
  // Include extension in name so tree-sitter can apply highlighting
1338
- const oursId = await editor.createVirtualBuffer({
1338
+ const oursResult = await editor.createVirtualBuffer({
1339
1339
  name: `*OURS*${sourceExt}`,
1340
1340
  mode: "merge-conflict",
1341
- read_only: true,
1341
+ readOnly: true,
1342
1342
  entries: buildFullFileEntries("ours"),
1343
- show_line_numbers: true,
1344
- show_cursors: true,
1345
- editing_disabled: true,
1343
+ showLineNumbers: true,
1344
+ showCursors: true,
1345
+ editingDisabled: true,
1346
1346
  });
1347
1347
 
1348
- if (oursId !== null) {
1349
- mergeState.oursPanelId = oursId;
1348
+ if (oursResult !== null) {
1349
+ mergeState.oursPanelId = oursResult.bufferId;
1350
1350
  mergeState.oursSplitId = editor.getActiveSplitId();
1351
1351
  }
1352
1352
 
@@ -1354,19 +1354,19 @@ async function createMergePanels(): Promise<void> {
1354
1354
  const theirsResult = await editor.createVirtualBufferInSplit({
1355
1355
  name: `*THEIRS*${sourceExt}`,
1356
1356
  mode: "merge-conflict",
1357
- read_only: true,
1357
+ readOnly: true,
1358
1358
  entries: buildFullFileEntries("theirs"),
1359
1359
  ratio: 0.5, // Will be equalized by distributeSplitsEvenly
1360
1360
  direction: "vertical",
1361
- panel_id: "merge-theirs",
1362
- show_line_numbers: true,
1363
- show_cursors: true,
1364
- editing_disabled: true,
1361
+ panelId: "merge-theirs",
1362
+ showLineNumbers: true,
1363
+ showCursors: true,
1364
+ editingDisabled: true,
1365
1365
  });
1366
1366
 
1367
1367
  if (theirsResult !== null) {
1368
- mergeState.theirsPanelId = theirsResult.buffer_id;
1369
- mergeState.theirsSplitId = theirsResult.split_id ?? editor.getActiveSplitId();
1368
+ mergeState.theirsPanelId = theirsResult.bufferId;
1369
+ mergeState.theirsSplitId = theirsResult.splitId ?? editor.getActiveSplitId();
1370
1370
  }
1371
1371
 
1372
1372
  // Focus back on OURS and create RESULT in the middle
@@ -1377,19 +1377,19 @@ async function createMergePanels(): Promise<void> {
1377
1377
  const resultResult = await editor.createVirtualBufferInSplit({
1378
1378
  name: `*RESULT*${sourceExt}`,
1379
1379
  mode: "merge-result",
1380
- read_only: false,
1380
+ readOnly: false,
1381
1381
  entries: buildResultFileEntries(),
1382
1382
  ratio: 0.5, // Will be equalized by distributeSplitsEvenly
1383
1383
  direction: "vertical",
1384
- panel_id: "merge-result",
1385
- show_line_numbers: true,
1386
- show_cursors: true,
1387
- editing_disabled: false,
1384
+ panelId: "merge-result",
1385
+ showLineNumbers: true,
1386
+ showCursors: true,
1387
+ editingDisabled: false,
1388
1388
  });
1389
1389
 
1390
1390
  if (resultResult !== null) {
1391
- mergeState.resultPanelId = resultResult.buffer_id;
1392
- mergeState.resultSplitId = resultResult.split_id ?? editor.getActiveSplitId();
1391
+ mergeState.resultPanelId = resultResult.bufferId;
1392
+ mergeState.resultSplitId = resultResult.splitId ?? editor.getActiveSplitId();
1393
1393
  }
1394
1394
 
1395
1395
  // Distribute splits evenly so all three panels get equal width
@@ -229,15 +229,15 @@ async function showResultsPanel(): Promise<void> {
229
229
  const result = await editor.createVirtualBufferInSplit({
230
230
  name: "*Search/Replace*",
231
231
  mode: "search-replace-list",
232
- read_only: true,
232
+ readOnly: true,
233
233
  entries: entries,
234
234
  ratio: 0.6, // 60/40 split
235
- panel_id: "search-replace-panel",
236
- show_line_numbers: false,
237
- show_cursors: true,
235
+ panelId: "search-replace-panel",
236
+ showLineNumbers: false,
237
+ showCursors: true,
238
238
  });
239
- resultsBufferId = result.buffer_id;
240
- resultsSplitId = result.split_id ?? editor.getActiveSplitId();
239
+ resultsBufferId = result.bufferId;
240
+ resultsSplitId = result.splitId ?? editor.getActiveSplitId();
241
241
 
242
242
  panelOpen = true;
243
243
  editor.debug(`Search/Replace panel opened with buffer ID ${resultsBufferId}`);
@@ -0,0 +1,65 @@
1
+ /// <reference path="./lib/fresh.d.ts" />
2
+ // Provides installation help when templ LSP is not found
3
+ const editor = getEditor();
4
+
5
+ interface LspServerErrorData {
6
+ language: string;
7
+ server_command: string;
8
+ error_type: string;
9
+ message: string;
10
+ }
11
+
12
+ interface LspStatusClickedData {
13
+ language: string;
14
+ has_error: boolean;
15
+ }
16
+
17
+ interface ActionPopupResultData {
18
+ popup_id: string;
19
+ action_id: string;
20
+ }
21
+
22
+ const INSTALL_URL = "https://templ.guide/quick-start/installation";
23
+ let templLspError: { serverCommand: string; message: string } | null = null;
24
+
25
+ globalThis.on_templ_lsp_server_error = function (data: LspServerErrorData): void {
26
+ if (data.language !== "templ") return;
27
+ templLspError = { serverCommand: data.server_command, message: data.message };
28
+ if (data.error_type === "not_found") {
29
+ editor.setStatus(`Templ LSP '${data.server_command}' not found. Click status bar for help.`);
30
+ } else {
31
+ editor.setStatus(`Templ LSP error: ${data.message}`);
32
+ }
33
+ };
34
+ editor.on("lsp_server_error", "on_templ_lsp_server_error");
35
+
36
+ globalThis.on_templ_lsp_status_clicked = function (data: LspStatusClickedData): void {
37
+ if (data.language !== "templ" || !templLspError) return;
38
+ editor.showActionPopup({
39
+ id: "templ-lsp-help",
40
+ title: "Templ Language Server Not Found",
41
+ message: `Install templ for code completion and diagnostics. Visit ${INSTALL_URL}`,
42
+ actions: [
43
+ { id: "copy_url", label: "Copy install URL" },
44
+ { id: "disable", label: "Disable Templ LSP" },
45
+ { id: "dismiss", label: "Dismiss (ESC)" },
46
+ ],
47
+ });
48
+ };
49
+ editor.on("lsp_status_clicked", "on_templ_lsp_status_clicked");
50
+
51
+ globalThis.on_templ_lsp_action_result = function (data: ActionPopupResultData): void {
52
+ if (data.popup_id !== "templ-lsp-help") return;
53
+ switch (data.action_id) {
54
+ case "copy_url":
55
+ editor.setClipboard(INSTALL_URL);
56
+ editor.setStatus("Copied: " + INSTALL_URL);
57
+ break;
58
+ case "disable":
59
+ editor.disableLspForLanguage("templ");
60
+ editor.setStatus("Templ LSP disabled");
61
+ templLspError = null;
62
+ break;
63
+ }
64
+ };
65
+ editor.on("action_popup_result", "on_templ_lsp_action_result");
@@ -1734,15 +1734,16 @@ async function doOpenThemeEditor(): Promise<void> {
1734
1734
 
1735
1735
  // Create virtual buffer in current split (no new split)
1736
1736
  editor.debug("[theme_editor] doOpenThemeEditor: calling createVirtualBuffer...");
1737
- const bufferId = await editor.createVirtualBuffer({
1737
+ const result = await editor.createVirtualBuffer({
1738
1738
  name: "*Theme Editor*",
1739
1739
  mode: "theme-editor",
1740
- read_only: true,
1740
+ readOnly: true,
1741
1741
  entries: entries,
1742
- show_line_numbers: false,
1743
- show_cursors: true,
1744
- editing_disabled: true,
1742
+ showLineNumbers: false,
1743
+ showCursors: true,
1744
+ editingDisabled: true,
1745
1745
  });
1746
+ const bufferId = result.bufferId;
1746
1747
  editor.debug(`[theme_editor] doOpenThemeEditor: createVirtualBuffer returned bufferId=${bufferId}`);
1747
1748
  editor.debug(`[theme_editor] doOpenThemeEditor: checking if bufferId !== null...`);
1748
1749
 
@@ -795,7 +795,7 @@ globalThis.vi_visual_toggle_line = function (): void {
795
795
  };
796
796
 
797
797
  // Enter visual block mode (Ctrl-v)
798
- globalThis.vi_visual_block = function (): void {
798
+ globalThis.vi_visual_block = async function (): Promise<void> {
799
799
  // Store anchor position for block selection
800
800
  state.visualAnchor = editor.getCursorPosition();
801
801
 
@@ -803,7 +803,7 @@ globalThis.vi_visual_block = function (): void {
803
803
  const cursorPos = editor.getCursorPosition();
804
804
  if (cursorPos !== null) {
805
805
  const line = editor.getCursorLine() ?? 1;
806
- const lineStart = editor.getLineStartPosition(line);
806
+ const lineStart = await editor.getLineStartPosition(line);
807
807
  const col = lineStart !== null ? cursorPos - lineStart : 0;
808
808
  state.visualBlockAnchor = { line, col };
809
809
  }
@@ -0,0 +1,65 @@
1
+ /// <reference path="./lib/fresh.d.ts" />
2
+ // Provides installation help when zls (Zig LSP) is not found
3
+ const editor = getEditor();
4
+
5
+ interface LspServerErrorData {
6
+ language: string;
7
+ server_command: string;
8
+ error_type: string;
9
+ message: string;
10
+ }
11
+
12
+ interface LspStatusClickedData {
13
+ language: string;
14
+ has_error: boolean;
15
+ }
16
+
17
+ interface ActionPopupResultData {
18
+ popup_id: string;
19
+ action_id: string;
20
+ }
21
+
22
+ const INSTALL_URL = "https://github.com/zigtools/zls#installation";
23
+ let zigLspError: { serverCommand: string; message: string } | null = null;
24
+
25
+ globalThis.on_zig_lsp_server_error = function (data: LspServerErrorData): void {
26
+ if (data.language !== "zig") return;
27
+ zigLspError = { serverCommand: data.server_command, message: data.message };
28
+ if (data.error_type === "not_found") {
29
+ editor.setStatus(`Zig LSP '${data.server_command}' not found. Click status bar for help.`);
30
+ } else {
31
+ editor.setStatus(`Zig LSP error: ${data.message}`);
32
+ }
33
+ };
34
+ editor.on("lsp_server_error", "on_zig_lsp_server_error");
35
+
36
+ globalThis.on_zig_lsp_status_clicked = function (data: LspStatusClickedData): void {
37
+ if (data.language !== "zig" || !zigLspError) return;
38
+ editor.showActionPopup({
39
+ id: "zig-lsp-help",
40
+ title: "Zig Language Server Not Found",
41
+ message: `Install zls for code completion and diagnostics. Visit ${INSTALL_URL}`,
42
+ actions: [
43
+ { id: "copy_url", label: "Copy install URL" },
44
+ { id: "disable", label: "Disable Zig LSP" },
45
+ { id: "dismiss", label: "Dismiss (ESC)" },
46
+ ],
47
+ });
48
+ };
49
+ editor.on("lsp_status_clicked", "on_zig_lsp_status_clicked");
50
+
51
+ globalThis.on_zig_lsp_action_result = function (data: ActionPopupResultData): void {
52
+ if (data.popup_id !== "zig-lsp-help") return;
53
+ switch (data.action_id) {
54
+ case "copy_url":
55
+ editor.setClipboard(INSTALL_URL);
56
+ editor.setStatus("Copied: " + INSTALL_URL);
57
+ break;
58
+ case "disable":
59
+ editor.disableLspForLanguage("zig");
60
+ editor.setStatus("Zig LSP disabled");
61
+ zigLspError = null;
62
+ break;
63
+ }
64
+ };
65
+ editor.on("action_popup_result", "on_zig_lsp_action_result");