@fresh-editor/fresh-editor 0.1.67 → 0.1.69

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.
Files changed (64) hide show
  1. package/CHANGELOG.md +58 -0
  2. package/README.md +2 -0
  3. package/package.json +1 -1
  4. package/plugins/audit_mode.i18n.json +380 -0
  5. package/plugins/audit_mode.ts +836 -68
  6. package/plugins/buffer_modified.i18n.json +32 -0
  7. package/plugins/buffer_modified.ts +5 -3
  8. package/plugins/calculator.i18n.json +44 -0
  9. package/plugins/calculator.ts +6 -4
  10. package/plugins/clangd-lsp.ts +2 -0
  11. package/plugins/clangd_support.i18n.json +104 -0
  12. package/plugins/clangd_support.ts +18 -16
  13. package/plugins/color_highlighter.i18n.json +68 -0
  14. package/plugins/color_highlighter.ts +12 -10
  15. package/plugins/config-schema.json +25 -140
  16. package/plugins/csharp-lsp.ts +2 -0
  17. package/plugins/csharp_support.i18n.json +38 -0
  18. package/plugins/csharp_support.ts +6 -4
  19. package/plugins/css-lsp.ts +2 -0
  20. package/plugins/diagnostics_panel.i18n.json +110 -0
  21. package/plugins/diagnostics_panel.ts +19 -17
  22. package/plugins/find_references.i18n.json +128 -0
  23. package/plugins/find_references.ts +22 -20
  24. package/plugins/git_blame.i18n.json +230 -0
  25. package/plugins/git_blame.ts +39 -37
  26. package/plugins/git_find_file.i18n.json +146 -0
  27. package/plugins/git_find_file.ts +24 -22
  28. package/plugins/git_grep.i18n.json +80 -0
  29. package/plugins/git_grep.ts +15 -13
  30. package/plugins/git_gutter.i18n.json +44 -0
  31. package/plugins/git_gutter.ts +7 -5
  32. package/plugins/git_log.i18n.json +224 -0
  33. package/plugins/git_log.ts +41 -39
  34. package/plugins/go-lsp.ts +2 -0
  35. package/plugins/html-lsp.ts +2 -0
  36. package/plugins/json-lsp.ts +2 -0
  37. package/plugins/lib/fresh.d.ts +53 -13
  38. package/plugins/lib/index.ts +1 -1
  39. package/plugins/lib/navigation-controller.ts +3 -3
  40. package/plugins/lib/panel-manager.ts +15 -13
  41. package/plugins/lib/virtual-buffer-factory.ts +84 -112
  42. package/plugins/live_grep.i18n.json +80 -0
  43. package/plugins/live_grep.ts +15 -13
  44. package/plugins/markdown_compose.i18n.json +104 -0
  45. package/plugins/markdown_compose.ts +17 -15
  46. package/plugins/merge_conflict.i18n.json +380 -0
  47. package/plugins/merge_conflict.ts +72 -73
  48. package/plugins/path_complete.i18n.json +38 -0
  49. package/plugins/path_complete.ts +6 -4
  50. package/plugins/python-lsp.ts +2 -0
  51. package/plugins/rust-lsp.ts +2 -0
  52. package/plugins/search_replace.i18n.json +188 -0
  53. package/plugins/search_replace.ts +31 -29
  54. package/plugins/test_i18n.i18n.json +12 -0
  55. package/plugins/test_i18n.ts +18 -0
  56. package/plugins/theme_editor.i18n.json +1417 -0
  57. package/plugins/theme_editor.ts +73 -69
  58. package/plugins/todo_highlighter.i18n.json +86 -0
  59. package/plugins/todo_highlighter.ts +15 -13
  60. package/plugins/typescript-lsp.ts +2 -0
  61. package/plugins/vi_mode.i18n.json +716 -0
  62. package/plugins/vi_mode.ts +1195 -78
  63. package/plugins/welcome.i18n.json +110 -0
  64. package/plugins/welcome.ts +18 -16
