@fresh-editor/fresh-editor 0.2.5 → 0.2.12
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 +146 -0
- package/README.md +2 -2
- package/package.json +1 -1
- package/plugins/README.md +1 -1
- package/plugins/clangd_support.ts +2 -10
- package/plugins/config-schema.json +90 -1
- package/plugins/csharp_support.ts +1 -1
- package/plugins/diagnostics_panel.ts +23 -25
- package/plugins/git_gutter.ts +1 -1
- package/plugins/lib/finder.ts +22 -0
- package/plugins/lib/fresh.d.ts +25 -1
- package/plugins/markdown_source.ts +354 -0
- package/plugins/schemas/theme.schema.json +9 -0
- package/plugins/theme_editor.i18n.json +43 -15
- package/plugins/theme_editor.ts +1 -1
- package/themes/dark.json +2 -1
- package/themes/dracula.json +2 -1
- package/themes/high-contrast.json +2 -1
- package/themes/light.json +2 -1
- package/themes/nord.json +2 -1
- package/themes/nostalgia.json +2 -1
- package/themes/solarized-dark.json +2 -1
- package/plugins/buffer_modified.i18n.json +0 -72
- package/plugins/buffer_modified.ts +0 -281
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,151 @@
|
|
|
1
1
|
# Release Notes
|
|
2
2
|
|
|
3
|
+
## 0.2.12
|
|
4
|
+
|
|
5
|
+
### Features
|
|
6
|
+
|
|
7
|
+
* **Auto-Close Config**: Separate `auto_close` toggle (default: true) to independently control bracket/quote auto-close, skip-over, and pair deletion — previously coupled to `auto_indent`. Per-language overrides via `languages.<lang>.auto_close` (#1144).
|
|
8
|
+
|
|
9
|
+
* **Surround Selection**: Typing an opening delimiter with a selection wraps it instead of replacing it (e.g. selecting `hello` and typing `(` produces `(hello)`). Controlled by `auto_surround` config with per-language overrides.
|
|
10
|
+
|
|
11
|
+
* **Smart Quote Suppression**: Quotes typed inside an existing string no longer auto-close, preventing unwanted doubled quotes (#1142).
|
|
12
|
+
|
|
13
|
+
* **Read-Only Mode**: Files without write permission and library/toolchain paths (rustup, /usr/include, /nix/store, Homebrew Cellar, .nuget, Xcode SDKs) automatically open as read-only. New "Toggle Read Only" command to override. Status bar shows `[RO]` indicator.
|
|
14
|
+
|
|
15
|
+
### Bug Fixes
|
|
16
|
+
|
|
17
|
+
* **Multi-Cursor Enter**: Fixed Enter key in markdown mode only inserting a newline at the last cursor, ignoring secondary cursors. Falls back to built-in insert_newline when multiple cursors are active (#1140).
|
|
18
|
+
|
|
19
|
+
* **Multi-Cursor Position Drift**: Fixed cursors with no events during bulk edits (e.g. Delete at end of buffer) drifting to stale positions. Uses saturating arithmetic to prevent overflow with overlapping selections (#1140).
|
|
20
|
+
|
|
21
|
+
### Improvements
|
|
22
|
+
|
|
23
|
+
* **Log Noise Reduction**: Disabled span close events (~90% of log volume) by default and moved 12 high-frequency log sites to trace level. Typical log size reduced from ~266MB to ~5-10MB. Set `FRESH_LOG_SPANS=1` to re-enable (#1154).
|
|
24
|
+
|
|
25
|
+
### Internal
|
|
26
|
+
|
|
27
|
+
* Added multi-cursor shadow model property-based tests with random operation sequences across 2-3 cursors.
|
|
28
|
+
* Added e2e regression tests for multi-cursor Enter with auto_indent, Ctrl+D selection, tree-sitter, and markdown grammar.
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## 0.2.11
|
|
33
|
+
|
|
34
|
+
### Features
|
|
35
|
+
|
|
36
|
+
* **Whitespace Indicators**: Granular control over whitespace visibility — configure space (·) and tab (→) indicators independently for leading, inner, and trailing positions. Master toggle, per-language overrides, and a new `whitespace_indicator_fg` theme color.
|
|
37
|
+
|
|
38
|
+
* **Indent-Based Code Folding**: Code folding now works in large file mode and for files without LSP folding ranges, using indentation analysis as a fallback. Fold from any line within a block (not just the header). Unified byte-offset pipeline for consistent gutter indicators.
|
|
39
|
+
|
|
40
|
+
* **Session Open-File Enhancements**: `--wait` flag blocks the CLI until the user dismisses a popup or closes the buffer — enables use as `git core.editor`. Range selection syntax (`file:L-EL`, `file:L:C-EL:EC`) and hover messages (`file:L@"markdown msg"`) for annotated file opening. Auto-attaches a client when `open-file` starts a new session.
|
|
41
|
+
|
|
42
|
+
* **GUI: macOS Native Integration** (experimental): Native menu bar with dynamic when/checkbox conditions, Cmd keybindings (`macos-gui` keymap), app icon, and `.app` bundle resources. Menu tracking detection prevents state mutations from causing menu jumps.
|
|
43
|
+
|
|
44
|
+
* **Platform Icons**: Application icons for Windows `.exe`, Linux `.deb`/`.rpm` packages, and macOS app bundles.
|
|
45
|
+
|
|
46
|
+
### Bug Fixes
|
|
47
|
+
|
|
48
|
+
* **Bracket Highlight Hanging on Large Files**: Bracket matching now caps scanning at 1MB and uses 16KB bulk reads instead of byte-at-a-time, preventing hangs on large files.
|
|
49
|
+
|
|
50
|
+
* **Markdown Plugin Activation**: Plugin now activates based on buffer language (not just file extension), fixing cases where `Set Language` to markdown didn't enable smart editing (#1117). Reverse bullet cycling on Shift+Tab now works correctly (#1116).
|
|
51
|
+
|
|
52
|
+
* **Settings UI**: Fixed Save button mouse click not closing the dialog. Fixed Reset button not showing confirmation dialog. Fixed Discard dialog persisting on reopen.
|
|
53
|
+
|
|
54
|
+
* **Active Tab Styling Bleed**: Fixed active tab border color bleeding through dropdown menus.
|
|
55
|
+
|
|
56
|
+
* **Cursor Corruption on Tab Click**: Fixed hardware cursor appearing at wrong position when clicking a tab in an inactive split.
|
|
57
|
+
|
|
58
|
+
* **Comment Delimiter Colors**: Fixed comment delimiter characters (e.g. `//`) using the wrong color in syntax highlighting.
|
|
59
|
+
|
|
60
|
+
* **Scroll Events Routing**: Fixed mouse scroll events going to the file explorer panel regardless of mouse position.
|
|
61
|
+
|
|
62
|
+
* **File Explorer Border**: Fixed hover/drag bugs on the file explorer resize border.
|
|
63
|
+
|
|
64
|
+
* **Windows Named Pipe Crash**: Fixed crash in `Server::handle_new_connection` on Windows.
|
|
65
|
+
|
|
66
|
+
* **Bar/Underline Cursor Invisible**: Fixed bar and underline cursor styles being invisible on characters due to REVERSED modifier creating a block-like highlight (#851).
|
|
67
|
+
|
|
68
|
+
* **Wrapped Line Viewport Scroll**: Fixed viewport scroll limit counting logical lines instead of visual rows, causing erratic scrolling, skipped wrapped rows, and stuck End key with line wrap enabled (#1147).
|
|
69
|
+
|
|
70
|
+
* **Search on Large Files**: Fixed multi-GB memory consumption, O(N²) offset accumulation, and search scan never completing when capped at max matches. Chunked incremental search, viewport-only overlays, and 100K match cap (#1146).
|
|
71
|
+
|
|
72
|
+
* **macOS Menu Hover Jump**: Fixed menu bar jumping to leftmost menu during hover by using `WaitUntil` instead of `Poll` and caching menu item states.
|
|
73
|
+
|
|
74
|
+
### Improvements
|
|
75
|
+
|
|
76
|
+
* Status log and warning log buffers are now read-only.
|
|
77
|
+
* Replaced `buffer_modified` JS plugin with native Rust diff indicators, eliminating JS↔Rust round-trips on every edit/scroll.
|
|
78
|
+
|
|
79
|
+
### Internal
|
|
80
|
+
|
|
81
|
+
* Folding system refactored to use byte offsets instead of line numbers for gutter indicators, fixing consistency issues in large file mode.
|
|
82
|
+
* Unified fold indicator pipeline shared between LSP-based and indent-based folding.
|
|
83
|
+
* Fixed Nix build: include PNG files in source filter for GUI icon resources.
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## 0.2.9
|
|
88
|
+
|
|
89
|
+
### Features
|
|
90
|
+
|
|
91
|
+
* **Code Folding**: Fold/unfold code blocks via LSP foldingRange. Per-view fold state, gutter indicators for collapsed ranges, fold-aware scrolling. Toggle via command palette ("Toggle Fold") (#900). Thanks @asukaminato0721 !
|
|
92
|
+
|
|
93
|
+
* **Large File Line Numbers**: Large files show byte offsets in gutter/status bar until scanned. On-demand parallel line index scanning (via Ctrl+G prompt or "Scan Line Index" command) gives exact line numbers with progress indicator. Remote scanning counts newlines server-side without data transfer.
|
|
94
|
+
|
|
95
|
+
* **Markdown Source Editing**: New plugin for smart Markdown source-mode editing — auto-continues list items on Enter (bullets, ordered lists, checkboxes), removes empty markers, Tab indents + cycles bullet style (#1095).
|
|
96
|
+
|
|
97
|
+
* **GUI mode - can run without terminal** (highly experimental): GPU-accelerated windowed mode via winit + wgpu. Build with `--features gui` and run with `--gui` to try it.
|
|
98
|
+
|
|
99
|
+
### Improvements
|
|
100
|
+
|
|
101
|
+
* **Smart Backspace Dedent**: Backspace in leading whitespace removes one indent unit (tab_size spaces or 1 tab) instead of a single character.
|
|
102
|
+
|
|
103
|
+
* **Diagnostics Panel**: Up/Down now scrolls the editor to preview diagnostic location. Enter jumps and focuses the editor.
|
|
104
|
+
|
|
105
|
+
* **Glob Patterns in Language Config**: `filenames` field now supports glob patterns (`*.conf`, `*rc`, `/etc/**/rc.*`) for extensionless file detection (#1083).
|
|
106
|
+
|
|
107
|
+
* Disabled single-quote auto-close in Markdown files (interferes with apostrophes).
|
|
108
|
+
|
|
109
|
+
### Bug Fixes
|
|
110
|
+
|
|
111
|
+
* **Auto-Indent**: Fixed `tab_size` setting ignored for auto-indent; fixed indent level lost on normal statement lines; fixed Go auto-dedent using spaces instead of tabs (#1068); fixed Python nested indent after consecutive `:` lines (#1069).
|
|
112
|
+
|
|
113
|
+
* **File Explorer Dotfiles**: Fixed dotfiles always visible regardless of "Show hidden files" toggle. Config `show_hidden`/`show_gitignored` now applied on init (#1079).
|
|
114
|
+
|
|
115
|
+
* **LSP Toggle Desync**: Fixed state corruption when toggling LSP off/on — now sends `didClose` so re-enable gets fresh `didOpen` (#952).
|
|
116
|
+
|
|
117
|
+
* **LSP Client Capabilities**: Now advertises all supported capabilities including `publishDiagnostics`, enabling diagnostics from strict servers like pyright (#1006).
|
|
118
|
+
|
|
119
|
+
* **LSP Status Indicator**: Fixed status bar indicator disappearing after each request completion (#952).
|
|
120
|
+
|
|
121
|
+
* **Set Language**: Fixed command storing display name instead of canonical ID, breaking LSP config lookups (#1078).
|
|
122
|
+
|
|
123
|
+
* **Escape Sequences in Client Mode**: Fixed mouse codes, Shift+Tab, and standalone ESC not working in `fresh -a` attach mode (#1089).
|
|
124
|
+
|
|
125
|
+
* **Client Mode Terminal Reset**: Fixed terminal not fully restored on exit in client mode (#1089).
|
|
126
|
+
|
|
127
|
+
* **Ctrl+End with Line Wrap**: Fixed viewport not scrolling to trailing empty line; fixed Down arrow not reaching it (#992).
|
|
128
|
+
|
|
129
|
+
* **Diagnostics Panel Windows Paths**: Fixed file URIs not decoded properly on Windows (#1071).
|
|
130
|
+
|
|
131
|
+
* **Debug Keyboard Dialog**: Fixed not capturing keys in client/server mode (#1089).
|
|
132
|
+
|
|
133
|
+
### Performance
|
|
134
|
+
|
|
135
|
+
* Replaced linear span lookups in syntax highlighting with O(1) amortized cursor.
|
|
136
|
+
* Eliminated JSON round-trip and JS re-parsing in plugin hook dispatch (~16% CPU reduction).
|
|
137
|
+
* Path-copying PieceTree mutations with structural diff via `Arc::ptr_eq` — O(edit regions) instead of O(all leaves).
|
|
138
|
+
* Viewport-aware filtering and batch API for large file gutter indicators (~780K IPC commands → ~50 per edit).
|
|
139
|
+
|
|
140
|
+
### Internal
|
|
141
|
+
|
|
142
|
+
* Update flake.nix to rust 1.92.0
|
|
143
|
+
* Split GUI backend into separate `fresh-gui` crate.
|
|
144
|
+
* Unified language detection with `DetectedLanguage` struct and single `apply_language()` mutation point.
|
|
145
|
+
* CI now runs clippy with `--all-features` to lint GUI code.
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
|
|
3
149
|
## 0.2.5
|
|
4
150
|
|
|
5
151
|
### Features
|
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
A modern, full-featured terminal text editor, **with zero configuration**. Familiar keybindings, mouse support, and IDE-level features — no learning curve required.
|
|
4
4
|
|
|
5
|
-
[Official Website](https://sinelaw.github.io/fresh/) · [Documentation](https://getfresh.dev/docs) · [Discord](https://discord.gg/
|
|
5
|
+
[Official Website](https://sinelaw.github.io/fresh/) · [Documentation](https://getfresh.dev/docs) · [Discord](https://discord.gg/gqGh3K4uW3) · [Contributing](#contributing)
|
|
6
6
|
|
|
7
7
|
**[Quick Install](#installation):** `curl https://raw.githubusercontent.com/sinelaw/fresh/refs/heads/master/scripts/install.sh | sh`
|
|
8
8
|
|
|
@@ -47,7 +47,7 @@ See more feature demos: [Editing](https://getfresh.dev/docs/blog/editing) (searc
|
|
|
47
47
|
| **Views & Layout** | split panes, line numbers, line wrap, backgrounds, markdown preview |
|
|
48
48
|
| **Language Server (LSP)** | go to definition, references, hover, code actions, rename, diagnostics, autocompletion |
|
|
49
49
|
| **Productivity** | command palette, menu bar, keyboard macros, git log, diagnostics panel |
|
|
50
|
-
| **Extensibility** | TypeScript plugins (sandboxed
|
|
50
|
+
| **Extensibility** | TypeScript plugins (sandboxed QuickJS), color highlighter, TODO highlighter, merge conflicts, path complete, keymaps |
|
|
51
51
|
| **Internationalization** | Multiple language support (see [`locales/`](locales/)), plugin translation system |
|
|
52
52
|
|
|
53
53
|
## Installation
|
package/package.json
CHANGED
package/plugins/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Plugins
|
|
2
2
|
|
|
3
|
-
This directory contains production-ready plugins for the editor. Plugins are written in **TypeScript** and run in a sandboxed
|
|
3
|
+
This directory contains production-ready plugins for the editor. Plugins are written in **TypeScript** and run in a sandboxed QuickJS environment (transpiled via oxc_transformer). They are automatically loaded when the editor starts.
|
|
4
4
|
|
|
5
5
|
## Available Plugins
|
|
6
6
|
|
|
@@ -36,22 +36,14 @@ function detectLanguage(path: string): string | null {
|
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
function pathToFileUri(path: string): string {
|
|
39
|
-
|
|
40
|
-
if (!normalized.startsWith("/")) {
|
|
41
|
-
normalized = "/" + normalized;
|
|
42
|
-
}
|
|
43
|
-
return "file://" + encodeURI(normalized);
|
|
39
|
+
return editor.pathToFileUri(path);
|
|
44
40
|
}
|
|
45
41
|
|
|
46
42
|
function fileUriToPath(uri: string): string {
|
|
47
43
|
if (!uri.startsWith("file://")) {
|
|
48
44
|
return uri;
|
|
49
45
|
}
|
|
50
|
-
|
|
51
|
-
if (path.startsWith("/") && path.length > 2 && path[2] === ":") {
|
|
52
|
-
path = path.substring(1);
|
|
53
|
-
}
|
|
54
|
-
return path;
|
|
46
|
+
return editor.fileUriToPath(uri) || uri;
|
|
55
47
|
}
|
|
56
48
|
|
|
57
49
|
function setClangdStatus(message: string): void {
|
|
@@ -41,8 +41,17 @@
|
|
|
41
41
|
"use_terminal_bg": false,
|
|
42
42
|
"cursor_style": "default",
|
|
43
43
|
"rulers": [],
|
|
44
|
+
"whitespace_show": true,
|
|
45
|
+
"whitespace_spaces_leading": false,
|
|
46
|
+
"whitespace_spaces_inner": false,
|
|
47
|
+
"whitespace_spaces_trailing": false,
|
|
48
|
+
"whitespace_tabs_leading": true,
|
|
49
|
+
"whitespace_tabs_inner": true,
|
|
50
|
+
"whitespace_tabs_trailing": true,
|
|
44
51
|
"tab_size": 4,
|
|
45
52
|
"auto_indent": true,
|
|
53
|
+
"auto_close": true,
|
|
54
|
+
"auto_surround": true,
|
|
46
55
|
"scroll_offset": 3,
|
|
47
56
|
"default_line_ending": "lf",
|
|
48
57
|
"trim_trailing_whitespace_on_save": false,
|
|
@@ -72,6 +81,7 @@
|
|
|
72
81
|
"highlight_context_bytes": 10000,
|
|
73
82
|
"large_file_threshold_bytes": 1048576,
|
|
74
83
|
"estimated_line_length": 80,
|
|
84
|
+
"read_concurrency": 64,
|
|
75
85
|
"file_tree_poll_interval_ms": 3000
|
|
76
86
|
}
|
|
77
87
|
},
|
|
@@ -278,6 +288,48 @@
|
|
|
278
288
|
"default": [],
|
|
279
289
|
"x-section": "Display"
|
|
280
290
|
},
|
|
291
|
+
"whitespace_show": {
|
|
292
|
+
"description": "Master toggle for whitespace indicator visibility.\nWhen disabled, no whitespace indicators (·, →) are shown regardless\nof the per-position settings below.\nDefault: true",
|
|
293
|
+
"type": "boolean",
|
|
294
|
+
"default": true,
|
|
295
|
+
"x-section": "Whitespace"
|
|
296
|
+
},
|
|
297
|
+
"whitespace_spaces_leading": {
|
|
298
|
+
"description": "Show space indicators (·) for leading whitespace (indentation).\nLeading whitespace is everything before the first non-space character on a line.\nDefault: false",
|
|
299
|
+
"type": "boolean",
|
|
300
|
+
"default": false,
|
|
301
|
+
"x-section": "Whitespace"
|
|
302
|
+
},
|
|
303
|
+
"whitespace_spaces_inner": {
|
|
304
|
+
"description": "Show space indicators (·) for inner whitespace (between words/tokens).\nInner whitespace is spaces between the first and last non-space characters.\nDefault: false",
|
|
305
|
+
"type": "boolean",
|
|
306
|
+
"default": false,
|
|
307
|
+
"x-section": "Whitespace"
|
|
308
|
+
},
|
|
309
|
+
"whitespace_spaces_trailing": {
|
|
310
|
+
"description": "Show space indicators (·) for trailing whitespace.\nTrailing whitespace is everything after the last non-space character on a line.\nDefault: false",
|
|
311
|
+
"type": "boolean",
|
|
312
|
+
"default": false,
|
|
313
|
+
"x-section": "Whitespace"
|
|
314
|
+
},
|
|
315
|
+
"whitespace_tabs_leading": {
|
|
316
|
+
"description": "Show tab indicators (→) for leading tabs (indentation).\nCan be overridden per-language via `show_whitespace_tabs` in language config.\nDefault: true",
|
|
317
|
+
"type": "boolean",
|
|
318
|
+
"default": true,
|
|
319
|
+
"x-section": "Whitespace"
|
|
320
|
+
},
|
|
321
|
+
"whitespace_tabs_inner": {
|
|
322
|
+
"description": "Show tab indicators (→) for inner tabs (between words/tokens).\nCan be overridden per-language via `show_whitespace_tabs` in language config.\nDefault: true",
|
|
323
|
+
"type": "boolean",
|
|
324
|
+
"default": true,
|
|
325
|
+
"x-section": "Whitespace"
|
|
326
|
+
},
|
|
327
|
+
"whitespace_tabs_trailing": {
|
|
328
|
+
"description": "Show tab indicators (→) for trailing tabs.\nCan be overridden per-language via `show_whitespace_tabs` in language config.\nDefault: true",
|
|
329
|
+
"type": "boolean",
|
|
330
|
+
"default": true,
|
|
331
|
+
"x-section": "Whitespace"
|
|
332
|
+
},
|
|
281
333
|
"tab_size": {
|
|
282
334
|
"description": "Number of spaces per tab character",
|
|
283
335
|
"type": "integer",
|
|
@@ -292,6 +344,18 @@
|
|
|
292
344
|
"default": true,
|
|
293
345
|
"x-section": "Editing"
|
|
294
346
|
},
|
|
347
|
+
"auto_close": {
|
|
348
|
+
"description": "Automatically close brackets, parentheses, and quotes when typing.\nWhen enabled, typing an opening delimiter like `(`, `[`, `{`, `\"`, `'`, or `` ` ``\nwill automatically insert the matching closing delimiter.\nAlso enables skip-over (moving past existing closing delimiters) and\npair deletion (deleting both delimiters when backspacing between them).\nDefault: true",
|
|
349
|
+
"type": "boolean",
|
|
350
|
+
"default": true,
|
|
351
|
+
"x-section": "Editing"
|
|
352
|
+
},
|
|
353
|
+
"auto_surround": {
|
|
354
|
+
"description": "Automatically surround selected text with matching pairs when typing\nan opening delimiter. When enabled and text is selected, typing `(`, `[`,\n`{`, `\"`, `'`, or `` ` `` wraps the selection instead of replacing it.\nDefault: true",
|
|
355
|
+
"type": "boolean",
|
|
356
|
+
"default": true,
|
|
357
|
+
"x-section": "Editing"
|
|
358
|
+
},
|
|
295
359
|
"scroll_offset": {
|
|
296
360
|
"description": "Minimum lines to keep visible above/below cursor when scrolling",
|
|
297
361
|
"type": "integer",
|
|
@@ -490,6 +554,14 @@
|
|
|
490
554
|
"default": 80,
|
|
491
555
|
"x-section": "Performance"
|
|
492
556
|
},
|
|
557
|
+
"read_concurrency": {
|
|
558
|
+
"description": "Maximum number of concurrent filesystem read requests.\nUsed during line-feed scanning and other bulk I/O operations.\nHigher values improve throughput, especially for remote filesystems.\nDefault: 64",
|
|
559
|
+
"type": "integer",
|
|
560
|
+
"format": "uint",
|
|
561
|
+
"minimum": 0,
|
|
562
|
+
"default": 64,
|
|
563
|
+
"x-section": "Performance"
|
|
564
|
+
},
|
|
493
565
|
"file_tree_poll_interval_ms": {
|
|
494
566
|
"description": "Poll interval in milliseconds for refreshing expanded directories in the file explorer.\nDirectory modification times are checked at this interval to detect new/deleted files.\nLower values detect changes faster but use more CPU.\nDefault: 3000ms (3 seconds)",
|
|
495
567
|
"type": "integer",
|
|
@@ -702,7 +774,8 @@
|
|
|
702
774
|
"default",
|
|
703
775
|
"emacs",
|
|
704
776
|
"vscode",
|
|
705
|
-
"macos"
|
|
777
|
+
"macos",
|
|
778
|
+
"macos-gui"
|
|
706
779
|
]
|
|
707
780
|
},
|
|
708
781
|
"LanguageConfig": {
|
|
@@ -743,6 +816,22 @@
|
|
|
743
816
|
"type": "boolean",
|
|
744
817
|
"default": true
|
|
745
818
|
},
|
|
819
|
+
"auto_close": {
|
|
820
|
+
"description": "Whether to auto-close brackets, parentheses, and quotes for this language.\nIf not specified (`null`), falls back to the global `editor.auto_close` setting.",
|
|
821
|
+
"type": [
|
|
822
|
+
"boolean",
|
|
823
|
+
"null"
|
|
824
|
+
],
|
|
825
|
+
"default": null
|
|
826
|
+
},
|
|
827
|
+
"auto_surround": {
|
|
828
|
+
"description": "Whether to auto-surround selected text with matching pairs for this language.\nIf not specified (`null`), falls back to the global `editor.auto_surround` setting.",
|
|
829
|
+
"type": [
|
|
830
|
+
"boolean",
|
|
831
|
+
"null"
|
|
832
|
+
],
|
|
833
|
+
"default": null
|
|
834
|
+
},
|
|
746
835
|
"highlighter": {
|
|
747
836
|
"description": "Preferred highlighter backend (auto, tree-sitter, or textmate)",
|
|
748
837
|
"$ref": "#/$defs/HighlighterPreference",
|
|
@@ -186,7 +186,7 @@ globalThis.on_csharp_file_open = async function (data: AfterFileOpenData): Promi
|
|
|
186
186
|
configuredProjectRoots.add(projectRoot);
|
|
187
187
|
|
|
188
188
|
// Convert path to file:// URI
|
|
189
|
-
const rootUri =
|
|
189
|
+
const rootUri = editor.pathToFileUri(projectRoot);
|
|
190
190
|
editor.debug(`csharp_support: Setting LSP root URI to ${rootUri}`);
|
|
191
191
|
editor.setLspRootUri("csharp", rootUri);
|
|
192
192
|
}
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* - syncWithEditor for bidirectional cursor sync
|
|
14
14
|
*/
|
|
15
15
|
|
|
16
|
-
import { Finder, createLiveProvider,
|
|
16
|
+
import { Finder, createLiveProvider, type FinderProvider } from "./lib/finder.ts";
|
|
17
17
|
|
|
18
18
|
const editor = getEditor();
|
|
19
19
|
|
|
@@ -49,41 +49,42 @@ function severityToString(severity: number): "error" | "warning" | "info" | "hin
|
|
|
49
49
|
}
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
-
// Convert URI to file path
|
|
52
|
+
// Convert file URI to file path using the editor's built-in URI handling
|
|
53
53
|
function uriToPath(uri: string): string {
|
|
54
|
-
if (uri.startsWith("file://")) {
|
|
55
|
-
return uri
|
|
54
|
+
if (!uri.startsWith("file://")) {
|
|
55
|
+
return uri;
|
|
56
56
|
}
|
|
57
|
-
return uri;
|
|
57
|
+
return editor.fileUriToPath(uri) || uri;
|
|
58
58
|
}
|
|
59
59
|
|
|
60
60
|
// Get diagnostics based on current filter
|
|
61
61
|
function getDiagnostics(): DiagnosticItem[] {
|
|
62
62
|
const diagnostics = editor.getAllDiagnostics();
|
|
63
63
|
|
|
64
|
-
// Get active file
|
|
65
|
-
let
|
|
64
|
+
// Get active file path for filtering
|
|
65
|
+
let activePath: string | null = null;
|
|
66
66
|
if (sourceBufferId !== null) {
|
|
67
67
|
const path = editor.getBufferPath(sourceBufferId);
|
|
68
68
|
if (path) {
|
|
69
|
-
|
|
69
|
+
activePath = path.replace(/\\/g, "/");
|
|
70
70
|
}
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
-
// Filter diagnostics
|
|
74
|
-
const
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
: diagnostics;
|
|
73
|
+
// Filter diagnostics by comparing decoded paths (avoids URI encoding mismatches)
|
|
74
|
+
const filtered = showAllFiles || !activePath
|
|
75
|
+
? diagnostics
|
|
76
|
+
: diagnostics.filter((d) => uriToPath(d.uri).replace(/\\/g, "/") === activePath);
|
|
78
77
|
|
|
79
78
|
// Sort by file, then line, then severity
|
|
80
79
|
filtered.sort((a, b) => {
|
|
81
80
|
// File comparison
|
|
82
81
|
if (a.uri !== b.uri) {
|
|
83
82
|
// Active file first
|
|
84
|
-
if (
|
|
85
|
-
|
|
86
|
-
|
|
83
|
+
if (activePath) {
|
|
84
|
+
const aPath = uriToPath(a.uri).replace(/\\/g, "/");
|
|
85
|
+
const bPath = uriToPath(b.uri).replace(/\\/g, "/");
|
|
86
|
+
if (aPath === activePath) return -1;
|
|
87
|
+
if (bPath === activePath) return 1;
|
|
87
88
|
}
|
|
88
89
|
return a.uri < b.uri ? -1 : 1;
|
|
89
90
|
}
|
|
@@ -124,15 +125,7 @@ const finder = new Finder<DiagnosticItem>(editor, {
|
|
|
124
125
|
}),
|
|
125
126
|
groupBy: "file",
|
|
126
127
|
syncWithEditor: true,
|
|
127
|
-
|
|
128
|
-
const displayPath = getRelativePath(editor, d.file);
|
|
129
|
-
editor.setStatus(
|
|
130
|
-
editor.t("status.jumped_to", {
|
|
131
|
-
file: displayPath,
|
|
132
|
-
line: String(d.line),
|
|
133
|
-
})
|
|
134
|
-
);
|
|
135
|
-
},
|
|
128
|
+
navigateOnCursorMove: true,
|
|
136
129
|
});
|
|
137
130
|
|
|
138
131
|
// Get title based on current filter state
|
|
@@ -225,6 +218,11 @@ globalThis.on_diagnostics_buffer_activated = function (data: {
|
|
|
225
218
|
}): void {
|
|
226
219
|
if (!isOpen) return;
|
|
227
220
|
|
|
221
|
+
// Skip virtual buffers (e.g. the diagnostics panel itself) — they have no
|
|
222
|
+
// file path and would clear the filtered diagnostics list.
|
|
223
|
+
const path = editor.getBufferPath(data.buffer_id);
|
|
224
|
+
if (!path) return;
|
|
225
|
+
|
|
228
226
|
// Update source buffer
|
|
229
227
|
sourceBufferId = data.buffer_id;
|
|
230
228
|
|
package/plugins/git_gutter.ts
CHANGED
|
@@ -396,7 +396,7 @@ globalThis.onGitGutterAfterSave = function (args: {
|
|
|
396
396
|
|
|
397
397
|
// Note: Git diff compares the file on disk, not the in-memory buffer.
|
|
398
398
|
// Line indicators automatically track position changes via byte-position markers.
|
|
399
|
-
// A full re-diff happens on save.
|
|
399
|
+
// A full re-diff happens on save. Unsaved changes are shown natively by the editor.
|
|
400
400
|
|
|
401
401
|
/**
|
|
402
402
|
* Handle buffer closed - cleanup state
|
package/plugins/lib/finder.ts
CHANGED
|
@@ -112,6 +112,9 @@ export interface FinderConfig<T> {
|
|
|
112
112
|
|
|
113
113
|
/** Panel-specific: sync cursor with editor */
|
|
114
114
|
syncWithEditor?: boolean;
|
|
115
|
+
|
|
116
|
+
/** Panel-specific: navigate source split when cursor moves (preview without focus change) */
|
|
117
|
+
navigateOnCursorMove?: boolean;
|
|
115
118
|
}
|
|
116
119
|
|
|
117
120
|
/**
|
|
@@ -410,6 +413,7 @@ export class Finder<T> {
|
|
|
410
413
|
maxResults: 100,
|
|
411
414
|
groupBy: "none",
|
|
412
415
|
syncWithEditor: false,
|
|
416
|
+
navigateOnCursorMove: false,
|
|
413
417
|
...config,
|
|
414
418
|
};
|
|
415
419
|
|
|
@@ -1016,6 +1020,24 @@ export class Finder<T> {
|
|
|
1016
1020
|
self.editor.setStatus(
|
|
1017
1021
|
`Item ${itemIndex + 1}/${self.panelState.items.length}`
|
|
1018
1022
|
);
|
|
1023
|
+
|
|
1024
|
+
// Navigate source split to show the item's location (without focus change)
|
|
1025
|
+
if (self.config.navigateOnCursorMove) {
|
|
1026
|
+
const entry = self.panelState.entries[itemIndex];
|
|
1027
|
+
if (
|
|
1028
|
+
entry.location &&
|
|
1029
|
+
self.panelState.sourceSplitId !== null &&
|
|
1030
|
+
self.panelState.splitId !== null
|
|
1031
|
+
) {
|
|
1032
|
+
self.editor.openFileInSplit(
|
|
1033
|
+
self.panelState.sourceSplitId,
|
|
1034
|
+
entry.location.file,
|
|
1035
|
+
entry.location.line,
|
|
1036
|
+
entry.location.column
|
|
1037
|
+
);
|
|
1038
|
+
self.editor.focusSplit(self.panelState.splitId);
|
|
1039
|
+
}
|
|
1040
|
+
}
|
|
1019
1041
|
}
|
|
1020
1042
|
};
|
|
1021
1043
|
|
package/plugins/lib/fresh.d.ts
CHANGED
|
@@ -138,6 +138,10 @@ type ViewportInfo = {
|
|
|
138
138
|
*/
|
|
139
139
|
topByte: number;
|
|
140
140
|
/**
|
|
141
|
+
* Line number of the first visible line (None when line index unavailable, e.g. large file before scan)
|
|
142
|
+
*/
|
|
143
|
+
topLine: number | null;
|
|
144
|
+
/**
|
|
141
145
|
* Left column offset (horizontal scroll)
|
|
142
146
|
*/
|
|
143
147
|
leftColumn: number;
|
|
@@ -260,7 +264,7 @@ type BufferInfo = {
|
|
|
260
264
|
view_mode: string;
|
|
261
265
|
/**
|
|
262
266
|
* True if any split showing this buffer has compose mode enabled.
|
|
263
|
-
* Plugins should use this (not view_mode) to decide whether to maintain
|
|
267
|
+
* Plugins should use this (not `view_mode`) to decide whether to maintain
|
|
264
268
|
* decorations, since decorations live on the buffer and are filtered
|
|
265
269
|
* per-split at render time.
|
|
266
270
|
*/
|
|
@@ -269,6 +273,10 @@ type BufferInfo = {
|
|
|
269
273
|
* Compose width (if set), from the active split's view state
|
|
270
274
|
*/
|
|
271
275
|
compose_width: number | null;
|
|
276
|
+
/**
|
|
277
|
+
* The detected language for this buffer (e.g., "rust", "markdown", "text")
|
|
278
|
+
*/
|
|
279
|
+
language: string;
|
|
272
280
|
};
|
|
273
281
|
type JsDiagnostic = {
|
|
274
282
|
/**
|
|
@@ -836,6 +844,18 @@ interface EditorAPI {
|
|
|
836
844
|
*/
|
|
837
845
|
pathIsAbsolute(path: string): boolean;
|
|
838
846
|
/**
|
|
847
|
+
* Convert a file:// URI to a local file path.
|
|
848
|
+
* Handles percent-decoding and Windows drive letters.
|
|
849
|
+
* Returns an empty string if the URI is not a valid file URI.
|
|
850
|
+
*/
|
|
851
|
+
fileUriToPath(uri: string): string;
|
|
852
|
+
/**
|
|
853
|
+
* Convert a local file path to a file:// URI.
|
|
854
|
+
* Handles Windows drive letters and special characters.
|
|
855
|
+
* Returns an empty string if the path cannot be converted.
|
|
856
|
+
*/
|
|
857
|
+
pathToFileUri(path: string): string;
|
|
858
|
+
/**
|
|
839
859
|
* Get the UTF-8 byte length of a JavaScript string.
|
|
840
860
|
*
|
|
841
861
|
* JS strings are UTF-16 internally, so `str.length` returns the number of
|
|
@@ -1147,6 +1167,10 @@ interface EditorAPI {
|
|
|
1147
1167
|
*/
|
|
1148
1168
|
setLineIndicator(bufferId: number, line: number, namespace: string, symbol: string, r: number, g: number, b: number, priority: number): boolean;
|
|
1149
1169
|
/**
|
|
1170
|
+
* Batch set line indicators in the gutter
|
|
1171
|
+
*/
|
|
1172
|
+
setLineIndicators(bufferId: number, lines: number[], namespace: string, symbol: string, r: number, g: number, b: number, priority: number): boolean;
|
|
1173
|
+
/**
|
|
1150
1174
|
* Clear line indicators in a namespace
|
|
1151
1175
|
*/
|
|
1152
1176
|
clearLineIndicators(bufferId: number, namespace: string): boolean;
|