@fresh-editor/fresh-editor 0.1.77 → 0.1.86

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,64 @@
1
1
  # Release Notes
2
2
 
3
+ ## 0.1.86
4
+
5
+ ### Features
6
+
7
+ * **Popup Text Selection**: Select and copy text from LSP hover popups and tooltips. Click and drag to select, Ctrl+C to copy.
8
+ * **File Explorer Status Tooltips**: Hover over git status indicators (M, U, A) to see detailed explanations and diff stats. Directory tooltips show list of modified files.
9
+ * **Terminal Background Transparency**: New `use_terminal_bg` config option allows terminal transparency or custom backgrounds to show through the editor (#640).
10
+ * **Vi Mode Improvements**: Added `:w filename` to save to path, `:wq filename` to save and quit, `:q!` to force quit without saving. Added Ctrl+P (command palette) and Ctrl+Q (quit) to all vi modes.
11
+
12
+ ### Bug Fixes
13
+
14
+ * **Settings UI Add Button**: Fixed "Add New" button not appearing for LSP and Languages maps in Settings UI.
15
+ * **LSP Hover Markdown**: Improved markdown rendering - soft breaks now create newlines (fixing Python docstring formatting), inline code rendered without visible backticks.
16
+ * **Symlink Directories**: Fixed symlinks to directories not showing expand marker and causing "Is a directory" error when opened (#787).
17
+ * **Live Grep Preview**: Fixed preview not updating when navigating through search results (#636).
18
+ * **Terminal Keyboard State**: Fixed arrow keys and Enter not working after exiting the editor due to Kitty keyboard protocol cleanup issue (#773).
19
+ * **Plugin Commands Visibility**: Fixed many plugin commands (Toggle Vi Mode, Git Blame, Diagnostics Panel, etc.) not appearing in command palette.
20
+
21
+ ### UI Changes
22
+
23
+ * **File Explorer Layout**: Git status indicators moved to rightmost column, matching VS Code's layout. Removed file size and item count for cleaner appearance.
24
+ * **Quieter Startup**: Removed plugin "ready/loaded" status messages that cluttered the status bar on startup.
25
+
26
+ ### Internal
27
+
28
+ * Separated I/O from pure types in theme and grammar modules for better testability and future WASM compatibility.
29
+ * Fixed workspace crate dependencies for crates.io publishing.
30
+ * Improved install.sh reliability for containers and edge cases.
31
+
32
+ ---
33
+
34
+ ## 0.1.83
35
+
36
+ ### Breaking Changes
37
+
38
+ * **QuickJS Plugin Runtime**: Replaced Deno with QuickJS for the plugin system. Each plugin now runs in its own isolated context.
39
+
40
+ ### Features
41
+
42
+ * **Cargo Workspace Architecture**: Refactored into modular crates (fresh-core, fresh-editor, fresh-languages, fresh-parser-js, fresh-plugin-runtime, fresh-plugin-api-macros).
43
+
44
+ ### Bug Fixes
45
+
46
+ * **Toggle Comment YAML**: Fixed toggle comment not working for YAML files by falling back to config-based language detection (#774).
47
+ * **Undo History Panic**: Fixed panic when undoing past a save point and making new edits caused out-of-bounds slice access (#776).
48
+ * **Sudo Save Prompt**: Fixed permission denied crash when saving files owned by another user; now shows sudo prompt correctly (#775).
49
+ * **Musl Plugin Support**: Plugins now work on musl target builds (x86_64/aarch64-unknown-linux-musl).
50
+ * **LSP Server Requests**: Fixed LSP server-to-client request handling not being dispatched to plugins.
51
+ * **Git Find File Selection**: Fixed race condition causing wrong file selection when pressing Enter quickly.
52
+ * **Plugin Cache**: Embedded plugins now cached in XDG cache dir instead of leaking temp directories.
53
+
54
+ ### Internal
55
+
56
+ * Improved compile times via LLVM optimization flag.
57
+ * Cross-platform path handling fixes for Windows.
58
+ * Test reliability improvements.
59
+
60
+ ---
61
+
3
62
  ## 0.1.77
4
63
 
5
64
  ### Documentation
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fresh-editor/fresh-editor",
3
- "version": "0.1.77",
3
+ "version": "0.1.86",
4
4
  "description": "A modern terminal-based text editor with plugin support",
5
5
  "repository": {
6
6
  "type": "git",
@@ -1103,21 +1103,21 @@ globalThis.review_drill_down = async () => {
1103
1103
  const oldBufferId = await editor.createVirtualBuffer({
1104
1104
  name: `*OLD:${h.file}*`,
1105
1105
  mode: "normal",
1106
- read_only: true,
1106
+ readOnly: true,
1107
1107
  entries: oldEntries,
1108
- show_line_numbers: true,
1109
- editing_disabled: true,
1110
- hidden_from_tabs: true
1108
+ showLineNumbers: true,
1109
+ editingDisabled: true,
1110
+ hiddenFromTabs: true
1111
1111
  });
1112
1112
 
1113
1113
  const newBufferId = await editor.createVirtualBuffer({
1114
1114
  name: `*NEW:${h.file}*`,
1115
1115
  mode: "normal",
1116
- read_only: true,
1116
+ readOnly: true,
1117
1117
  entries: newEntries,
1118
- show_line_numbers: true,
1119
- editing_disabled: true,
1120
- hidden_from_tabs: true
1118
+ showLineNumbers: true,
1119
+ editingDisabled: true,
1120
+ hiddenFromTabs: true
1121
1121
  });
1122
1122
 
1123
1123
  // Convert hunks to composite buffer format (parse counts from git diff)
@@ -1493,7 +1493,7 @@ globalThis.start_review_diff = async () => {
1493
1493
  state.comments = []; // Reset comments for new session
1494
1494
 
1495
1495
  const bufferId = await VirtualBufferFactory.create({
1496
- name: "*Review Diff*", mode: "review-mode", read_only: true,
1496
+ name: "*Review Diff*", mode: "review-mode", readOnly: true,
1497
1497
  entries: (await renderReviewStream()).entries, showLineNumbers: false
1498
1498
  });
1499
1499
  state.reviewBufferId = bufferId;
@@ -1666,21 +1666,21 @@ globalThis.side_by_side_diff_current_file = async () => {
1666
1666
  const oldBufferId = await editor.createVirtualBuffer({
1667
1667
  name: `*OLD:${filePath}*`,
1668
1668
  mode: "normal",
1669
- read_only: true,
1669
+ readOnly: true,
1670
1670
  entries: oldEntries,
1671
- show_line_numbers: true,
1672
- editing_disabled: true,
1673
- hidden_from_tabs: true
1671
+ showLineNumbers: true,
1672
+ editingDisabled: true,
1673
+ hiddenFromTabs: true
1674
1674
  });
1675
1675
 
1676
1676
  const newBufferId = await editor.createVirtualBuffer({
1677
1677
  name: `*NEW:${filePath}*`,
1678
1678
  mode: "normal",
1679
- read_only: true,
1679
+ readOnly: true,
1680
1680
  entries: newEntries,
1681
- show_line_numbers: true,
1682
- editing_disabled: true,
1683
- hidden_from_tabs: true
1681
+ showLineNumbers: true,
1682
+ editingDisabled: true,
1683
+ hiddenFromTabs: true
1684
1684
  });
1685
1685
 
1686
1686
  // Convert hunks to composite buffer format
@@ -765,6 +765,5 @@ editor.on("mouse_click", "onCalculatorMouseClick");
765
765
  editor.on("mouse_move", "onCalculatorMouseMove");
766
766
 
767
767
  // Register main command
768
- editor.registerCommand("%cmd.calculator", "%cmd.calculator_desc", "calculator_open", "normal");
768
+ editor.registerCommand("%cmd.calculator", "%cmd.calculator_desc", "calculator_open", null);
769
769
 
770
- editor.setStatus(editor.t("status.loaded"));
@@ -251,7 +251,7 @@ editor.registerCommand(
251
251
  "%cmd.project_setup",
252
252
  "%cmd.project_setup_desc",
253
253
  "clangdProjectSetup",
254
- ""
254
+ null
255
255
  );
256
256
 
257
257
  globalThis.clangdOpenProjectConfig = function(): void {
@@ -287,17 +287,16 @@ editor.registerCommand(
287
287
  "%cmd.switch_source_header",
288
288
  "%cmd.switch_source_header_desc",
289
289
  "clangdSwitchSourceHeader",
290
- "normal"
290
+ null
291
291
  );
292
292
 
293
293
  editor.registerCommand(
294
294
  "%cmd.open_project_config",
295
295
  "%cmd.open_project_config_desc",
296
296
  "clangdOpenProjectConfig",
297
- "normal"
297
+ null
298
298
  );
299
299
 
300
- setClangdStatus(editor.t("status.plugin_loaded"));
301
300
 
302
301
  globalThis.onClangdCustomNotification = function(payload: {
303
302
  language: string;
@@ -285,23 +285,22 @@ editor.registerCommand(
285
285
  "%cmd.enable",
286
286
  "%cmd.enable_desc",
287
287
  "colorHighlighterEnable",
288
- "normal"
288
+ null
289
289
  );
290
290
 
291
291
  editor.registerCommand(
292
292
  "%cmd.disable",
293
293
  "%cmd.disable_desc",
294
294
  "colorHighlighterDisable",
295
- "normal"
295
+ null
296
296
  );
297
297
 
298
298
  editor.registerCommand(
299
299
  "%cmd.toggle",
300
300
  "%cmd.toggle_desc",
301
301
  "colorHighlighterToggle",
302
- "normal"
302
+ null
303
303
  );
304
304
 
305
305
  // Initialization
306
- editor.setStatus(editor.t("status.loaded"));
307
306
  editor.debug("Color Highlighter initialized - supports hex, rgb, hsl, and Rust Color::Rgb");
@@ -59,7 +59,8 @@
59
59
  "keyboard_report_all_keys_as_escape_codes": false,
60
60
  "quick_suggestions": true,
61
61
  "show_menu_bar": true,
62
- "show_tab_bar": true
62
+ "show_tab_bar": true,
63
+ "use_terminal_bg": false
63
64
  }
64
65
  },
65
66
  "file_explorer": {
@@ -349,6 +350,11 @@
349
350
  "description": "Whether the tab bar is visible by default.\nThe tab bar shows open files in each split pane.\nCan be toggled at runtime via command palette or keybinding.\nDefault: true",
350
351
  "type": "boolean",
351
352
  "default": true
353
+ },
354
+ "use_terminal_bg": {
355
+ "description": "Use the terminal's default background color instead of the theme's editor background.\nWhen enabled, the editor background inherits from the terminal emulator,\nallowing transparency or custom terminal backgrounds to show through.\nDefault: false",
356
+ "type": "boolean",
357
+ "default": false
352
358
  }
353
359
  }
354
360
  },
@@ -817,7 +823,7 @@
817
823
  }
818
824
  },
819
825
  "PluginConfig": {
820
- "description": "Configuration for an individual plugin",
826
+ "description": "Configuration for a single plugin",
821
827
  "type": "object",
822
828
  "properties": {
823
829
  "enabled": {
@@ -255,16 +255,15 @@ editor.registerCommand(
255
255
  "%cmd.show_diagnostics_panel",
256
256
  "%cmd.show_diagnostics_panel_desc",
257
257
  "show_diagnostics_panel",
258
- "normal"
258
+ null
259
259
  );
260
260
 
261
261
  editor.registerCommand(
262
262
  "%cmd.toggle_diagnostics_panel",
263
263
  "%cmd.toggle_diagnostics_panel_desc",
264
264
  "toggle_diagnostics_panel",
265
- "normal"
265
+ null
266
266
  );
267
267
 
268
268
  // Initialization
269
- editor.setStatus(editor.t("status.loaded"));
270
269
  editor.debug("Diagnostics Panel plugin initialized (using Finder abstraction)");
@@ -481,12 +481,12 @@ globalThis.show_git_blame = async function(): Promise<void> {
481
481
  const bufferId = await editor.createVirtualBufferInExistingSplit({
482
482
  name: bufferName,
483
483
  mode: "git-blame",
484
- read_only: true,
484
+ readOnly: true,
485
485
  entries: entries,
486
- split_id: blameState.splitId!,
487
- show_line_numbers: true, // We DO want line numbers (headers won't have them due to source_offset: null)
488
- show_cursors: true,
489
- editing_disabled: true,
486
+ splitId: blameState.splitId!,
487
+ showLineNumbers: true, // We DO want line numbers (headers won't have them due to source_offset: null)
488
+ showCursors: true,
489
+ editingDisabled: true,
490
490
  });
491
491
 
492
492
  if (bufferId !== null) {
@@ -677,26 +677,25 @@ editor.registerCommand(
677
677
  "%cmd.git_blame",
678
678
  "%cmd.git_blame_desc",
679
679
  "show_git_blame",
680
- "normal"
680
+ null
681
681
  );
682
682
 
683
683
  editor.registerCommand(
684
684
  "%cmd.git_blame_close",
685
685
  "%cmd.git_blame_close_desc",
686
686
  "git_blame_close",
687
- "normal"
687
+ null
688
688
  );
689
689
 
690
690
  editor.registerCommand(
691
691
  "%cmd.git_blame_go_back",
692
692
  "%cmd.git_blame_go_back_desc",
693
693
  "git_blame_go_back",
694
- "normal"
694
+ null
695
695
  );
696
696
 
697
697
  // =============================================================================
698
698
  // Plugin Initialization
699
699
  // =============================================================================
700
700
 
701
- editor.setStatus(editor.t("status.ready"));
702
701
  editor.debug("Git Blame plugin initialized - Use 'Git Blame' command to open");
@@ -27,7 +27,11 @@ async function loadGitFiles(): Promise<string[]> {
27
27
  const result = await editor.spawnProcess("git", ["ls-files"]);
28
28
 
29
29
  if (result.exit_code === 0) {
30
- return result.stdout.split("\n").filter((line) => line.trim() !== "");
30
+ // Split by newline and trim each line to handle \r\n on Windows
31
+ return result.stdout
32
+ .split("\n")
33
+ .map((line) => line.trim())
34
+ .filter((line) => line !== "");
31
35
  }
32
36
 
33
37
  editor.debug(`Failed to load git files: ${result.stderr}`);
@@ -58,15 +62,14 @@ editor.registerCommand(
58
62
  "%cmd.find",
59
63
  "%cmd.find_desc",
60
64
  "start_git_find_file",
61
- "normal"
65
+ null
62
66
  );
63
67
 
64
68
  editor.registerCommand(
65
69
  "%cmd.reload",
66
70
  "%cmd.reload_desc",
67
71
  "git_reload_files",
68
- "normal"
72
+ null
69
73
  );
70
74
 
71
75
  editor.debug("Git Find File plugin loaded (using Finder abstraction)");
72
- editor.setStatus(editor.t("status.ready"));
@@ -67,8 +67,7 @@ globalThis.start_git_grep = function (): void {
67
67
  };
68
68
 
69
69
  // Register command
70
- editor.registerCommand("%cmd.grep", "%cmd.grep_desc", "start_git_grep", "normal");
70
+ editor.registerCommand("%cmd.grep", "%cmd.grep_desc", "start_git_grep", null);
71
71
 
72
72
  // Log that plugin loaded successfully
73
73
  editor.debug("Git Grep plugin loaded (using Finder abstraction)");
74
- editor.setStatus(editor.t("status.ready"));
@@ -458,7 +458,7 @@ editor.registerCommand(
458
458
  "%cmd.refresh",
459
459
  "%cmd.refresh_desc",
460
460
  "git_gutter_refresh",
461
- "normal"
461
+ null
462
462
  );
463
463
 
464
464
  // Initialize for the current buffer
@@ -474,4 +474,3 @@ if (initPath && initPath !== "") {
474
474
  }
475
475
 
476
476
  editor.debug("Git Gutter plugin loaded");
477
- editor.setStatus(editor.t("status.ready"));
@@ -766,12 +766,12 @@ globalThis.show_git_log = async function(): Promise<void> {
766
766
  const bufferId = await editor.createVirtualBufferInExistingSplit({
767
767
  name: "*Git Log*",
768
768
  mode: "git-log",
769
- read_only: true,
769
+ readOnly: true,
770
770
  entries: entries,
771
- split_id: gitLogState.splitId!,
772
- show_line_numbers: false,
773
- show_cursors: true,
774
- editing_disabled: true,
771
+ splitId: gitLogState.splitId!,
772
+ showLineNumbers: false,
773
+ showCursors: true,
774
+ editingDisabled: true,
775
775
  });
776
776
 
777
777
  if (bufferId !== null) {
@@ -900,12 +900,12 @@ globalThis.git_log_show_commit = async function(): Promise<void> {
900
900
  const bufferId = await editor.createVirtualBufferInExistingSplit({
901
901
  name: `*Commit: ${commit.shortHash}*`,
902
902
  mode: "git-commit-detail",
903
- read_only: true,
903
+ readOnly: true,
904
904
  entries: entries,
905
- split_id: gitLogState.splitId!,
906
- show_line_numbers: false, // Disable line numbers for cleaner diff view
907
- show_cursors: true,
908
- editing_disabled: true,
905
+ splitId: gitLogState.splitId!,
906
+ showLineNumbers: false, // Disable line numbers for cleaner diff view
907
+ showCursors: true,
908
+ editingDisabled: true,
909
909
  });
910
910
 
911
911
  if (bufferId !== null) {
@@ -1213,12 +1213,12 @@ globalThis.git_commit_detail_open_file = async function(): Promise<void> {
1213
1213
  const bufferId = await editor.createVirtualBufferInExistingSplit({
1214
1214
  name: `${file} @ ${commit.shortHash}`,
1215
1215
  mode: "git-file-view",
1216
- read_only: true,
1216
+ readOnly: true,
1217
1217
  entries: entries,
1218
- split_id: commitDetailState.splitId!,
1219
- show_line_numbers: true,
1220
- show_cursors: true,
1221
- editing_disabled: true,
1218
+ splitId: commitDetailState.splitId!,
1219
+ showLineNumbers: true,
1220
+ showCursors: true,
1221
+ editingDisabled: true,
1222
1222
  });
1223
1223
 
1224
1224
  if (bufferId !== null) {
@@ -1253,26 +1253,25 @@ editor.registerCommand(
1253
1253
  "%cmd.git_log",
1254
1254
  "%cmd.git_log_desc",
1255
1255
  "show_git_log",
1256
- "normal"
1256
+ null
1257
1257
  );
1258
1258
 
1259
1259
  editor.registerCommand(
1260
1260
  "%cmd.git_log_close",
1261
1261
  "%cmd.git_log_close_desc",
1262
1262
  "git_log_close",
1263
- "normal"
1263
+ null
1264
1264
  );
1265
1265
 
1266
1266
  editor.registerCommand(
1267
1267
  "%cmd.git_log_refresh",
1268
1268
  "%cmd.git_log_refresh_desc",
1269
1269
  "git_log_refresh",
1270
- "normal"
1270
+ null
1271
1271
  );
1272
1272
 
1273
1273
  // =============================================================================
1274
1274
  // Plugin Initialization
1275
1275
  // =============================================================================
1276
1276
 
1277
- editor.setStatus(editor.t("status.ready", { count: "0" }));
1278
1277
  editor.debug("Git Log plugin initialized - Use 'Git Log' command to open");
@@ -465,7 +465,9 @@ export class Finder<T> {
465
465
  options.initialQuery
466
466
  );
467
467
  } else {
468
- this.editor.startPrompt(options.title, this.config.id);
468
+ this.editor.debug(`[Finder] calling startPrompt with title="${options.title}", id="${this.config.id}"`);
469
+ const result = this.editor.startPrompt(options.title, this.config.id);
470
+ this.editor.debug(`[Finder] startPrompt returned: ${result}`);
469
471
  }
470
472
  this.editor.setStatus("Type to search...");
471
473
  }
@@ -951,11 +953,11 @@ export class Finder<T> {
951
953
  }
952
954
 
953
955
  private closePreview(): void {
954
- if (this.previewState.bufferId !== null) {
956
+ if (this.previewState.bufferId || this.previewState.bufferId == 0) {
955
957
  this.editor.closeBuffer(this.previewState.bufferId);
956
958
  this.previewState.bufferId = null;
957
959
  }
958
- if (this.previewState.splitId !== null) {
960
+ if (this.previewState.splitId || this.previewState.splitId == 0) {
959
961
  this.editor.closeSplit(this.previewState.splitId);
960
962
  this.previewState.splitId = null;
961
963
  }