@@ -0,0 +1,224 @@
1
+ {
2
+ "en": {
3
+ "cmd.git_log": "Git Log",
4
+ "cmd.git_log_desc": "Show git log in magit-style interface",
5
+ "cmd.git_log_close": "Git Log: Close",
6
+ "cmd.git_log_close_desc": "Close the git log panel",
7
+ "cmd.git_log_refresh": "Git Log: Refresh",
8
+ "cmd.git_log_refresh_desc": "Refresh the git log",
9
+
10
+ "status.already_open": "Git log already open",
11
+ "status.loading": "Loading git log...",
12
+ "status.no_commits": "No commits found or not a git repository",
13
+ "status.closed": "Git log closed",
14
+ "status.failed_open": "Failed to open git log panel",
15
+ "status.refreshing": "Refreshing git log...",
16
+ "status.refreshed": "Git log refreshed: {count} commits",
17
+ "status.log_ready": "Git log: {count} commits | Up/Down: navigate | RET: show | q: quit",
18
+ "status.commit_position": "Commit {current}/{total}",
19
+ "status.move_to_commit": "Move cursor to a commit line",
20
+ "status.loading_commit": "Loading commit {hash}...",
21
+ "status.commit_ready": "Commit {hash} | Up/Down: navigate | RET: open file | q: back",
22
+ "status.failed_open_details": "Failed to open commit details",
23
+ "status.hash_copied": "Copied: {short} ({full})",
24
+ "status.hash_display": "Hash: {hash}",
25
+ "status.git_error": "Git log error: {error}",
26
+ "status.error_fetching_diff": "Error fetching diff: {error}",
27
+ "status.file_loading": "Loading {file} at {hash}...",
28
+ "status.file_not_found": "File {file} not found at commit {hash}",
29
+ "status.file_view_ready": "{file} @ {hash} (read-only) | Target: line {line} | q: back",
30
+ "status.failed_open_file": "Failed to open {file}",
31
+ "status.move_to_diff_with_context": "Move cursor to a diff line with file context",
32
+ "status.move_to_diff": "Move cursor to a diff line",
33
+
34
+ "panel.commits_header": "Commits:",
35
+ "panel.no_commits": " No commits found",
36
+ "panel.log_footer": "{count} commits | Up/Down/j/k: navigate | RET: show | y: yank hash | r: refresh | q: quit",
37
+ "panel.detail_footer": "Up/Down/j/k: navigate | RET: open file at line | q: back to log"
38
+ },
39
+ "es": {
40
+ "cmd.git_log": "Registro Git",
41
+ "cmd.git_log_desc": "Mostrar registro git en interfaz estilo magit",
42
+ "cmd.git_log_close": "Registro Git: Cerrar",
43
+ "cmd.git_log_close_desc": "Cerrar el panel de registro git",
44
+ "cmd.git_log_refresh": "Registro Git: Actualizar",
45
+ "cmd.git_log_refresh_desc": "Actualizar el registro git",
46
+
47
+ "status.already_open": "El registro git ya esta abierto",
48
+ "status.loading": "Cargando registro git...",
49
+ "status.no_commits": "No se encontraron commits o no es un repositorio git",
50
+ "status.closed": "Registro git cerrado",
51
+ "status.failed_open": "Error al abrir el panel de registro git",
52
+ "status.refreshing": "Actualizando registro git...",
53
+ "status.refreshed": "Registro git actualizado: {count} commits",
54
+ "status.log_ready": "Registro git: {count} commits | Arriba/Abajo: navegar | RET: mostrar | q: salir",
55
+ "status.commit_position": "Commit {current}/{total}",
56
+ "status.move_to_commit": "Mueve el cursor a una linea de commit",
57
+ "status.loading_commit": "Cargando commit {hash}...",
58
+ "status.commit_ready": "Commit {hash} | Arriba/Abajo: navegar | RET: abrir archivo | q: volver",
59
+ "status.failed_open_details": "Error al abrir detalles del commit",
60
+ "status.hash_copied": "Copiado: {short} ({full})",
61
+ "status.hash_display": "Hash: {hash}",
62
+ "status.git_error": "Error de registro git: {error}",
63
+ "status.error_fetching_diff": "Error al obtener diff: {error}",
64
+ "status.file_loading": "Cargando {file} en {hash}...",
65
+ "status.file_not_found": "Archivo {file} no encontrado en commit {hash}",
66
+ "status.file_view_ready": "{file} @ {hash} (solo lectura) | Objetivo: linea {line} | q: volver",
67
+ "status.failed_open_file": "Error al abrir {file}",
68
+ "status.move_to_diff_with_context": "Mueve el cursor a una linea de diff con contexto de archivo",
69
+ "status.move_to_diff": "Mueve el cursor a una linea de diff",
70
+
71
+ "panel.commits_header": "Commits:",
72
+ "panel.no_commits": " No se encontraron commits",
73
+ "panel.log_footer": "{count} commits | Arriba/Abajo/j/k: navegar | RET: mostrar | y: copiar hash | r: actualizar | q: salir",
74
+ "panel.detail_footer": "Arriba/Abajo/j/k: navegar | RET: abrir archivo en linea | q: volver al registro"
75
+ },
76
+ "de": {
77
+ "cmd.git_log": "Git-Protokoll",
78
+ "cmd.git_log_desc": "Git-Protokoll in Magit-Stil-Oberflache anzeigen",
79
+ "cmd.git_log_close": "Git-Protokoll: Schliessen",
80
+ "cmd.git_log_close_desc": "Git-Protokoll-Panel schliessen",
81
+ "cmd.git_log_refresh": "Git-Protokoll: Aktualisieren",
82
+ "cmd.git_log_refresh_desc": "Git-Protokoll aktualisieren",
83
+
84
+ "status.already_open": "Git-Protokoll bereits geoeffnet",
85
+ "status.loading": "Lade Git-Protokoll...",
86
+ "status.no_commits": "Keine Commits gefunden oder kein Git-Repository",
87
+ "status.closed": "Git-Protokoll geschlossen",
88
+ "status.failed_open": "Git-Protokoll-Panel konnte nicht geoeffnet werden",
89
+ "status.refreshing": "Aktualisiere Git-Protokoll...",
90
+ "status.refreshed": "Git-Protokoll aktualisiert: {count} Commits",
91
+ "status.log_ready": "Git-Protokoll: {count} Commits | Auf/Ab: navigieren | RET: anzeigen | q: beenden",
92
+ "status.commit_position": "Commit {current}/{total}",
93
+ "status.move_to_commit": "Cursor auf eine Commit-Zeile bewegen",
94
+ "status.loading_commit": "Lade Commit {hash}...",
95
+ "status.commit_ready": "Commit {hash} | Auf/Ab: navigieren | RET: Datei oeffnen | q: zurueck",
96
+ "status.failed_open_details": "Commit-Details konnten nicht geoeffnet werden",
97
+ "status.hash_copied": "Kopiert: {short} ({full})",
98
+ "status.hash_display": "Hash: {hash}",
99
+ "status.git_error": "Git-Protokoll-Fehler: {error}",
100
+ "status.error_fetching_diff": "Fehler beim Abrufen des Diffs: {error}",
101
+ "status.file_loading": "Lade {file} bei {hash}...",
102
+ "status.file_not_found": "Datei {file} nicht gefunden bei Commit {hash}",
103
+ "status.file_view_ready": "{file} @ {hash} (schreibgeschuetzt) | Ziel: Zeile {line} | q: zurueck",
104
+ "status.failed_open_file": "{file} konnte nicht geoeffnet werden",
105
+ "status.move_to_diff_with_context": "Cursor auf eine Diff-Zeile mit Dateikontext bewegen",
106
+ "status.move_to_diff": "Cursor auf eine Diff-Zeile bewegen",
107
+
108
+ "panel.commits_header": "Commits:",
109
+ "panel.no_commits": " Keine Commits gefunden",
110
+ "panel.log_footer": "{count} Commits | Auf/Ab/j/k: navigieren | RET: anzeigen | y: Hash kopieren | r: aktualisieren | q: beenden",
111
+ "panel.detail_footer": "Auf/Ab/j/k: navigieren | RET: Datei bei Zeile oeffnen | q: zurueck zum Protokoll"
112
+ },
113
+ "fr": {
114
+ "cmd.git_log": "Journal Git",
115
+ "cmd.git_log_desc": "Afficher le journal git en interface style magit",
116
+ "cmd.git_log_close": "Journal Git: Fermer",
117
+ "cmd.git_log_close_desc": "Fermer le panneau du journal git",
118
+ "cmd.git_log_refresh": "Journal Git: Actualiser",
119
+ "cmd.git_log_refresh_desc": "Actualiser le journal git",
120
+
121
+ "status.already_open": "Le journal git est deja ouvert",
122
+ "status.loading": "Chargement du journal git...",
123
+ "status.no_commits": "Aucun commit trouve ou ce n'est pas un depot git",
124
+ "status.closed": "Journal git ferme",
125
+ "status.failed_open": "Echec de l'ouverture du panneau du journal git",
126
+ "status.refreshing": "Actualisation du journal git...",
127
+ "status.refreshed": "Journal git actualise: {count} commits",
128
+ "status.log_ready": "Journal git: {count} commits | Haut/Bas: naviguer | RET: afficher | q: quitter",
129
+ "status.commit_position": "Commit {current}/{total}",
130
+ "status.move_to_commit": "Deplacez le curseur sur une ligne de commit",
131
+ "status.loading_commit": "Chargement du commit {hash}...",
132
+ "status.commit_ready": "Commit {hash} | Haut/Bas: naviguer | RET: ouvrir fichier | q: retour",
133
+ "status.failed_open_details": "Echec de l'ouverture des details du commit",
134
+ "status.hash_copied": "Copie: {short} ({full})",
135
+ "status.hash_display": "Hash: {hash}",
136
+ "status.git_error": "Erreur du journal git: {error}",
137
+ "status.error_fetching_diff": "Erreur lors de la recuperation du diff: {error}",
138
+ "status.file_loading": "Chargement de {file} a {hash}...",
139
+ "status.file_not_found": "Fichier {file} non trouve au commit {hash}",
140
+ "status.file_view_ready": "{file} @ {hash} (lecture seule) | Cible: ligne {line} | q: retour",
141
+ "status.failed_open_file": "Echec de l'ouverture de {file}",
142
+ "status.move_to_diff_with_context": "Deplacez le curseur sur une ligne de diff avec contexte de fichier",
143
+ "status.move_to_diff": "Deplacez le curseur sur une ligne de diff",
144
+
145
+ "panel.commits_header": "Commits:",
146
+ "panel.no_commits": " Aucun commit trouve",
147
+ "panel.log_footer": "{count} commits | Haut/Bas/j/k: naviguer | RET: afficher | y: copier hash | r: actualiser | q: quitter",
148
+ "panel.detail_footer": "Haut/Bas/j/k: naviguer | RET: ouvrir fichier a la ligne | q: retour au journal"
149
+ },
150
+ "ja": {
151
+ "cmd.git_log": "Gitログ",
152
+ "cmd.git_log_desc": "magitスタイルのインターフェースでgitログを表示",
153
+ "cmd.git_log_close": "Gitログ: 閉じる",
154
+ "cmd.git_log_close_desc": "gitログパネルを閉じる",
155
+ "cmd.git_log_refresh": "Gitログ: 更新",
156
+ "cmd.git_log_refresh_desc": "gitログを更新",
157
+
158
+ "status.already_open": "Gitログは既に開いています",
159
+ "status.loading": "Gitログを読み込み中...",
160
+ "status.no_commits": "コミットが見つからないか、gitリポジトリではありません",
161
+ "status.closed": "Gitログを閉じました",
162
+ "status.failed_open": "Gitログパネルを開けませんでした",
163
+ "status.refreshing": "Gitログを更新中...",
164
+ "status.refreshed": "Gitログを更新しました: {count}件のコミット",
165
+ "status.log_ready": "Gitログ: {count}件のコミット | 上/下: 移動 | RET: 表示 | q: 終了",
166
+ "status.commit_position": "コミット {current}/{total}",
167
+ "status.move_to_commit": "カーソルをコミット行に移動してください",
168
+ "status.loading_commit": "コミット {hash} を読み込み中...",
169
+ "status.commit_ready": "コミット {hash} | 上/下: 移動 | RET: ファイルを開く | q: 戻る",
170
+ "status.failed_open_details": "コミット詳細を開けませんでした",
171
+ "status.hash_copied": "コピーしました: {short} ({full})",
172
+ "status.hash_display": "ハッシュ: {hash}",
173
+ "status.git_error": "Gitログエラー: {error}",
174
+ "status.error_fetching_diff": "差分取得エラー: {error}",
175
+ "status.file_loading": "{file} を {hash} で読み込み中...",
176
+ "status.file_not_found": "コミット {hash} でファイル {file} が見つかりません",
177
+ "status.file_view_ready": "{file} @ {hash} (読み取り専用) | 対象: {line}行目 | q: 戻る",
178
+ "status.failed_open_file": "{file} を開けませんでした",
179
+ "status.move_to_diff_with_context": "ファイルコンテキストのある差分行にカーソルを移動してください",
180
+ "status.move_to_diff": "カーソルを差分行に移動してください",
181
+
182
+ "panel.commits_header": "コミット:",
183
+ "panel.no_commits": " コミットが見つかりません",
184
+ "panel.log_footer": "{count}件のコミット | 上/下/j/k: 移動 | RET: 表示 | y: ハッシュをコピー | r: 更新 | q: 終了",
185
+ "panel.detail_footer": "上/下/j/k: 移動 | RET: ファイルを行で開く | q: ログに戻る"
186
+ },
187
+ "zh": {
188
+ "cmd.git_log": "Git日志",
189
+ "cmd.git_log_desc": "以magit风格界面显示git日志",
190
+ "cmd.git_log_close": "Git日志: 关闭",
191
+ "cmd.git_log_close_desc": "关闭git日志面板",
192
+ "cmd.git_log_refresh": "Git日志: 刷新",
193
+ "cmd.git_log_refresh_desc": "刷新git日志",
194
+
195
+ "status.already_open": "Git日志已经打开",
196
+ "status.loading": "正在加载Git日志...",
197
+ "status.no_commits": "未找到提交或不是git仓库",
198
+ "status.closed": "Git日志已关闭",
199
+ "status.failed_open": "无法打开Git日志面板",
200
+ "status.refreshing": "正在刷新Git日志...",
201
+ "status.refreshed": "Git日志已刷新: {count}个提交",
202
+ "status.log_ready": "Git日志: {count}个提交 | 上/下: 导航 | RET: 显示 | q: 退出",
203
+ "status.commit_position": "提交 {current}/{total}",
204
+ "status.move_to_commit": "请将光标移动到提交行",
205
+ "status.loading_commit": "正在加载提交 {hash}...",
206
+ "status.commit_ready": "提交 {hash} | 上/下: 导航 | RET: 打开文件 | q: 返回",
207
+ "status.failed_open_details": "无法打开提交详情",
208
+ "status.hash_copied": "已复制: {short} ({full})",
209
+ "status.hash_display": "哈希: {hash}",
210
+ "status.git_error": "Git日志错误: {error}",
211
+ "status.error_fetching_diff": "获取差异时出错: {error}",
212
+ "status.file_loading": "正在加载 {file} 于 {hash}...",
213
+ "status.file_not_found": "在提交 {hash} 中未找到文件 {file}",
214
+ "status.file_view_ready": "{file} @ {hash} (只读) | 目标: 第{line}行 | q: 返回",
215
+ "status.failed_open_file": "无法打开 {file}",
216
+ "status.move_to_diff_with_context": "请将光标移动到带有文件上下文的差异行",
217
+ "status.move_to_diff": "请将光标移动到差异行",
218
+
219
+ "panel.commits_header": "提交:",
220
+ "panel.no_commits": " 未找到提交",
221
+ "panel.log_footer": "{count}个提交 | 上/下/j/k: 导航 | RET: 显示 | y: 复制哈希 | r: 刷新 | q: 退出",
222
+ "panel.detail_footer": "上/下/j/k: 导航 | RET: 在行处打开文件 | q: 返回日志"
223
+ }
224
+ }
@@ -1,4 +1,6 @@
1
1
  /// <reference path="../types/fresh.d.ts" />
