@fresh-editor/fresh-editor 0.2.20 → 0.2.21
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 +40 -0
- package/package.json +1 -1
- package/plugins/config-schema.json +23 -18
- package/plugins/git_explorer.ts +6 -0
- package/plugins/theme_editor.i18n.json +42 -14
- package/plugins/theme_editor.ts +30 -3
- package/plugins/vi_mode.ts +189 -51
- package/themes/high-contrast.json +66 -66
- package/themes/light.json +18 -18
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,45 @@
|
|
|
1
1
|
# Release Notes
|
|
2
2
|
|
|
3
|
+
## 0.2.21
|
|
4
|
+
|
|
5
|
+
### Features
|
|
6
|
+
|
|
7
|
+
* **Fast Completions without LSP**: New basic completions providers without language server — buffer-word candidates appear below LSP results in the popup. Also, a new setting (config) controls auto-trigger vs explicit Ctrl+Space (default: explicit). Enter dismisses the popup (Tab accepts). I plan to further improve it (make it more intelligent) in future releases.
|
|
8
|
+
|
|
9
|
+
* **Current Line Highlighting**: Highlights the cursor line. Enabled by default, togglable from the command palette and Settings UI (caveat: wrapped lines are currently highlighted in their entirety, this should probably be changed to visual lines).
|
|
10
|
+
|
|
11
|
+
* **LSP Code Actions**: Code action modal now actually works! Select an action by number or up/down arrows and enter (#1405). Supports resolve, execute command, and server-initiated workspace edits (previously dropped silently). File create/rename/delete operations handled. Actions from multiple servers unified into one popup. Default keybinding changed to Alt+. - because Ctrl+. is filtered by many terminals.
|
|
12
|
+
|
|
13
|
+
* **LSP Completion Resolve and Formatting**: Auto-imports applied on completion accept. Format Buffer falls back to LSP when no external formatter is configured. Also adds range formatting and pre-rename validation.
|
|
14
|
+
|
|
15
|
+
* **LSP Server Selection for Restart/Stop**: Popup to choose which server to restart/stop individually, or all at once.
|
|
16
|
+
|
|
17
|
+
* **Grammar Listing**: `fresh --cmd grammar list` and `editor.listGrammars()` plugin API show all available grammars with source and extensions. When specifying a grammar in a `languages` entry in the config, you must currently use a full name from this list - for example "Bourne Again Shell (bash)" rather than "bash". This will be improved once I add grammar aliases.
|
|
18
|
+
|
|
19
|
+
### Improvements
|
|
20
|
+
|
|
21
|
+
* **Theme Contrast**: Replaced all named ANSI colors with explicit RGB in built-in themes for deterministic rendering. Improved contrast ratios across both high-contrast and light themes. Diagnostic and semantic overlays now re-apply correctly on theme change, including during live preview.
|
|
22
|
+
|
|
23
|
+
* **Git Status Marker Refresh**: File explorer markers update on terminal focus gain and by polling for git index changes (#1431).
|
|
24
|
+
|
|
25
|
+
* **Config-Only Languages**: Custom languages without a built-in grammar (e.g., "fish") appear in the Set Language popup and are detected correctly — no more fallthrough to wrong built-in grammars.
|
|
26
|
+
|
|
27
|
+
* **Theme Inspector**: Records exact theme keys during rendering instead of reverse-mapping via heuristics. Theme editor Save As improved for built-in themes.
|
|
28
|
+
|
|
29
|
+
* **LSP Reliability**: Diagnostics cleared on server stop/crash, buffers re-opened on server start, document version checking for workspace edits, LSP notified after undo/redo of bulk edits, pending requests drained on server death to prevent deadlocks, hover suppressed while popups are visible.
|
|
30
|
+
|
|
31
|
+
### Vim Mode
|
|
32
|
+
|
|
33
|
+
22 bug fixes: C/D/S/cc, e motion, nG, h/l line clamping, ^, $, J with space, f/t special chars, r replace, ~ toggle case, visual mode entry/switching, count display. Key motions moved from async plugin commands to native Rust actions, eliminating race conditions.
|
|
34
|
+
|
|
35
|
+
If you use the Vim plugin please drop a note at https://github.com/sinelaw/fresh/discussions/417 - I need feedback on this feature.
|
|
36
|
+
|
|
37
|
+
### Bug Fixes
|
|
38
|
+
|
|
39
|
+
* Fixed Ctrl+W panic on accented/multi-byte characters (#1332).
|
|
40
|
+
|
|
41
|
+
* Fixed LSP diagnostics from stopped servers reappearing from queued messages.
|
|
42
|
+
|
|
3
43
|
## 0.2.20
|
|
4
44
|
|
|
5
45
|
### Features
|
package/package.json
CHANGED
|
@@ -32,6 +32,7 @@
|
|
|
32
32
|
"default": {
|
|
33
33
|
"line_numbers": true,
|
|
34
34
|
"relative_line_numbers": false,
|
|
35
|
+
"highlight_current_line": true,
|
|
35
36
|
"line_wrap": true,
|
|
36
37
|
"wrap_indent": true,
|
|
37
38
|
"wrap_column": null,
|
|
@@ -66,10 +67,10 @@
|
|
|
66
67
|
"ensure_final_newline_on_save": false,
|
|
67
68
|
"highlight_matching_brackets": true,
|
|
68
69
|
"rainbow_brackets": true,
|
|
70
|
+
"completion_popup_auto_show": false,
|
|
69
71
|
"quick_suggestions": true,
|
|
70
72
|
"quick_suggestions_delay_ms": 150,
|
|
71
73
|
"suggest_on_trigger_characters": true,
|
|
72
|
-
"accept_suggestion_on_enter": "on",
|
|
73
74
|
"enable_inlay_hints": true,
|
|
74
75
|
"enable_semantic_tokens_full": false,
|
|
75
76
|
"diagnostics_inline_text": false,
|
|
@@ -251,6 +252,12 @@
|
|
|
251
252
|
"default": false,
|
|
252
253
|
"x-section": "Display"
|
|
253
254
|
},
|
|
255
|
+
"highlight_current_line": {
|
|
256
|
+
"description": "Highlight the line containing the cursor",
|
|
257
|
+
"type": "boolean",
|
|
258
|
+
"default": true,
|
|
259
|
+
"x-section": "Display"
|
|
260
|
+
},
|
|
254
261
|
"line_wrap": {
|
|
255
262
|
"description": "Wrap long lines to fit the window width (default for new views)",
|
|
256
263
|
"type": "boolean",
|
|
@@ -474,8 +481,14 @@
|
|
|
474
481
|
"default": true,
|
|
475
482
|
"x-section": "Bracket Matching"
|
|
476
483
|
},
|
|
484
|
+
"completion_popup_auto_show": {
|
|
485
|
+
"description": "Automatically show the completion popup while typing.\nWhen false (default), the popup only appears when explicitly invoked\n(e.g. via Ctrl+Space). When true, it appears automatically after a\nshort delay while typing.\nDefault: false",
|
|
486
|
+
"type": "boolean",
|
|
487
|
+
"default": false,
|
|
488
|
+
"x-section": "Completion"
|
|
489
|
+
},
|
|
477
490
|
"quick_suggestions": {
|
|
478
|
-
"description": "Enable quick suggestions (VS Code-like behavior).\nWhen enabled, completion suggestions appear automatically while typing,\nnot just on trigger characters (like `.` or `::`).\nDefault: true",
|
|
491
|
+
"description": "Enable quick suggestions (VS Code-like behavior).\nWhen enabled, completion suggestions appear automatically while typing,\nnot just on trigger characters (like `.` or `::`).\nOnly takes effect when completion_popup_auto_show is true.\nDefault: true",
|
|
479
492
|
"type": "boolean",
|
|
480
493
|
"default": true,
|
|
481
494
|
"x-section": "Completion"
|
|
@@ -494,12 +507,6 @@
|
|
|
494
507
|
"default": true,
|
|
495
508
|
"x-section": "Completion"
|
|
496
509
|
},
|
|
497
|
-
"accept_suggestion_on_enter": {
|
|
498
|
-
"description": "Controls whether pressing Enter accepts the selected completion.\n - \"on\": Enter always accepts the completion\n - \"off\": Enter inserts a newline (use Tab to accept)\n - \"smart\": Enter accepts only if the completion text differs from typed text\n\nDefault: \"on\"",
|
|
499
|
-
"$ref": "#/$defs/AcceptSuggestionOnEnter",
|
|
500
|
-
"default": "on",
|
|
501
|
-
"x-section": "Completion"
|
|
502
|
-
},
|
|
503
510
|
"enable_inlay_hints": {
|
|
504
511
|
"description": "Whether to enable LSP inlay hints (type hints, parameter hints, etc.)",
|
|
505
512
|
"type": "boolean",
|
|
@@ -687,16 +694,6 @@
|
|
|
687
694
|
],
|
|
688
695
|
"default": "lf"
|
|
689
696
|
},
|
|
690
|
-
"AcceptSuggestionOnEnter": {
|
|
691
|
-
"description": "Controls whether Enter accepts a completion suggestion",
|
|
692
|
-
"type": "string",
|
|
693
|
-
"enum": [
|
|
694
|
-
"on",
|
|
695
|
-
"off",
|
|
696
|
-
"smart"
|
|
697
|
-
],
|
|
698
|
-
"default": "on"
|
|
699
|
-
},
|
|
700
697
|
"FileExplorerConfig": {
|
|
701
698
|
"description": "File explorer configuration",
|
|
702
699
|
"type": "object",
|
|
@@ -1020,6 +1017,14 @@
|
|
|
1020
1017
|
"$ref": "#/$defs/OnSaveAction"
|
|
1021
1018
|
},
|
|
1022
1019
|
"default": []
|
|
1020
|
+
},
|
|
1021
|
+
"word_characters": {
|
|
1022
|
+
"description": "Extra characters (beyond alphanumeric and `_`) considered part of\nidentifiers for this language. Used by dabbrev and buffer-word\ncompletion to correctly tokenise language-specific naming conventions.\n\nExamples:\n- Lisp/Clojure/CSS: `\"-\"` (kebab-case identifiers)\n- PHP/Bash: `\"$\"` (variable sigils)\n- Ruby: `\"?!\"` (predicate/bang methods)\n- Rust (default): `\"\"` (standard alphanumeric + underscore)",
|
|
1023
|
+
"type": [
|
|
1024
|
+
"string",
|
|
1025
|
+
"null"
|
|
1026
|
+
],
|
|
1027
|
+
"default": null
|
|
1023
1028
|
}
|
|
1024
1029
|
},
|
|
1025
1030
|
"x-display-field": "/grammar"
|
package/plugins/git_explorer.ts
CHANGED
|
@@ -156,8 +156,14 @@ function onGitExplorerEditorInitialized() {
|
|
|
156
156
|
}
|
|
157
157
|
registerHandler("onGitExplorerEditorInitialized", onGitExplorerEditorInitialized);
|
|
158
158
|
|
|
159
|
+
function onGitExplorerFocusGained() {
|
|
160
|
+
refreshGitExplorerDecorations();
|
|
161
|
+
}
|
|
162
|
+
registerHandler("onGitExplorerFocusGained", onGitExplorerFocusGained);
|
|
163
|
+
|
|
159
164
|
editor.on("after_file_open", "onGitExplorerAfterFileOpen");
|
|
160
165
|
editor.on("after_file_save", "onGitExplorerAfterFileSave");
|
|
161
166
|
editor.on("editor_initialized", "onGitExplorerEditorInitialized");
|
|
167
|
+
editor.on("focus_gained", "onGitExplorerFocusGained");
|
|
162
168
|
|
|
163
169
|
refreshGitExplorerDecorations();
|
|
@@ -300,7 +300,9 @@
|
|
|
300
300
|
"field.punctuation_bracket": "závorka",
|
|
301
301
|
"field.punctuation_bracket_desc": "závorkas ({, }, (, ), [, ])",
|
|
302
302
|
"field.punctuation_delimiter": "oddělovač",
|
|
303
|
-
"field.punctuation_delimiter_desc": "oddělovačs (;, ,, .)"
|
|
303
|
+
"field.punctuation_delimiter_desc": "oddělovačs (;, ,, .)",
|
|
304
|
+
"suggestion.current_builtin": "(aktuální · vestavěný · pouze pro čtení)",
|
|
305
|
+
"prompt.save_as_builtin_error": "Nelze přepsat vestavěný motiv, zvolte jiný název: "
|
|
304
306
|
},
|
|
305
307
|
"de": {
|
|
306
308
|
"cmd.edit_theme": "Theme bearbeiten",
|
|
@@ -603,7 +605,9 @@
|
|
|
603
605
|
"field.punctuation_bracket": "Klammer",
|
|
604
606
|
"field.punctuation_bracket_desc": "Klammern ({, }, (, ), [, ])",
|
|
605
607
|
"field.punctuation_delimiter": "Trennzeichen",
|
|
606
|
-
"field.punctuation_delimiter_desc": "Trennzeichen (;, ,, .)"
|
|
608
|
+
"field.punctuation_delimiter_desc": "Trennzeichen (;, ,, .)",
|
|
609
|
+
"suggestion.current_builtin": "(aktuell · eingebaut · schreibgeschützt)",
|
|
610
|
+
"prompt.save_as_builtin_error": "Eingebautes Theme kann nicht überschrieben werden, anderen Namen wählen: "
|
|
607
611
|
},
|
|
608
612
|
"en": {
|
|
609
613
|
"cmd.edit_theme": "Edit Theme",
|
|
@@ -906,7 +910,9 @@
|
|
|
906
910
|
"field.punctuation_bracket": "Punctuation Bracket",
|
|
907
911
|
"field.punctuation_bracket_desc": "Brackets and parentheses ({, }, (, ), [, ])",
|
|
908
912
|
"field.punctuation_delimiter": "Punctuation Delimiter",
|
|
909
|
-
"field.punctuation_delimiter_desc": "Delimiters and separators (;, ,, .)"
|
|
913
|
+
"field.punctuation_delimiter_desc": "Delimiters and separators (;, ,, .)",
|
|
914
|
+
"suggestion.current_builtin": "(current · built-in · read-only)",
|
|
915
|
+
"prompt.save_as_builtin_error": "Can't override built-in theme, choose a different name: "
|
|
910
916
|
},
|
|
911
917
|
"es": {
|
|
912
918
|
"cmd.edit_theme": "Editar tema",
|
|
@@ -1209,7 +1215,9 @@
|
|
|
1209
1215
|
"field.punctuation_bracket": "Paréntesis",
|
|
1210
1216
|
"field.punctuation_bracket_desc": "Paréntesis y corchetes ({, }, (, ), [, ])",
|
|
1211
1217
|
"field.punctuation_delimiter": "Delimitador",
|
|
1212
|
-
"field.punctuation_delimiter_desc": "Delimitadores y separadores (;, ,, .)"
|
|
1218
|
+
"field.punctuation_delimiter_desc": "Delimitadores y separadores (;, ,, .)",
|
|
1219
|
+
"suggestion.current_builtin": "(actual · predefinido · solo lectura)",
|
|
1220
|
+
"prompt.save_as_builtin_error": "No se puede sobrescribir un tema predefinido, elija otro nombre: "
|
|
1213
1221
|
},
|
|
1214
1222
|
"fr": {
|
|
1215
1223
|
"cmd.edit_theme": "Modifier le theme",
|
|
@@ -1512,7 +1520,9 @@
|
|
|
1512
1520
|
"field.punctuation_bracket": "Parenthese",
|
|
1513
1521
|
"field.punctuation_bracket_desc": "Parentheses et crochets ({, }, (, ), [, ])",
|
|
1514
1522
|
"field.punctuation_delimiter": "Delimiteur",
|
|
1515
|
-
"field.punctuation_delimiter_desc": "Delimiteurs et separateurs (;, ,, .)"
|
|
1523
|
+
"field.punctuation_delimiter_desc": "Delimiteurs et separateurs (;, ,, .)",
|
|
1524
|
+
"suggestion.current_builtin": "(actuel · intégré · lecture seule)",
|
|
1525
|
+
"prompt.save_as_builtin_error": "Impossible de remplacer un thème intégré, choisissez un autre nom : "
|
|
1516
1526
|
},
|
|
1517
1527
|
"ja": {
|
|
1518
1528
|
"cmd.edit_theme": "テーマを編集",
|
|
@@ -1815,7 +1825,9 @@
|
|
|
1815
1825
|
"field.punctuation_bracket": "括弧",
|
|
1816
1826
|
"field.punctuation_bracket_desc": "括弧 ({、}、(、)、[、])",
|
|
1817
1827
|
"field.punctuation_delimiter": "区切り文字",
|
|
1818
|
-
"field.punctuation_delimiter_desc": "区切り文字 (;、,、.)"
|
|
1828
|
+
"field.punctuation_delimiter_desc": "区切り文字 (;、,、.)",
|
|
1829
|
+
"suggestion.current_builtin": "(現在 · 組み込み · 読み取り専用)",
|
|
1830
|
+
"prompt.save_as_builtin_error": "組み込みテーマは上書きできません。別の名前を入力してください: "
|
|
1819
1831
|
},
|
|
1820
1832
|
"ko": {
|
|
1821
1833
|
"cmd.edit_theme": "편집 Theme",
|
|
@@ -2118,7 +2130,9 @@
|
|
|
2118
2130
|
"field.punctuation_bracket": "괄호",
|
|
2119
2131
|
"field.punctuation_bracket_desc": "괄호s ({, }, (, ), [, ])",
|
|
2120
2132
|
"field.punctuation_delimiter": "구분자",
|
|
2121
|
-
"field.punctuation_delimiter_desc": "구분자s (;, ,, .)"
|
|
2133
|
+
"field.punctuation_delimiter_desc": "구분자s (;, ,, .)",
|
|
2134
|
+
"suggestion.current_builtin": "(현재 · 기본 제공 · 읽기 전용)",
|
|
2135
|
+
"prompt.save_as_builtin_error": "기본 제공 테마를 덮어쓸 수 없습니다. 다른 이름을 입력하세요: "
|
|
2122
2136
|
},
|
|
2123
2137
|
"pt-BR": {
|
|
2124
2138
|
"cmd.edit_theme": "editar Theme",
|
|
@@ -2421,7 +2435,9 @@
|
|
|
2421
2435
|
"field.punctuation_bracket": "parêntese",
|
|
2422
2436
|
"field.punctuation_bracket_desc": "parênteses ({, }, (, ), [, ])",
|
|
2423
2437
|
"field.punctuation_delimiter": "delimitador",
|
|
2424
|
-
"field.punctuation_delimiter_desc": "delimitadors (;, ,, .)"
|
|
2438
|
+
"field.punctuation_delimiter_desc": "delimitadors (;, ,, .)",
|
|
2439
|
+
"suggestion.current_builtin": "(atual · integrado · somente leitura)",
|
|
2440
|
+
"prompt.save_as_builtin_error": "Não é possível sobrescrever tema integrado, escolha outro nome: "
|
|
2425
2441
|
},
|
|
2426
2442
|
"ru": {
|
|
2427
2443
|
"cmd.edit_theme": "редактировать Theme",
|
|
@@ -2724,7 +2740,9 @@
|
|
|
2724
2740
|
"field.punctuation_bracket": "скобка",
|
|
2725
2741
|
"field.punctuation_bracket_desc": "скобкаs ({, }, (, ), [, ])",
|
|
2726
2742
|
"field.punctuation_delimiter": "разделитель",
|
|
2727
|
-
"field.punctuation_delimiter_desc": "разделительs (;, ,, .)"
|
|
2743
|
+
"field.punctuation_delimiter_desc": "разделительs (;, ,, .)",
|
|
2744
|
+
"suggestion.current_builtin": "(текущий · встроенная · только чтение)",
|
|
2745
|
+
"prompt.save_as_builtin_error": "Невозможно перезаписать встроенную тему, выберите другое имя: "
|
|
2728
2746
|
},
|
|
2729
2747
|
"th": {
|
|
2730
2748
|
"cmd.edit_theme": "แก้ไข Theme",
|
|
@@ -3027,7 +3045,9 @@
|
|
|
3027
3045
|
"field.punctuation_bracket": "วงเล็บ",
|
|
3028
3046
|
"field.punctuation_bracket_desc": "วงเล็บs ({, }, (, ), [, ])",
|
|
3029
3047
|
"field.punctuation_delimiter": "ตัวคั่น",
|
|
3030
|
-
"field.punctuation_delimiter_desc": "ตัวคั่นs (;, ,, .)"
|
|
3048
|
+
"field.punctuation_delimiter_desc": "ตัวคั่นs (;, ,, .)",
|
|
3049
|
+
"suggestion.current_builtin": "(ปัจจุบัน · ในตัว · อ่านอย่างเดียว)",
|
|
3050
|
+
"prompt.save_as_builtin_error": "ไม่สามารถเขียนทับธีมในตัวได้ กรุณาเลือกชื่ออื่น: "
|
|
3031
3051
|
},
|
|
3032
3052
|
"uk": {
|
|
3033
3053
|
"cmd.edit_theme": "редагувати Theme",
|
|
@@ -3330,7 +3350,9 @@
|
|
|
3330
3350
|
"field.punctuation_bracket": "дужка",
|
|
3331
3351
|
"field.punctuation_bracket_desc": "дужкаs ({, }, (, ), [, ])",
|
|
3332
3352
|
"field.punctuation_delimiter": "роздільник",
|
|
3333
|
-
"field.punctuation_delimiter_desc": "роздільникs (;, ,, .)"
|
|
3353
|
+
"field.punctuation_delimiter_desc": "роздільникs (;, ,, .)",
|
|
3354
|
+
"suggestion.current_builtin": "(поточний · вбудована · лише читання)",
|
|
3355
|
+
"prompt.save_as_builtin_error": "Неможливо перезаписати вбудовану тему, виберіть іншу назву: "
|
|
3334
3356
|
},
|
|
3335
3357
|
"vi": {
|
|
3336
3358
|
"cmd.edit_theme": "Chỉnh sửa giao diện",
|
|
@@ -3633,7 +3655,9 @@
|
|
|
3633
3655
|
"field.punctuation_bracket": "Dấu ngoặc",
|
|
3634
3656
|
"field.punctuation_bracket_desc": "Dấu ngoặc ({, }, (, ), [, ])",
|
|
3635
3657
|
"field.punctuation_delimiter": "Dấu phân cách",
|
|
3636
|
-
"field.punctuation_delimiter_desc": "Dấu phân cách (;, ,, .)"
|
|
3658
|
+
"field.punctuation_delimiter_desc": "Dấu phân cách (;, ,, .)",
|
|
3659
|
+
"suggestion.current_builtin": "(hiện tại · có sẵn · chỉ đọc)",
|
|
3660
|
+
"prompt.save_as_builtin_error": "Không thể ghi đè chủ đề có sẵn, chọn tên khác: "
|
|
3637
3661
|
},
|
|
3638
3662
|
"zh-CN": {
|
|
3639
3663
|
"cmd.edit_theme": "编辑主题",
|
|
@@ -3936,7 +3960,9 @@
|
|
|
3936
3960
|
"field.punctuation_bracket": "括号",
|
|
3937
3961
|
"field.punctuation_bracket_desc": "括号 ({、}、(、)、[、])",
|
|
3938
3962
|
"field.punctuation_delimiter": "分隔符",
|
|
3939
|
-
"field.punctuation_delimiter_desc": "分隔符 (;、,、.)"
|
|
3963
|
+
"field.punctuation_delimiter_desc": "分隔符 (;、,、.)",
|
|
3964
|
+
"suggestion.current_builtin": "(当前 · 内置 · 只读)",
|
|
3965
|
+
"prompt.save_as_builtin_error": "无法覆盖内置主题,请选择其他名称: "
|
|
3940
3966
|
},
|
|
3941
3967
|
"it": {
|
|
3942
3968
|
"cmd.edit_theme": "Modifica tema",
|
|
@@ -4239,6 +4265,8 @@
|
|
|
4239
4265
|
"field.punctuation_bracket": "Parentesi",
|
|
4240
4266
|
"field.punctuation_bracket_desc": "Parentesi e parentesi quadre ({, }, (, ), [, ])",
|
|
4241
4267
|
"field.punctuation_delimiter": "Delimitatore",
|
|
4242
|
-
"field.punctuation_delimiter_desc": "Delimitatori e separatori (;, ,, .)"
|
|
4268
|
+
"field.punctuation_delimiter_desc": "Delimitatori e separatori (;, ,, .)",
|
|
4269
|
+
"suggestion.current_builtin": "(corrente · integrato · sola lettura)",
|
|
4270
|
+
"prompt.save_as_builtin_error": "Impossibile sovrascrivere il tema integrato, scegli un altro nome: "
|
|
4243
4271
|
}
|
|
4244
4272
|
}
|
package/plugins/theme_editor.ts
CHANGED
|
@@ -355,6 +355,8 @@ interface ThemeEditorState {
|
|
|
355
355
|
savedCursorPath: string | null;
|
|
356
356
|
/** Whether to close the editor after a successful save */
|
|
357
357
|
closeAfterSave: boolean;
|
|
358
|
+
/** Whether the Save As prompt has been pre-filled (to distinguish first vs second Enter) */
|
|
359
|
+
saveAsPreFilled: boolean;
|
|
358
360
|
/** Which panel has focus */
|
|
359
361
|
focusPanel: "tree" | "picker";
|
|
360
362
|
/** Focus target within picker panel */
|
|
@@ -420,6 +422,7 @@ const state: ThemeEditorState = {
|
|
|
420
422
|
isBuiltin: false,
|
|
421
423
|
savedCursorPath: null,
|
|
422
424
|
closeAfterSave: false,
|
|
425
|
+
saveAsPreFilled: false,
|
|
423
426
|
focusPanel: "tree",
|
|
424
427
|
pickerFocus: { type: "hex-input" },
|
|
425
428
|
filterText: "",
|
|
@@ -1604,10 +1607,31 @@ async function onThemeSaveAsPromptConfirmed(args: {
|
|
|
1604
1607
|
|
|
1605
1608
|
const name = args.input.trim();
|
|
1606
1609
|
if (name) {
|
|
1610
|
+
// If user accepted a suggestion without typing, pre-fill the prompt so they can edit the name
|
|
1611
|
+
if (args.selected_index !== null && !state.saveAsPreFilled) {
|
|
1612
|
+
state.saveAsPreFilled = true;
|
|
1613
|
+
editor.startPromptWithInitial(editor.t("prompt.save_as"), "theme-save-as", name);
|
|
1614
|
+
editor.setPromptSuggestions([{
|
|
1615
|
+
text: state.themeName,
|
|
1616
|
+
description: state.isBuiltin
|
|
1617
|
+
? editor.t("suggestion.current_builtin")
|
|
1618
|
+
: editor.t("suggestion.current"),
|
|
1619
|
+
value: state.themeName,
|
|
1620
|
+
}]);
|
|
1621
|
+
return true;
|
|
1622
|
+
}
|
|
1623
|
+
state.saveAsPreFilled = false;
|
|
1624
|
+
|
|
1607
1625
|
// Reject names that match a built-in theme
|
|
1608
1626
|
if (state.builtinThemes.includes(name)) {
|
|
1609
|
-
editor.
|
|
1610
|
-
|
|
1627
|
+
editor.startPromptWithInitial(editor.t("prompt.save_as_builtin_error"), "theme-save-as", name);
|
|
1628
|
+
editor.setPromptSuggestions([{
|
|
1629
|
+
text: state.themeName,
|
|
1630
|
+
description: state.isBuiltin
|
|
1631
|
+
? editor.t("suggestion.current_builtin")
|
|
1632
|
+
: editor.t("suggestion.current"),
|
|
1633
|
+
value: state.themeName,
|
|
1634
|
+
}]);
|
|
1611
1635
|
return true;
|
|
1612
1636
|
}
|
|
1613
1637
|
|
|
@@ -2757,11 +2781,14 @@ function theme_editor_save_as() : void {
|
|
|
2757
2781
|
state.savedCursorPath = getCurrentFieldPath();
|
|
2758
2782
|
}
|
|
2759
2783
|
|
|
2784
|
+
state.saveAsPreFilled = false;
|
|
2760
2785
|
editor.startPrompt(editor.t("prompt.save_as"), "theme-save-as");
|
|
2761
2786
|
|
|
2762
2787
|
editor.setPromptSuggestions([{
|
|
2763
2788
|
text: state.themeName,
|
|
2764
|
-
description:
|
|
2789
|
+
description: state.isBuiltin
|
|
2790
|
+
? editor.t("suggestion.current_builtin")
|
|
2791
|
+
: editor.t("suggestion.current"),
|
|
2765
2792
|
value: state.themeName,
|
|
2766
2793
|
}]);
|
|
2767
2794
|
}
|
package/plugins/vi_mode.ts
CHANGED
|
@@ -64,6 +64,14 @@ const state: ViState = {
|
|
|
64
64
|
visualBlockAnchor: null,
|
|
65
65
|
};
|
|
66
66
|
|
|
67
|
+
// Safe getBufferText that clamps end to buffer length
|
|
68
|
+
async function safeGetBufferText(bufferId: number, start: number, end: number): Promise<string | null> {
|
|
69
|
+
const bufLen = editor.getBufferLength(bufferId);
|
|
70
|
+
const clampedEnd = Math.min(end, bufLen);
|
|
71
|
+
if (clampedEnd <= start) return null;
|
|
72
|
+
return editor.getBufferText(bufferId, start, clampedEnd);
|
|
73
|
+
}
|
|
74
|
+
|
|
67
75
|
// Mode indicator for status bar
|
|
68
76
|
function getModeIndicator(mode: ViMode): string {
|
|
69
77
|
const countPrefix = state.count !== null ? `${state.count} ` : "";
|
|
@@ -179,7 +187,11 @@ function getCount(): number {
|
|
|
179
187
|
// Returns the count (defaults to 1)
|
|
180
188
|
function consumeCount(): number {
|
|
181
189
|
const count = state.count ?? 1;
|
|
182
|
-
state.count
|
|
190
|
+
if (state.count !== null) {
|
|
191
|
+
state.count = null;
|
|
192
|
+
// Update status to clear the count display
|
|
193
|
+
editor.setStatus(getModeIndicator(state.mode));
|
|
194
|
+
}
|
|
183
195
|
return count;
|
|
184
196
|
}
|
|
185
197
|
|
|
@@ -212,6 +224,7 @@ const motionToSelection: Record<string, string> = {
|
|
|
212
224
|
move_down: "select_down",
|
|
213
225
|
move_word_left: "select_word_left",
|
|
214
226
|
move_word_right: "select_word_right",
|
|
227
|
+
vi_move_word_end: "vi_select_word_end",
|
|
215
228
|
move_line_start: "select_line_start",
|
|
216
229
|
move_line_end: "select_line_end",
|
|
217
230
|
move_document_start: "select_document_start",
|
|
@@ -227,6 +240,7 @@ const atomicOperatorActions: OperatorMotionMap = {
|
|
|
227
240
|
// Delete operators
|
|
228
241
|
move_word_right: "delete_word_forward",
|
|
229
242
|
move_word_left: "delete_word_backward",
|
|
243
|
+
vi_move_word_end: "delete_vi_word_end",
|
|
230
244
|
move_line_end: "delete_to_line_end",
|
|
231
245
|
move_line_start: "delete_to_line_start",
|
|
232
246
|
},
|
|
@@ -234,6 +248,7 @@ const atomicOperatorActions: OperatorMotionMap = {
|
|
|
234
248
|
// Yank operators
|
|
235
249
|
move_word_right: "yank_word_forward",
|
|
236
250
|
move_word_left: "yank_word_backward",
|
|
251
|
+
vi_move_word_end: "yank_vi_word_end",
|
|
237
252
|
move_line_end: "yank_to_line_end",
|
|
238
253
|
move_line_start: "yank_to_line_start",
|
|
239
254
|
},
|
|
@@ -325,7 +340,8 @@ function handleMotionWithOperator(motionAction: string): void {
|
|
|
325
340
|
|
|
326
341
|
// Navigation (all support count prefix, e.g., 5j moves down 5 lines)
|
|
327
342
|
function vi_left() : void {
|
|
328
|
-
|
|
343
|
+
// h — line-bounded move left (vim doesn't wrap across lines)
|
|
344
|
+
executeWithCount("move_left_in_line");
|
|
329
345
|
}
|
|
330
346
|
registerHandler("vi_left", vi_left);
|
|
331
347
|
|
|
@@ -340,7 +356,8 @@ function vi_up() : void {
|
|
|
340
356
|
registerHandler("vi_up", vi_up);
|
|
341
357
|
|
|
342
358
|
function vi_right() : void {
|
|
343
|
-
|
|
359
|
+
// l — line-bounded move right (vim doesn't wrap across lines)
|
|
360
|
+
executeWithCount("move_right_in_line");
|
|
344
361
|
}
|
|
345
362
|
registerHandler("vi_right", vi_right);
|
|
346
363
|
|
|
@@ -355,12 +372,8 @@ function vi_word_back() : void {
|
|
|
355
372
|
registerHandler("vi_word_back", vi_word_back);
|
|
356
373
|
|
|
357
374
|
function vi_word_end() : void {
|
|
358
|
-
//
|
|
359
|
-
|
|
360
|
-
for (let i = 0; i < count; i++) {
|
|
361
|
-
editor.executeAction("move_word_right");
|
|
362
|
-
editor.executeAction("move_left");
|
|
363
|
-
}
|
|
375
|
+
// Vim 'e' motion — uses native vi_move_word_end action
|
|
376
|
+
executeWithCount("vi_move_word_end");
|
|
364
377
|
}
|
|
365
378
|
registerHandler("vi_word_end", vi_word_end);
|
|
366
379
|
|
|
@@ -373,13 +386,36 @@ registerHandler("vi_line_start", vi_line_start);
|
|
|
373
386
|
function vi_line_end() : void {
|
|
374
387
|
consumeCount(); // Count doesn't apply to line end
|
|
375
388
|
editor.executeAction("move_line_end");
|
|
389
|
+
// In vim normal mode, cursor should be ON the last char, not past it
|
|
390
|
+
// move_line_end goes past the last char; move_left corrects this
|
|
391
|
+
editor.executeAction("move_left");
|
|
376
392
|
}
|
|
377
393
|
registerHandler("vi_line_end", vi_line_end);
|
|
378
394
|
|
|
379
|
-
function vi_first_non_blank() : void {
|
|
395
|
+
async function vi_first_non_blank() : Promise<void> {
|
|
380
396
|
consumeCount(); // Count doesn't apply
|
|
381
|
-
|
|
382
|
-
|
|
397
|
+
// Get line start position directly (avoids stale snapshot from executeAction)
|
|
398
|
+
const line = editor.getCursorLine();
|
|
399
|
+
const bufferId = editor.getActiveBufferId();
|
|
400
|
+
const lineStart = await editor.getLineStartPosition(line);
|
|
401
|
+
if (lineStart === null) {
|
|
402
|
+
editor.executeAction("move_line_start");
|
|
403
|
+
return;
|
|
404
|
+
}
|
|
405
|
+
const text = await safeGetBufferText(bufferId, lineStart, lineStart + 200);
|
|
406
|
+
if (text) {
|
|
407
|
+
let offset = 0;
|
|
408
|
+
while (offset < text.length && (text[offset] === ' ' || text[offset] === '\t')) {
|
|
409
|
+
offset++;
|
|
410
|
+
}
|
|
411
|
+
if (offset < text.length && text[offset] !== '\n' && text[offset] !== '\r') {
|
|
412
|
+
editor.setBufferCursor(bufferId, lineStart + offset);
|
|
413
|
+
} else {
|
|
414
|
+
editor.setBufferCursor(bufferId, lineStart);
|
|
415
|
+
}
|
|
416
|
+
} else {
|
|
417
|
+
editor.executeAction("move_line_start");
|
|
418
|
+
}
|
|
383
419
|
}
|
|
384
420
|
registerHandler("vi_first_non_blank", vi_first_non_blank);
|
|
385
421
|
|
|
@@ -390,8 +426,22 @@ function vi_doc_start() : void {
|
|
|
390
426
|
registerHandler("vi_doc_start", vi_doc_start);
|
|
391
427
|
|
|
392
428
|
function vi_doc_end() : void {
|
|
393
|
-
|
|
394
|
-
|
|
429
|
+
const count = state.count;
|
|
430
|
+
consumeCount();
|
|
431
|
+
if (count !== null) {
|
|
432
|
+
// nG = go to line n (1-indexed; goto_line expects 0-indexed internally)
|
|
433
|
+
// Use setBufferCursor to move to line start via getLineStartPosition
|
|
434
|
+
const line = count - 1; // Convert to 0-indexed
|
|
435
|
+
editor.getLineStartPosition(line).then((pos) => {
|
|
436
|
+
if (pos !== null) {
|
|
437
|
+
editor.setBufferCursor(editor.getActiveBufferId(), pos);
|
|
438
|
+
}
|
|
439
|
+
});
|
|
440
|
+
} else {
|
|
441
|
+
editor.executeAction("move_document_end");
|
|
442
|
+
}
|
|
443
|
+
// Update status to clear any count display
|
|
444
|
+
editor.setStatus(getModeIndicator(state.mode));
|
|
395
445
|
}
|
|
396
446
|
registerHandler("vi_doc_end", vi_doc_end);
|
|
397
447
|
|
|
@@ -489,13 +539,10 @@ registerHandler("vi_delete_line", vi_delete_line);
|
|
|
489
539
|
function vi_change_line() : void {
|
|
490
540
|
const count = consumeCount();
|
|
491
541
|
state.lastChange = { type: "line-op", action: "change_line", count };
|
|
542
|
+
// Select from line start to line end, then cut (avoids stale snapshot issue)
|
|
492
543
|
editor.executeAction("move_line_start");
|
|
493
|
-
|
|
494
|
-
editor.executeAction("
|
|
495
|
-
const end = editor.getCursorPosition();
|
|
496
|
-
if (start !== null && end !== null) {
|
|
497
|
-
editor.deleteRange(editor.getActiveBufferId(), start, end);
|
|
498
|
-
}
|
|
544
|
+
editor.executeAction("select_line_end");
|
|
545
|
+
editor.executeAction("cut");
|
|
499
546
|
switchMode("insert");
|
|
500
547
|
}
|
|
501
548
|
registerHandler("vi_change_line", vi_change_line);
|
|
@@ -535,11 +582,27 @@ function vi_delete_char_before() : void {
|
|
|
535
582
|
registerHandler("vi_delete_char_before", vi_delete_char_before);
|
|
536
583
|
|
|
537
584
|
function vi_replace_char() : void {
|
|
538
|
-
//
|
|
539
|
-
|
|
585
|
+
// Enter replace-char mode to read the replacement character
|
|
586
|
+
state.mode = "find-char"; // Reuse find-char mode mechanism
|
|
587
|
+
editor.setEditorMode("vi-replace-char");
|
|
588
|
+
editor.setStatus("-- REPLACE CHAR --");
|
|
540
589
|
}
|
|
541
590
|
registerHandler("vi_replace_char", vi_replace_char);
|
|
542
591
|
|
|
592
|
+
// Handler for replacement character input
|
|
593
|
+
async function vi_replace_char_handler(char: string): Promise<void> {
|
|
594
|
+
const count = consumeCount();
|
|
595
|
+
// Replace character(s) under cursor without moving
|
|
596
|
+
for (let i = 0; i < count; i++) {
|
|
597
|
+
editor.executeAction("delete_forward");
|
|
598
|
+
editor.insertAtCursor(char);
|
|
599
|
+
}
|
|
600
|
+
// Move cursor back to stay on the replaced char (vim behavior)
|
|
601
|
+
editor.executeAction("move_left");
|
|
602
|
+
switchMode("normal");
|
|
603
|
+
}
|
|
604
|
+
registerHandler("vi_replace_char_handler", vi_replace_char_handler);
|
|
605
|
+
|
|
543
606
|
// Substitute (delete char and enter insert mode)
|
|
544
607
|
function vi_substitute() : void {
|
|
545
608
|
const count = consumeCount();
|
|
@@ -553,27 +616,19 @@ function vi_substitute() : void {
|
|
|
553
616
|
}
|
|
554
617
|
registerHandler("vi_substitute", vi_substitute);
|
|
555
618
|
|
|
556
|
-
// Delete to end of line
|
|
619
|
+
// Delete to end of line (D)
|
|
557
620
|
function vi_delete_to_end() : void {
|
|
558
621
|
state.lastChange = { type: "operator-motion", operator: "d", motion: "move_line_end" };
|
|
559
|
-
|
|
560
|
-
editor.executeAction("
|
|
561
|
-
const end = editor.getCursorPosition();
|
|
562
|
-
if (start !== null && end !== null && end > start) {
|
|
563
|
-
editor.deleteRange(editor.getActiveBufferId(), start, end);
|
|
564
|
-
}
|
|
622
|
+
// Use the atomic delete_to_line_end action to avoid stale snapshot issues
|
|
623
|
+
editor.executeAction("delete_to_line_end");
|
|
565
624
|
}
|
|
566
625
|
registerHandler("vi_delete_to_end", vi_delete_to_end);
|
|
567
626
|
|
|
568
|
-
// Change to end of line
|
|
627
|
+
// Change to end of line (C)
|
|
569
628
|
function vi_change_to_end() : void {
|
|
570
629
|
state.lastChange = { type: "operator-motion", operator: "c", motion: "move_line_end" };
|
|
571
|
-
|
|
572
|
-
editor.executeAction("
|
|
573
|
-
const end = editor.getCursorPosition();
|
|
574
|
-
if (start !== null && end !== null && end > start) {
|
|
575
|
-
editor.deleteRange(editor.getActiveBufferId(), start, end);
|
|
576
|
-
}
|
|
630
|
+
// Use the atomic delete_to_line_end action to avoid stale snapshot issues
|
|
631
|
+
editor.executeAction("delete_to_line_end");
|
|
577
632
|
switchMode("insert");
|
|
578
633
|
}
|
|
579
634
|
registerHandler("vi_change_to_end", vi_change_to_end);
|
|
@@ -665,14 +720,10 @@ async function vi_repeat() : Promise<void> {
|
|
|
665
720
|
editor.executeAction("delete_line");
|
|
666
721
|
}
|
|
667
722
|
} else if (change.action === "change_line") {
|
|
668
|
-
// Change line:
|
|
723
|
+
// Change line: select line content, cut, insert text
|
|
669
724
|
editor.executeAction("move_line_start");
|
|
670
|
-
|
|
671
|
-
editor.executeAction("
|
|
672
|
-
const end = editor.getCursorPosition();
|
|
673
|
-
if (start !== null && end !== null) {
|
|
674
|
-
editor.deleteRange(editor.getActiveBufferId(), start, end);
|
|
675
|
-
}
|
|
725
|
+
editor.executeAction("select_line_end");
|
|
726
|
+
editor.executeAction("cut");
|
|
676
727
|
if (change.insertedText) {
|
|
677
728
|
editor.insertAtCursor(change.insertedText);
|
|
678
729
|
}
|
|
@@ -721,14 +772,22 @@ async function vi_repeat() : Promise<void> {
|
|
|
721
772
|
}
|
|
722
773
|
registerHandler("vi_repeat", vi_repeat);
|
|
723
774
|
|
|
724
|
-
// Join lines
|
|
775
|
+
// Join lines — delete newline at end of current line and insert a space
|
|
725
776
|
function vi_join() : void {
|
|
726
777
|
editor.executeAction("move_line_end");
|
|
778
|
+
// Delete the newline character
|
|
727
779
|
editor.executeAction("delete_forward");
|
|
728
|
-
|
|
780
|
+
// Insert a space between the joined content
|
|
781
|
+
editor.insertAtCursor(" ");
|
|
729
782
|
}
|
|
730
783
|
registerHandler("vi_join", vi_join);
|
|
731
784
|
|
|
785
|
+
// Toggle case (~) — uses native toggle_case action
|
|
786
|
+
function vi_toggle_case() : void {
|
|
787
|
+
executeWithCount("toggle_case");
|
|
788
|
+
}
|
|
789
|
+
registerHandler("vi_toggle_case", vi_toggle_case);
|
|
790
|
+
|
|
732
791
|
// Search
|
|
733
792
|
function vi_search_forward() : void {
|
|
734
793
|
editor.executeAction("search");
|
|
@@ -822,7 +881,9 @@ registerHandler("vi_op_digit_0_or_line_start", vi_op_digit_0_or_line_start);
|
|
|
822
881
|
// Enter character-wise visual mode
|
|
823
882
|
function vi_visual_char() : void {
|
|
824
883
|
state.visualAnchor = editor.getCursorPosition();
|
|
825
|
-
// Select
|
|
884
|
+
// Select the character under cursor to establish the anchor.
|
|
885
|
+
// This moves cursor one position right (the selection end), which is
|
|
886
|
+
// standard visual mode behavior — the first char is part of the selection.
|
|
826
887
|
editor.executeAction("select_right");
|
|
827
888
|
switchMode("visual");
|
|
828
889
|
}
|
|
@@ -831,8 +892,7 @@ registerHandler("vi_visual_char", vi_visual_char);
|
|
|
831
892
|
// Enter line-wise visual mode
|
|
832
893
|
function vi_visual_line() : void {
|
|
833
894
|
state.visualAnchor = editor.getCursorPosition();
|
|
834
|
-
// Select
|
|
835
|
-
editor.executeAction("move_line_start");
|
|
895
|
+
// Select full line including newline (select_line selects and moves to next line)
|
|
836
896
|
editor.executeAction("select_line");
|
|
837
897
|
switchMode("visual-line");
|
|
838
898
|
}
|
|
@@ -989,6 +1049,7 @@ function vi_vis_word_back() : void {
|
|
|
989
1049
|
registerHandler("vi_vis_word_back", vi_vis_word_back);
|
|
990
1050
|
|
|
991
1051
|
function vi_vis_word_end() : void {
|
|
1052
|
+
// Extend selection to end of word
|
|
992
1053
|
const count = consumeCount();
|
|
993
1054
|
for (let i = 0; i < count; i++) {
|
|
994
1055
|
editor.executeAction("select_word_right");
|
|
@@ -1557,6 +1618,13 @@ function vi_op_word_back(): void {
|
|
|
1557
1618
|
}
|
|
1558
1619
|
registerHandler("vi_op_word_back", vi_op_word_back);
|
|
1559
1620
|
|
|
1621
|
+
// Operator-pending e (word end) - select to word end, then apply operator
|
|
1622
|
+
// Operator-pending e (word end) — uses native vi_move_word_end motion
|
|
1623
|
+
function vi_op_word_end(): void {
|
|
1624
|
+
handleMotionWithOperator("vi_move_word_end");
|
|
1625
|
+
}
|
|
1626
|
+
registerHandler("vi_op_word_end", vi_op_word_end);
|
|
1627
|
+
|
|
1560
1628
|
function vi_op_line_start(): void {
|
|
1561
1629
|
handleMotionWithOperator("move_line_start");
|
|
1562
1630
|
}
|
|
@@ -1680,6 +1748,7 @@ editor.defineMode("vi-normal", [
|
|
|
1680
1748
|
|
|
1681
1749
|
// Other
|
|
1682
1750
|
["J", "vi_join"],
|
|
1751
|
+
["~", "vi_toggle_case"],
|
|
1683
1752
|
|
|
1684
1753
|
// Command mode
|
|
1685
1754
|
[":", "vi_command_mode"],
|
|
@@ -1829,6 +1898,24 @@ registerHandler("vi_fc_9", vi_fc_9);
|
|
|
1829
1898
|
async function vi_fc_space(): Promise<void> { return vi_find_char_handler(" "); }
|
|
1830
1899
|
registerHandler("vi_fc_space", vi_fc_space);
|
|
1831
1900
|
|
|
1901
|
+
// Punctuation character handlers for find-char mode
|
|
1902
|
+
const punctuationChars: [string, string][] = [
|
|
1903
|
+
["!", "excl"], ["@", "at"], ["#", "hash"], ["$", "dollar"], ["%", "percent"],
|
|
1904
|
+
["^", "caret"], ["&", "amp"], ["*", "star"], ["(", "lparen"], [")", "rparen"],
|
|
1905
|
+
["-", "minus"], ["_", "underscore"], ["=", "equals"], ["+", "plus"],
|
|
1906
|
+
["[", "lbracket"], ["]", "rbracket"], ["{", "lbrace"], ["}", "rbrace"],
|
|
1907
|
+
["\\", "backslash"], ["|", "pipe"], [";", "semi"], [":", "colon"],
|
|
1908
|
+
["'", "squote"], ["\"", "dquote"], [",", "comma"], [".", "dot"],
|
|
1909
|
+
["<", "lt"], [">", "gt"], ["/", "slash"], ["?", "question"], ["`", "backtick"],
|
|
1910
|
+
["~", "tilde"],
|
|
1911
|
+
];
|
|
1912
|
+
|
|
1913
|
+
for (const [char, name] of punctuationChars) {
|
|
1914
|
+
const handlerName = `vi_fc_p_${name}`;
|
|
1915
|
+
const handler = async (): Promise<void> => { return vi_find_char_handler(char); };
|
|
1916
|
+
registerHandler(handlerName, handler);
|
|
1917
|
+
}
|
|
1918
|
+
|
|
1832
1919
|
// Define vi-find-char mode with all the character bindings
|
|
1833
1920
|
editor.defineMode("vi-find-char", [
|
|
1834
1921
|
["Escape", "vi_find_char_cancel"],
|
|
@@ -1851,8 +1938,56 @@ editor.defineMode("vi-find-char", [
|
|
|
1851
1938
|
["0", "vi_fc_0"], ["1", "vi_fc_1"], ["2", "vi_fc_2"], ["3", "vi_fc_3"],
|
|
1852
1939
|
["4", "vi_fc_4"], ["5", "vi_fc_5"], ["6", "vi_fc_6"], ["7", "vi_fc_7"],
|
|
1853
1940
|
["8", "vi_fc_8"], ["9", "vi_fc_9"],
|
|
1854
|
-
//
|
|
1941
|
+
// Space and punctuation
|
|
1855
1942
|
["Space", "vi_fc_space"],
|
|
1943
|
+
["!", "vi_fc_p_excl"], ["@", "vi_fc_p_at"], ["#", "vi_fc_p_hash"],
|
|
1944
|
+
["$", "vi_fc_p_dollar"], ["%", "vi_fc_p_percent"], ["^", "vi_fc_p_caret"],
|
|
1945
|
+
["&", "vi_fc_p_amp"], ["*", "vi_fc_p_star"], ["(", "vi_fc_p_lparen"],
|
|
1946
|
+
[")", "vi_fc_p_rparen"], ["-", "vi_fc_p_minus"], ["_", "vi_fc_p_underscore"],
|
|
1947
|
+
["=", "vi_fc_p_equals"], ["+", "vi_fc_p_plus"], ["[", "vi_fc_p_lbracket"],
|
|
1948
|
+
["]", "vi_fc_p_rbracket"], ["{", "vi_fc_p_lbrace"], ["}", "vi_fc_p_rbrace"],
|
|
1949
|
+
["\\", "vi_fc_p_backslash"], ["|", "vi_fc_p_pipe"], [";", "vi_fc_p_semi"],
|
|
1950
|
+
[":", "vi_fc_p_colon"], ["'", "vi_fc_p_squote"], ["\"", "vi_fc_p_dquote"],
|
|
1951
|
+
[",", "vi_fc_p_comma"], [".", "vi_fc_p_dot"], ["<", "vi_fc_p_lt"],
|
|
1952
|
+
[">", "vi_fc_p_gt"], ["/", "vi_fc_p_slash"], ["?", "vi_fc_p_question"],
|
|
1953
|
+
["`", "vi_fc_p_backtick"], ["~", "vi_fc_p_tilde"],
|
|
1954
|
+
], true);
|
|
1955
|
+
|
|
1956
|
+
// Define vi-replace-char mode — reuses find-char handlers but calls vi_replace_char_handler
|
|
1957
|
+
// We create replace-char specific handlers that delegate to the replace handler
|
|
1958
|
+
const rcHandlers: [string, string][] = [];
|
|
1959
|
+
for (const c of "abcdefghijklmnopqrstuvwxyz") {
|
|
1960
|
+
const name = `vi_rc_${c}`;
|
|
1961
|
+
const handler = async (): Promise<void> => { return vi_replace_char_handler(c); };
|
|
1962
|
+
registerHandler(name, handler);
|
|
1963
|
+
rcHandlers.push([c, name]);
|
|
1964
|
+
}
|
|
1965
|
+
for (const c of "ABCDEFGHIJKLMNOPQRSTUVWXYZ") {
|
|
1966
|
+
const name = `vi_rc_${c}`;
|
|
1967
|
+
const handler = async (): Promise<void> => { return vi_replace_char_handler(c); };
|
|
1968
|
+
registerHandler(name, handler);
|
|
1969
|
+
rcHandlers.push([c, name]);
|
|
1970
|
+
}
|
|
1971
|
+
for (const c of "0123456789") {
|
|
1972
|
+
const name = `vi_rc_d${c}`;
|
|
1973
|
+
const handler = async (): Promise<void> => { return vi_replace_char_handler(c); };
|
|
1974
|
+
registerHandler(name, handler);
|
|
1975
|
+
rcHandlers.push([c, name]);
|
|
1976
|
+
}
|
|
1977
|
+
// Space and common punctuation for replace-char mode
|
|
1978
|
+
const rcSpaceHandler = async (): Promise<void> => { return vi_replace_char_handler(" "); };
|
|
1979
|
+
registerHandler("vi_rc_space", rcSpaceHandler);
|
|
1980
|
+
for (const [char, pname] of punctuationChars) {
|
|
1981
|
+
const name = `vi_rc_p_${pname}`;
|
|
1982
|
+
const handler = async (): Promise<void> => { return vi_replace_char_handler(char); };
|
|
1983
|
+
registerHandler(name, handler);
|
|
1984
|
+
}
|
|
1985
|
+
|
|
1986
|
+
editor.defineMode("vi-replace-char", [
|
|
1987
|
+
["Escape", "vi_find_char_cancel"],
|
|
1988
|
+
...rcHandlers.map(([key, name]): [string, string] => [key, name]),
|
|
1989
|
+
["Space", "vi_rc_space"],
|
|
1990
|
+
...punctuationChars.map(([char, pname]): [string, string] => [char, `vi_rc_p_${pname}`]),
|
|
1856
1991
|
], true);
|
|
1857
1992
|
|
|
1858
1993
|
// Define vi-operator-pending mode
|
|
@@ -1876,6 +2011,7 @@ editor.defineMode("vi-operator-pending", [
|
|
|
1876
2011
|
["l", "vi_op_right"],
|
|
1877
2012
|
["w", "vi_op_word"],
|
|
1878
2013
|
["b", "vi_op_word_back"],
|
|
2014
|
+
["e", "vi_op_word_end"],
|
|
1879
2015
|
["$", "vi_op_line_end"],
|
|
1880
2016
|
["g g", "vi_op_doc_start"],
|
|
1881
2017
|
["G", "vi_op_doc_end"],
|
|
@@ -1948,8 +2084,9 @@ editor.defineMode("vi-visual", [
|
|
|
1948
2084
|
["g g", "vi_vis_doc_start"],
|
|
1949
2085
|
["G", "vi_vis_doc_end"],
|
|
1950
2086
|
|
|
1951
|
-
// Switch
|
|
2087
|
+
// Switch visual sub-modes
|
|
1952
2088
|
["V", "vi_visual_toggle_line"],
|
|
2089
|
+
["C-v", "vi_visual_block"], // Switch to block mode
|
|
1953
2090
|
|
|
1954
2091
|
// Operators
|
|
1955
2092
|
["d", "vi_vis_delete"],
|
|
@@ -1986,8 +2123,9 @@ editor.defineMode("vi-visual-line", [
|
|
|
1986
2123
|
["g g", "vi_vis_doc_start"],
|
|
1987
2124
|
["G", "vi_vis_doc_end"],
|
|
1988
2125
|
|
|
1989
|
-
// Switch
|
|
2126
|
+
// Switch visual sub-modes
|
|
1990
2127
|
["v", "vi_visual_toggle_line"],
|
|
2128
|
+
["C-v", "vi_visual_block"], // Switch to block mode
|
|
1991
2129
|
|
|
1992
2130
|
// Operators
|
|
1993
2131
|
["d", "vi_vis_delete"],
|
|
@@ -1,103 +1,103 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "high-contrast",
|
|
3
3
|
"editor": {
|
|
4
|
-
"bg":
|
|
5
|
-
"fg":
|
|
6
|
-
"cursor":
|
|
7
|
-
"inactive_cursor":
|
|
4
|
+
"bg": [0, 0, 0],
|
|
5
|
+
"fg": [255, 255, 255],
|
|
6
|
+
"cursor": [255, 255, 255],
|
|
7
|
+
"inactive_cursor": [127, 127, 127],
|
|
8
8
|
"selection_bg": [0, 100, 200],
|
|
9
9
|
"current_line_bg": [20, 20, 20],
|
|
10
10
|
"line_number_fg": [140, 140, 140],
|
|
11
|
-
"line_number_bg":
|
|
12
|
-
"diff_add_bg": [0,
|
|
13
|
-
"diff_remove_bg": [
|
|
11
|
+
"line_number_bg": [0, 0, 0],
|
|
12
|
+
"diff_add_bg": [0, 35, 0],
|
|
13
|
+
"diff_remove_bg": [50, 0, 0],
|
|
14
14
|
"diff_modify_bg": [25, 22, 0],
|
|
15
15
|
"whitespace_indicator_fg": [80, 80, 80]
|
|
16
16
|
},
|
|
17
17
|
"ui": {
|
|
18
|
-
"tab_active_fg":
|
|
19
|
-
"tab_active_bg":
|
|
20
|
-
"tab_inactive_fg":
|
|
21
|
-
"tab_inactive_bg":
|
|
18
|
+
"tab_active_fg": [0, 0, 0],
|
|
19
|
+
"tab_active_bg": [255, 255, 0],
|
|
20
|
+
"tab_inactive_fg": [255, 255, 255],
|
|
21
|
+
"tab_inactive_bg": [0, 0, 0],
|
|
22
22
|
"tab_separator_bg": [30, 30, 35],
|
|
23
23
|
"tab_close_hover_fg": [249, 38, 114],
|
|
24
24
|
"tab_hover_bg": [50, 50, 55],
|
|
25
25
|
"menu_bg": [50, 50, 55],
|
|
26
|
-
"menu_fg":
|
|
27
|
-
"menu_active_bg":
|
|
28
|
-
"menu_active_fg":
|
|
26
|
+
"menu_fg": [255, 255, 255],
|
|
27
|
+
"menu_active_bg": [255, 255, 0],
|
|
28
|
+
"menu_active_fg": [0, 0, 0],
|
|
29
29
|
"menu_dropdown_bg": [20, 20, 20],
|
|
30
|
-
"menu_dropdown_fg":
|
|
30
|
+
"menu_dropdown_fg": [255, 255, 255],
|
|
31
31
|
"menu_highlight_bg": [0, 100, 200],
|
|
32
|
-
"menu_highlight_fg":
|
|
33
|
-
"menu_border_fg":
|
|
34
|
-
"menu_separator_fg":
|
|
32
|
+
"menu_highlight_fg": [255, 255, 255],
|
|
33
|
+
"menu_border_fg": [255, 255, 0],
|
|
34
|
+
"menu_separator_fg": [255, 255, 255],
|
|
35
35
|
"menu_hover_bg": [50, 50, 50],
|
|
36
|
-
"menu_hover_fg":
|
|
37
|
-
"menu_disabled_fg":
|
|
36
|
+
"menu_hover_fg": [255, 255, 0],
|
|
37
|
+
"menu_disabled_fg": [127, 127, 127],
|
|
38
38
|
"menu_disabled_bg": [20, 20, 20],
|
|
39
|
-
"status_bar_fg":
|
|
39
|
+
"status_bar_fg": [255, 255, 255],
|
|
40
40
|
"status_bar_bg": [20, 20, 20],
|
|
41
|
-
"prompt_fg":
|
|
41
|
+
"prompt_fg": [255, 255, 255],
|
|
42
42
|
"prompt_bg": [10, 10, 10],
|
|
43
|
-
"prompt_selection_fg":
|
|
43
|
+
"prompt_selection_fg": [255, 255, 255],
|
|
44
44
|
"prompt_selection_bg": [0, 100, 200],
|
|
45
|
-
"popup_border_fg":
|
|
46
|
-
"popup_bg":
|
|
45
|
+
"popup_border_fg": [0, 255, 255],
|
|
46
|
+
"popup_bg": [0, 0, 0],
|
|
47
47
|
"popup_selection_bg": [0, 100, 200],
|
|
48
|
-
"popup_text_fg":
|
|
49
|
-
"suggestion_bg":
|
|
48
|
+
"popup_text_fg": [255, 255, 255],
|
|
49
|
+
"suggestion_bg": [0, 0, 0],
|
|
50
50
|
"suggestion_selected_bg": [0, 100, 200],
|
|
51
|
-
"help_bg":
|
|
52
|
-
"help_fg":
|
|
53
|
-
"help_key_fg":
|
|
54
|
-
"help_separator_fg":
|
|
55
|
-
"help_indicator_fg":
|
|
56
|
-
"help_indicator_bg":
|
|
51
|
+
"help_bg": [0, 0, 0],
|
|
52
|
+
"help_fg": [255, 255, 255],
|
|
53
|
+
"help_key_fg": [0, 255, 255],
|
|
54
|
+
"help_separator_fg": [255, 255, 255],
|
|
55
|
+
"help_indicator_fg": [255, 80, 80],
|
|
56
|
+
"help_indicator_bg": [0, 0, 0],
|
|
57
57
|
"inline_code_bg": [40, 40, 40],
|
|
58
58
|
"split_separator_fg": [140, 140, 140],
|
|
59
|
-
"split_separator_hover_fg":
|
|
60
|
-
"scrollbar_track_fg":
|
|
61
|
-
"scrollbar_thumb_fg":
|
|
62
|
-
"scrollbar_track_hover_fg":
|
|
63
|
-
"scrollbar_thumb_hover_fg":
|
|
59
|
+
"split_separator_hover_fg": [255, 255, 0],
|
|
60
|
+
"scrollbar_track_fg": [255, 255, 255],
|
|
61
|
+
"scrollbar_thumb_fg": [255, 255, 0],
|
|
62
|
+
"scrollbar_track_hover_fg": [255, 255, 0],
|
|
63
|
+
"scrollbar_thumb_hover_fg": [0, 255, 255],
|
|
64
64
|
"compose_margin_bg": [10, 10, 10],
|
|
65
|
-
"semantic_highlight_bg": [0,
|
|
65
|
+
"semantic_highlight_bg": [0, 25, 55],
|
|
66
66
|
"terminal_bg": "Default",
|
|
67
67
|
"terminal_fg": "Default",
|
|
68
|
-
"status_warning_indicator_bg":
|
|
69
|
-
"status_warning_indicator_fg":
|
|
70
|
-
"status_error_indicator_bg":
|
|
71
|
-
"status_error_indicator_fg":
|
|
72
|
-
"status_warning_indicator_hover_bg":
|
|
73
|
-
"status_warning_indicator_hover_fg":
|
|
74
|
-
"status_error_indicator_hover_bg":
|
|
75
|
-
"status_error_indicator_hover_fg":
|
|
68
|
+
"status_warning_indicator_bg": [255, 255, 0],
|
|
69
|
+
"status_warning_indicator_fg": [0, 0, 0],
|
|
70
|
+
"status_error_indicator_bg": [255, 60, 60],
|
|
71
|
+
"status_error_indicator_fg": [255, 255, 255],
|
|
72
|
+
"status_warning_indicator_hover_bg": [255, 255, 100],
|
|
73
|
+
"status_warning_indicator_hover_fg": [0, 0, 0],
|
|
74
|
+
"status_error_indicator_hover_bg": [255, 100, 100],
|
|
75
|
+
"status_error_indicator_hover_fg": [255, 255, 255],
|
|
76
76
|
"tab_drop_zone_bg": [0, 100, 200],
|
|
77
|
-
"tab_drop_zone_border":
|
|
77
|
+
"tab_drop_zone_border": [255, 255, 0]
|
|
78
78
|
},
|
|
79
79
|
"search": {
|
|
80
|
-
"match_bg":
|
|
81
|
-
"match_fg":
|
|
80
|
+
"match_bg": [255, 255, 0],
|
|
81
|
+
"match_fg": [0, 0, 0]
|
|
82
82
|
},
|
|
83
83
|
"diagnostic": {
|
|
84
|
-
"error_fg":
|
|
85
|
-
"error_bg": [
|
|
86
|
-
"warning_fg":
|
|
87
|
-
"warning_bg": [
|
|
88
|
-
"info_fg":
|
|
89
|
-
"info_bg": [0,
|
|
90
|
-
"hint_fg":
|
|
91
|
-
"hint_bg": [
|
|
84
|
+
"error_fg": [255, 80, 80],
|
|
85
|
+
"error_bg": [50, 0, 0],
|
|
86
|
+
"warning_fg": [255, 255, 0],
|
|
87
|
+
"warning_bg": [35, 30, 0],
|
|
88
|
+
"info_fg": [0, 255, 255],
|
|
89
|
+
"info_bg": [0, 25, 55],
|
|
90
|
+
"hint_fg": [255, 255, 255],
|
|
91
|
+
"hint_bg": [30, 30, 30]
|
|
92
92
|
},
|
|
93
93
|
"syntax": {
|
|
94
|
-
"keyword":
|
|
95
|
-
"string":
|
|
96
|
-
"comment":
|
|
97
|
-
"function":
|
|
98
|
-
"type":
|
|
99
|
-
"variable":
|
|
100
|
-
"constant":
|
|
101
|
-
"operator":
|
|
94
|
+
"keyword": [0, 255, 255],
|
|
95
|
+
"string": [0, 205, 0],
|
|
96
|
+
"comment": [229, 229, 229],
|
|
97
|
+
"function": [255, 255, 0],
|
|
98
|
+
"type": [255, 85, 255],
|
|
99
|
+
"variable": [255, 255, 255],
|
|
100
|
+
"constant": [120, 130, 255],
|
|
101
|
+
"operator": [255, 255, 255]
|
|
102
102
|
}
|
|
103
103
|
}
|
package/themes/light.json
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
"inactive_cursor": [180, 180, 180],
|
|
8
8
|
"selection_bg": [173, 214, 255],
|
|
9
9
|
"current_line_bg": [245, 245, 245],
|
|
10
|
-
"line_number_fg": [
|
|
10
|
+
"line_number_fg": [115, 115, 115],
|
|
11
11
|
"line_number_bg": [255, 255, 255],
|
|
12
12
|
"diff_add_bg": [200, 255, 200],
|
|
13
13
|
"diff_remove_bg": [255, 200, 200],
|
|
@@ -36,11 +36,11 @@
|
|
|
36
36
|
"menu_hover_fg": [0, 0, 0],
|
|
37
37
|
"menu_disabled_fg": [160, 160, 160],
|
|
38
38
|
"menu_disabled_bg": [248, 248, 248],
|
|
39
|
-
"status_bar_fg":
|
|
39
|
+
"status_bar_fg": [0, 0, 0],
|
|
40
40
|
"status_bar_bg": [220, 220, 220],
|
|
41
|
-
"prompt_fg":
|
|
41
|
+
"prompt_fg": [0, 0, 0],
|
|
42
42
|
"prompt_bg": [230, 240, 250],
|
|
43
|
-
"prompt_selection_fg":
|
|
43
|
+
"prompt_selection_fg": [0, 0, 0],
|
|
44
44
|
"prompt_selection_bg": [173, 214, 255],
|
|
45
45
|
"popup_border_fg": [140, 140, 140],
|
|
46
46
|
"popup_bg": [232, 238, 245],
|
|
@@ -48,12 +48,12 @@
|
|
|
48
48
|
"popup_text_fg": [30, 30, 30],
|
|
49
49
|
"suggestion_bg": [232, 238, 245],
|
|
50
50
|
"suggestion_selected_bg": [209, 226, 243],
|
|
51
|
-
"help_bg":
|
|
52
|
-
"help_fg":
|
|
53
|
-
"help_key_fg":
|
|
54
|
-
"help_separator_fg":
|
|
55
|
-
"help_indicator_fg":
|
|
56
|
-
"help_indicator_bg":
|
|
51
|
+
"help_bg": [255, 255, 255],
|
|
52
|
+
"help_fg": [0, 0, 0],
|
|
53
|
+
"help_key_fg": [0, 0, 180],
|
|
54
|
+
"help_separator_fg": [170, 170, 170],
|
|
55
|
+
"help_indicator_fg": [200, 30, 30],
|
|
56
|
+
"help_indicator_bg": [255, 255, 255],
|
|
57
57
|
"inline_code_bg": [230, 230, 235],
|
|
58
58
|
"split_separator_fg": [140, 140, 140],
|
|
59
59
|
"split_separator_hover_fg": [70, 130, 180],
|
|
@@ -81,14 +81,14 @@
|
|
|
81
81
|
"match_fg": [0, 0, 0]
|
|
82
82
|
},
|
|
83
83
|
"diagnostic": {
|
|
84
|
-
"error_fg":
|
|
85
|
-
"error_bg": [255,
|
|
86
|
-
"warning_fg": [
|
|
87
|
-
"warning_bg": [255,
|
|
88
|
-
"info_fg":
|
|
89
|
-
"info_bg": [
|
|
90
|
-
"hint_fg":
|
|
91
|
-
"hint_bg": [
|
|
84
|
+
"error_fg": [180, 0, 0],
|
|
85
|
+
"error_bg": [255, 210, 210],
|
|
86
|
+
"warning_fg": [150, 110, 0],
|
|
87
|
+
"warning_bg": [255, 248, 170],
|
|
88
|
+
"info_fg": [0, 0, 180],
|
|
89
|
+
"info_bg": [210, 230, 255],
|
|
90
|
+
"hint_fg": [100, 100, 100],
|
|
91
|
+
"hint_bg": [235, 235, 240]
|
|
92
92
|
},
|
|
93
93
|
"syntax": {
|
|
94
94
|
"keyword": [175, 0, 219],
|