2
+ const editor = getEditor();
3
+
2
4
 
3
5
  /**
4
6
  * Git Log Plugin - Magit-style Git Log Interface
@@ -185,7 +187,7 @@ async function fetchGitLog(): Promise<GitCommit[]> {
185
187
  const result = await editor.spawnProcess("git", args, cwd);
186
188
 
187
189
  if (result.exit_code !== 0) {
188
- editor.setStatus(`Git log error: ${result.stderr}`);
190
+ editor.setStatus(editor.t("status.git_error", { error: result.stderr }));
189
191
  return [];
190
192
  }
191
193
 
@@ -226,7 +228,7 @@ async function fetchCommitDiff(hash: string): Promise<string> {
226
228
  ], cwd);
227
229
 
228
230
  if (result.exit_code !== 0) {
229
- return `Error fetching diff: ${result.stderr}`;
231
+ return editor.t("status.error_fetching_diff", { error: result.stderr });
230
232
  }
231
233
 
232
234
  return result.stdout;
@@ -265,13 +267,13 @@ function buildGitLogEntries(): TextPropertyEntry[] {
265
267
 
266
268
  // Magit-style header
267
269
  entries.push({
268
- text: "Commits:\n",
270
+ text: editor.t("panel.commits_header") + "\n",
269
271
  properties: { type: "section-header" },
270
272
  });
271
273
 
272
274
  if (gitLogState.commits.length === 0) {
273
275
  entries.push({
274
- text: " No commits found\n",
276
+ text: editor.t("panel.no_commits") + "\n",
275
277
  properties: { type: "empty" },
276
278
  });
277
279
  } else {
@@ -301,7 +303,7 @@ function buildGitLogEntries(): TextPropertyEntry[] {
301
303
  properties: { type: "blank" },
302
304
  });
303
305
  entries.push({
304
- text: `${gitLogState.commits.length} commits | ↑/↓/j/k: navigate | RET: show | y: yank hash | r: refresh | q: quit\n`,
306
+ text: editor.t("panel.log_footer", { count: String(gitLogState.commits.length) }) + "\n",
305
307
  properties: { type: "footer" },
306
308
  });
307
309
 
@@ -333,7 +335,7 @@ function applyGitLogHighlighting(): void {
333
335
  const lineEnd = byteOffset + line.length;
334
336
 
335
337
  // Highlight section header
336
- if (line === "Commits:") {
338
+ if (line === editor.t("panel.commits_header")) {
337
339
  editor.addOverlay(
338
340
  bufferId,
339
341
  "gitlog",
@@ -590,7 +592,7 @@ function buildCommitDetailEntries(commit: GitCommit, showOutput: string): TextPr
590
592
  properties: { type: "blank" },
591
593
  });
592
594
  entries.push({
593
- text: `↑/↓/j/k: navigate | RET: open file at line | q: back to log\n`,
595
+ text: editor.t("panel.detail_footer") + "\n",
594
596
  properties: { type: "footer" },
595
597
  });
596
598
 
@@ -737,11 +739,11 @@ function applyCommitDetailHighlighting(): void {
737
739
 
738
740
  globalThis.show_git_log = async function(): Promise<void> {
739
741
  if (gitLogState.isOpen) {
740
- editor.setStatus("Git log already open");
742
+ editor.setStatus(editor.t("status.already_open"));
741
743
  return;
742
744
  }
743
745
 
744
- editor.setStatus("Loading git log...");
746
+ editor.setStatus(editor.t("status.loading"));
745
747
 
746
748
  // Store the current split ID and buffer ID before opening git log
747
749
  gitLogState.splitId = editor.getActiveSplitId();
@@ -751,7 +753,7 @@ globalThis.show_git_log = async function(): Promise<void> {
751
753
  gitLogState.commits = await fetchGitLog();
752
754
 
753
755
  if (gitLogState.commits.length === 0) {
754
- editor.setStatus("No commits found or not a git repository");
756
+ editor.setStatus(editor.t("status.no_commits"));
755
757
  gitLogState.splitId = null;
756
758
  return;
757
759
  }
@@ -779,11 +781,11 @@ globalThis.show_git_log = async function(): Promise<void> {
779
781
  // Apply syntax highlighting
780
782
  applyGitLogHighlighting();
781
783
 
782
- editor.setStatus(`Git log: ${gitLogState.commits.length} commits | ↑/↓: navigate | RET: show | q: quit`);
784
+ editor.setStatus(editor.t("status.log_ready", { count: String(gitLogState.commits.length) }));
783
785
  editor.debug("Git log panel opened");
784
786
  } else {
785
787
  gitLogState.splitId = null;
786
- editor.setStatus("Failed to open git log panel");
788
+ editor.setStatus(editor.t("status.failed_open"));
787
789
  }
788
790
  };
789
791
 
@@ -807,7 +809,7 @@ globalThis.git_log_close = function(): void {
807
809
  gitLogState.splitId = null;
808
810
  gitLogState.sourceBufferId = null;
809
811
  gitLogState.commits = [];
810
- editor.setStatus("Git log closed");
812
+ editor.setStatus(editor.t("status.closed"));
811
813
  };
812
814
 
813
815
  // Cursor moved handler for git log - update highlighting and status
@@ -831,7 +833,7 @@ globalThis.on_git_log_cursor_moved = function(data: {
831
833
  const commitIndex = cursorLine - headerLines;
832
834
 
833
835
  if (commitIndex >= 0 && commitIndex < gitLogState.commits.length) {
834
- editor.setStatus(`Commit ${commitIndex + 1}/${gitLogState.commits.length}`);
836
+ editor.setStatus(editor.t("status.commit_position", { current: String(commitIndex + 1), total: String(gitLogState.commits.length) }));
835
837
  }
836
838
  };
837
839
 
@@ -841,10 +843,10 @@ editor.on("cursor_moved", "on_git_log_cursor_moved");
841
843
  globalThis.git_log_refresh = async function(): Promise<void> {
842
844
  if (!gitLogState.isOpen) return;
843
845
 
844
- editor.setStatus("Refreshing git log...");
846
+ editor.setStatus(editor.t("status.refreshing"));
845
847
  gitLogState.commits = await fetchGitLog();
846
848
  updateGitLogView();
847
- editor.setStatus(`Git log refreshed: ${gitLogState.commits.length} commits`);
849
+ editor.setStatus(editor.t("status.refreshed", { count: String(gitLogState.commits.length) }));
848
850
  };
849
851
 
850
852
  // Helper function to get commit at current cursor position
@@ -879,11 +881,11 @@ globalThis.git_log_show_commit = async function(): Promise<void> {
879
881
 
880
882
  const commit = getCommitAtCursor();
881
883
  if (!commit) {
882
- editor.setStatus("Move cursor to a commit line");
884
+ editor.setStatus(editor.t("status.move_to_commit"));
883
885
  return;
884
886
  }
885
887
 
886
- editor.setStatus(`Loading commit ${commit.shortHash}...`);
888
+ editor.setStatus(editor.t("status.loading_commit", { hash: commit.shortHash }));
887
889
 
888
890
  // Fetch full commit info using git show (includes header and diff)
889
891
  const showOutput = await fetchCommitDiff(commit.hash);
@@ -915,9 +917,9 @@ globalThis.git_log_show_commit = async function(): Promise<void> {
915
917
  // Apply syntax highlighting
916
918
  applyCommitDetailHighlighting();
917
919
 
918
- editor.setStatus(`Commit ${commit.shortHash} | ↑/↓: navigate | RET: open file | q: back`);
920
+ editor.setStatus(editor.t("status.commit_ready", { hash: commit.shortHash }));
919
921
  } else {
920
- editor.setStatus("Failed to open commit details");
922
+ editor.setStatus(editor.t("status.failed_open_details"));
921
923
  }
922
924
  };
923
925
 
@@ -926,7 +928,7 @@ globalThis.git_log_copy_hash = function(): void {
926
928
 
927
929
  const commit = getCommitAtCursor();
928
930
  if (!commit) {
929
- editor.setStatus("Move cursor to a commit line");
931
+ editor.setStatus(editor.t("status.move_to_commit"));
930
932
  return;
931
933
  }
932
934
 
@@ -934,11 +936,11 @@ globalThis.git_log_copy_hash = function(): void {
934
936
  // Try xclip first (Linux), then pbcopy (macOS), then xsel
935
937
  editor.spawnProcess("sh", ["-c", `echo -n "${commit.hash}" | xclip -selection clipboard 2>/dev/null || echo -n "${commit.hash}" | pbcopy 2>/dev/null || echo -n "${commit.hash}" | xsel --clipboard 2>/dev/null`])
936
938
  .then(() => {
937
- editor.setStatus(`Copied: ${commit.shortHash} (${commit.hash})`);
939
+ editor.setStatus(editor.t("status.hash_copied", { short: commit.shortHash, full: commit.hash }));
938
940
  })
939
941
  .catch(() => {
940
942
  // If all clipboard commands fail, just show the hash
941
- editor.setStatus(`Hash: ${commit.hash}`);
943
+ editor.setStatus(editor.t("status.hash_display", { hash: commit.hash }));
942
944
  });
943
945
  };
944
946
 
@@ -968,7 +970,7 @@ globalThis.git_commit_detail_close = function(): void {
968
970
  commitDetailState.splitId = null;
969
971
  commitDetailState.commit = null;
970
972
 
971
- editor.setStatus(`Git log: ${gitLogState.commits.length} commits | ↑/↓: navigate | RET: show | q: quit`);
973
+ editor.setStatus(editor.t("status.log_ready", { count: String(gitLogState.commits.length) }));
972
974
  };
973
975
 
974
976
  // Close file view and go back to commit detail
@@ -996,7 +998,7 @@ globalThis.git_file_view_close = function(): void {
996
998
  fileViewState.commitHash = null;
997
999
 
998
1000
  if (commitDetailState.commit) {
999
- editor.setStatus(`Commit ${commitDetailState.commit.shortHash} | ↑/↓: navigate | RET: open file | q: back`);
1001
+ editor.setStatus(editor.t("status.commit_ready", { hash: commitDetailState.commit.shortHash }));
1000
1002
  }
1001
1003
  };
1002
1004
 
@@ -1181,7 +1183,7 @@ globalThis.git_commit_detail_open_file = async function(): Promise<void> {
1181
1183
 
1182
1184
  const commit = commitDetailState.commit;
1183
1185
  if (!commit) {
1184
- editor.setStatus("No commit context available");
1186
+ editor.setStatus(editor.t("status.move_to_commit"));
1185
1187
  return;
1186
1188
  }
1187
1189
 
@@ -1193,13 +1195,13 @@ globalThis.git_commit_detail_open_file = async function(): Promise<void> {
1193
1195
  const line = props[0].line as number | undefined;
1194
1196
 
1195
1197
  if (file) {
1196
- editor.setStatus(`Loading ${file} at ${commit.shortHash}...`);
1198
+ editor.setStatus(editor.t("status.file_loading", { file, hash: commit.shortHash }));
1197
1199
 
1198
1200
  // Fetch file content at this commit
1199
1201
  const content = await fetchFileAtCommit(commit.hash, file);
1200
1202
 
1201
1203
  if (content === null) {
1202
- editor.setStatus(`File ${file} not found at commit ${commit.shortHash}`);
1204
+ editor.setStatus(editor.t("status.file_not_found", { file, hash: commit.shortHash }));
1203
1205
  return;
1204
1206
  }
1205
1207
 
@@ -1238,15 +1240,15 @@ globalThis.git_commit_detail_open_file = async function(): Promise<void> {
1238
1240
  applyFileViewHighlighting(bufferId, content, file);
1239
1241
 
1240
1242
  const targetLine = line || 1;
1241
- editor.setStatus(`${file} @ ${commit.shortHash} (read-only) | Target: line ${targetLine} | q: back`);
1243
+ editor.setStatus(editor.t("status.file_view_ready", { file, hash: commit.shortHash, line: String(targetLine) }));
1242
1244
  } else {
1243
- editor.setStatus(`Failed to open ${file}`);
1245
+ editor.setStatus(editor.t("status.failed_open_file", { file }));
1244
1246
  }
1245
1247
  } else {
1246
- editor.setStatus("Move cursor to a diff line with file context");
1248
+ editor.setStatus(editor.t("status.move_to_diff_with_context"));
1247
1249
  }
1248
1250
  } else {
1249
- editor.setStatus("Move cursor to a diff line");
1251
+ editor.setStatus(editor.t("status.move_to_diff"));
1250
1252
  }
1251
1253
  };
1252
1254
 
@@ -1255,22 +1257,22 @@ globalThis.git_commit_detail_open_file = async function(): Promise<void> {
1255
1257
  // =============================================================================
1256
1258
 
1257
1259
  editor.registerCommand(
1258
- "Git Log",
1259
- "Show git log in magit-style interface",
1260
+ "%cmd.git_log",
1261
+ "%cmd.git_log_desc",
1260
1262
  "show_git_log",
1261
1263
  "normal"
1262
1264
  );
1263
1265
 
1264
1266
  editor.registerCommand(
1265
- "Git Log: Close",
1266
- "Close the git log panel",
1267
+ "%cmd.git_log_close",
1268
+ "%cmd.git_log_close_desc",
1267
1269
  "git_log_close",
1268
1270
  "normal"
1269
1271
  );
1270
1272
 
1271
1273
  editor.registerCommand(
1272
- "Git Log: Refresh",
1273
- "Refresh the git log",
1274
+ "%cmd.git_log_refresh",
1275
+ "%cmd.git_log_refresh_desc",
1274
1276
  "git_log_refresh",
1275
1277
  "normal"
1276
1278
  );
@@ -1279,5 +1281,5 @@ editor.registerCommand(
1279
1281
  // Plugin Initialization
1280
1282
  // =============================================================================
1281
1283
 
1282
- editor.setStatus("Git Log plugin loaded (magit-style)");
1284
+ editor.setStatus(editor.t("status.ready", { count: "0" }));
1283
1285
  editor.debug("Git Log plugin initialized - Use 'Git Log' command to open");
package/plugins/go-lsp.ts CHANGED
@@ -1,4 +1,6 @@
1
1
  /// <reference path="./lib/fresh.d.ts" />
2
+ const editor = getEditor();
3
+
2
4
 
3
5
  /**
4
6
  * Go LSP Helper Plugin
@@ -1,4 +1,6 @@
1
1
  /// <reference path="./lib/fresh.d.ts" />
2
+ const editor = getEditor();
3
+
2
4
 
3
5
  /**
4
6
  * HTML LSP Helper Plugin
@@ -1,4 +1,6 @@
1
1
  /// <reference path="./lib/fresh.d.ts" />
2
+ const editor = getEditor();
3
+
2
4
 
3
5
  /**
4
6
  * JSON LSP Helper Plugin
@@ -254,6 +254,8 @@ interface CreateVirtualBufferOptions {
254
254
  show_cursors?: boolean | null;
255
255
  /** Disable all editing commands (default: false) */
256
256
  editing_disabled?: boolean | null;
257
+ /** Enable/disable line wrapping (None = use global setting) */
258
+ line_wrap?: boolean | null;
257
259
  }
258
260
 
259
261
  /** Options for creating a virtual buffer in an existing split */
@@ -274,6 +276,8 @@ interface CreateVirtualBufferInExistingSplitOptions {
274
276
  show_cursors?: boolean | null;
275
277
  /** Whether editing is disabled for this buffer (default false) */
276
278
  editing_disabled?: boolean | null;
279
+ /** Enable/disable line wrapping (None = use global setting) */
280
+ line_wrap?: boolean | null;
277
281
  }
278
282
 
279
283
  /** Options for creating a virtual buffer in the current split as a new tab */
@@ -328,9 +332,9 @@ interface EditorAPI {
328
332
  */
329
333
  setStatus(message: string): void;
330
334
  /**
331
- * Log a debug message to the editor's trace output
335
+ * Log a debug message from a plugin
332
336
  *
333
- * Messages appear in stderr when running with RUST_LOG=debug.
337
+ * Messages appear in log file when running with RUST_LOG=debug.
334
338
  * Useful for plugin development and troubleshooting.
335
339
  * @param message - Debug message; include context like function name and relevant values
336
340
  */
@@ -394,6 +398,8 @@ interface EditorAPI {
394
398
  * @param buffer_id - Target buffer ID
395
399
  */
396
400
  isBufferModified(buffer_id: number): boolean;
401
+ /** Get the currently active locale */
402
+ getCurrentLocale(): string;
397
403
  /**
398
404
  * Get the ID of the focused split pane
399
405
  *
@@ -508,6 +514,30 @@ interface EditorAPI {
508
514
  * stay in sync with the saved config.
509
515
  */
510
516
  reloadConfig(): void;
517
+ /**
518
+ * Log an error message from a plugin
519
+ *
520
+ * Messages appear in log file when running with RUST_LOG=error.
521
+ * Use for critical errors that need attention.
522
+ * @param message - Error message
523
+ */
524
+ error(message: string): void;
525
+ /**
526
+ * Log a warning message from a plugin
527
+ *
528
+ * Messages appear in log file when running with RUST_LOG=warn.
529
+ * Use for warnings that don't prevent operation but indicate issues.
530
+ * @param message - Warning message
531
+ */
532
+ warn(message: string): void;
533
+ /**
534
+ * Log an info message from a plugin
535
+ *
536
+ * Messages appear in log file when running with RUST_LOG=info.
537
+ * Use for important operational messages.
538
+ * @param message - Info message
539
+ */
540
+ info(message: string): void;
511
541
  /**
512
542
  * Copy text to the system clipboard
513
543
  *
@@ -612,16 +642,9 @@ interface EditorAPI {
612
642
  * @returns true if insertion succeeded
613
643
  */
614
644
  insertAtCursor(text: string): boolean;
615
- /**
616
- * Register a custom command that can be triggered by keybindings or the command palette
617
- * @param name - Unique command name (e.g., "my_plugin_action")
618
- * @param description - Human-readable description
619
- * @param action - JavaScript function name to call when command is triggered
620
- * @param contexts - Comma-separated list of contexts, including both built-in (normal, prompt, popup,
621
- * fileexplorer, menu) and custom plugin-defined contexts (e.g., "normal,config-editor")
622
- * @param source - Plugin source name (empty string for builtin)
623
- * @returns true if command was registered
624
- */
645
+ /** Translate a string for a plugin using the current locale */
646
+ pluginTranslate(plugin_name: string, key: string, args: Record<string, unknown>): string;
647
+ /** Register a custom command that can be triggered by keybindings or the command palette */
625
648
  registerCommand(name: string, description: string, action: string, contexts: string, source: string): boolean;
626
649
  /**
627
650
  * Unregister a custom command by name
@@ -793,6 +816,22 @@ interface EditorAPI {
793
816
  * @param language - The language to disable LSP for (e.g., "python", "rust")
794
817
  */
795
818
  disableLspForLanguage(language: string): boolean;
819
+ /**
820
+ * Create a scroll sync group for anchor-based synchronized scrolling
821
+ *
822
+ * Used for side-by-side diff views where two panes need to scroll together.
823
+ * The plugin provides the group ID (must be unique per plugin).
824
+ */
825
+ createScrollSyncGroup(group_id: number, left_split: number, right_split: number): boolean;
826
+ /**
827
+ * Set sync anchors for a scroll sync group
828
+ *
829
+ * Anchors map corresponding line numbers between left and right buffers.
830
+ * Each anchor is a tuple of (left_line, right_line).
831
+ */
832
+ setScrollSyncAnchors(group_id: number, anchors: Vec<(usize, usize): boolean;
833
+ /** Remove a scroll sync group */
834
+ removeScrollSyncGroup(group_id: number): boolean;
796
835
 
797
836
  /**
798
837
  * Spawn an external process and return a cancellable handle
@@ -830,9 +869,10 @@ interface EditorAPI {
830
869
  * @param underline - Add underline decoration
831
870
  * @param bold - Use bold text
832
871
  * @param italic - Use italic text
872
+ * @param extend_to_line_end - Extend background to end of visual line
833
873
  * @returns true if overlay was added
834
874
  */
835
- addOverlay(buffer_id: number, namespace: string, start: number, end: number, r: number, g: number, b: number, bg_r: i16, bg_g: i16, bg_b: i16, underline: boolean, bold: boolean, italic: boolean): boolean;
875
+ addOverlay(buffer_id: number, namespace: string, start: number, end: number, r: number, g: number, b: number, bg_r: i16, bg_g: i16, bg_b: i16, underline: boolean, bold: boolean, italic: boolean, extend_to_line_end: boolean): boolean;
836
876
  /**
837
877
  * Remove a specific overlay by its handle
838
878
  * @param buffer_id - The buffer ID
@@ -20,5 +20,5 @@ export { PanelManager } from "./panel-manager.ts";
20
20
  export { NavigationController } from "./navigation-controller.ts";
21
21
 
22
22
  // Buffer Creation
23
- export { VirtualBufferFactory } from "./virtual-buffer-factory.ts";
23
+ export { createVirtualBufferFactory } from "./virtual-buffer-factory.ts";
24
24
  export type { VirtualBufferOptions, SplitBufferOptions } from "./virtual-buffer-factory.ts";