@fresh-editor/fresh-editor 0.3.6 → 0.3.8

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.
@@ -0,0 +1,72 @@
1
+ {
2
+ "cs": {
3
+ "status.detecting_branch": "Detekuji větev ...",
4
+ "status.not_in_git": "Není v git",
5
+ "status.git_branch": "Git: větev"
6
+ },
7
+ "de": {
8
+ "status.detecting_branch": "Branch erkennen ...",
9
+ "status.not_in_git": "Nicht in git",
10
+ "status.git_branch": "Git: Branch"
11
+ },
12
+ "en": {
13
+ "status.detecting_branch": "Detecting branch ...",
14
+ "status.not_in_git": "Not in git",
15
+ "status.git_branch": "Git: branch"
16
+ },
17
+ "es": {
18
+ "status.detecting_branch": "Detectando rama ...",
19
+ "status.not_in_git": "No está en git",
20
+ "status.git_branch": "Git: rama"
21
+ },
22
+ "fr": {
23
+ "status.detecting_branch": "Détection de la branche ...",
24
+ "status.not_in_git": "Pas dans git",
25
+ "status.git_branch": "Git : branche"
26
+ },
27
+ "it": {
28
+ "status.detecting_branch": "Rilevamento branch ...",
29
+ "status.not_in_git": "Non in git",
30
+ "status.git_branch": "Git: branch"
31
+ },
32
+ "ja": {
33
+ "status.detecting_branch": "ブランチを検出中...",
34
+ "status.not_in_git": "git外",
35
+ "status.git_branch": "Git: ブランチ"
36
+ },
37
+ "ko": {
38
+ "status.detecting_branch": "브랜치 감지 중...",
39
+ "status.not_in_git": "git 아님",
40
+ "status.git_branch": "Git: 브랜치"
41
+ },
42
+ "pt-BR": {
43
+ "status.detecting_branch": "Detectando ramo ...",
44
+ "status.not_in_git": "Não está em git",
45
+ "status.git_branch": "Git: ramo"
46
+ },
47
+ "ru": {
48
+ "status.detecting_branch": "Определение ветки ...",
49
+ "status.not_in_git": "Не в git",
50
+ "status.git_branch": "Git: ветка"
51
+ },
52
+ "th": {
53
+ "status.detecting_branch": "กำลังตรวจจับสาขา ...",
54
+ "status.not_in_git": "ไม่ได้อยู่ใน git",
55
+ "status.git_branch": "Git: สาขา"
56
+ },
57
+ "uk": {
58
+ "status.detecting_branch": "Визначення гілки ...",
59
+ "status.not_in_git": "Не в git",
60
+ "status.git_branch": "Git: гілка"
61
+ },
62
+ "vi": {
63
+ "status.detecting_branch": "Đang phát hiện nhánh ...",
64
+ "status.not_in_git": "Không trong git",
65
+ "status.git_branch": "Git: nhánh"
66
+ },
67
+ "zh-CN": {
68
+ "status.detecting_branch": "正在检测分支...",
69
+ "status.not_in_git": "不在 git 中",
70
+ "status.git_branch": "Git: 分支"
71
+ }
72
+ }
@@ -0,0 +1,133 @@
1
+ /// <reference path="./lib/fresh.d.ts" />
2
+
3
+ const editor = getEditor();
4
+
5
+ const GIT_BRANCH = "branch";
6
+
7
+ let lastDetectedBranch = editor.t("status.detecting_branch");
8
+ let inFlight: Promise<string> | null = null;
9
+
10
+ // HEAD-file watcher. Branch changes correspond exactly to mutations of
11
+ // the `HEAD` file inside the relevant git dir (resolved by
12
+ // `git rev-parse --git-path HEAD` so worktrees / submodules / `--git-dir`
13
+ // setups work). When HEAD changes we re-spawn `git rev-parse --abbrev-ref`
14
+ // and push the new value; otherwise we never spawn git on the hot path.
15
+ let headWatchHandle: number | null = null;
16
+ let watchedCwd: string | null = null;
17
+ let watchedHeadPath: string | null = null;
18
+ let ensureWatchInFlight: Promise<void> | null = null;
19
+
20
+ async function discoverHeadPath(cwd: string): Promise<string | null> {
21
+ const result = await editor.spawnProcess(
22
+ "git",
23
+ ["rev-parse", "--git-path", "HEAD"],
24
+ cwd,
25
+ );
26
+ if (result.exit_code !== 0) return null;
27
+ const headPath = result.stdout.trim();
28
+ if (!headPath) return null;
29
+ // `--git-path` returns a path relative to cwd unless the git dir is
30
+ // outside (e.g. worktree). Make absolute so notify gets a stable target.
31
+ return headPath.startsWith("/") ? headPath : `${cwd}/${headPath}`;
32
+ }
33
+
34
+ async function ensureHeadWatch(): Promise<void> {
35
+ const cwd = editor.getCwd();
36
+ if (watchedCwd === cwd && headWatchHandle !== null) return;
37
+ if (ensureWatchInFlight) return ensureWatchInFlight;
38
+
39
+ ensureWatchInFlight = (async () => {
40
+ try {
41
+ if (headWatchHandle !== null) {
42
+ editor.unwatchPath(headWatchHandle);
43
+ headWatchHandle = null;
44
+ watchedHeadPath = null;
45
+ }
46
+ watchedCwd = cwd;
47
+ const headPath = await discoverHeadPath(cwd);
48
+ if (!headPath) return;
49
+ try {
50
+ headWatchHandle = await editor.watchPath(headPath, false);
51
+ watchedHeadPath = headPath;
52
+ } catch (_e) {
53
+ // Watch registration failed (path missing, kernel limit). Fall
54
+ // back to event-driven refresh — getCurrentGitBranch is still
55
+ // gated by inFlight + the per-event invocation pattern below.
56
+ }
57
+ } finally {
58
+ ensureWatchInFlight = null;
59
+ }
60
+ })();
61
+ return ensureWatchInFlight;
62
+ }
63
+
64
+ async function getCurrentGitBranch(): Promise<string> {
65
+ if (inFlight) return inFlight;
66
+ inFlight = (async () => {
67
+ try {
68
+ const cwd = editor.getCwd();
69
+ const result = await editor.spawnProcess(
70
+ "git",
71
+ ["rev-parse", "--abbrev-ref", "HEAD"],
72
+ cwd,
73
+ );
74
+ if (result.exit_code === 0) {
75
+ const branch = result.stdout.trim();
76
+ lastDetectedBranch = branch || "HEAD";
77
+ } else {
78
+ lastDetectedBranch = editor.t("status.not_in_git");
79
+ }
80
+ return lastDetectedBranch;
81
+ } finally {
82
+ inFlight = null;
83
+ }
84
+ })();
85
+ return inFlight;
86
+ }
87
+
88
+ async function refreshForActiveBuffer(): Promise<void> {
89
+ // Lazy: pick up cwd changes (Orchestrator window switch, etc.) the next
90
+ // time anything triggers us.
91
+ ensureHeadWatch();
92
+ const bufferId = editor.getActiveBufferId();
93
+ if (bufferId === 0) return;
94
+ const branch = await getCurrentGitBranch();
95
+ editor.setStatusBarValue(bufferId, GIT_BRANCH, branch);
96
+ }
97
+
98
+ editor.registerStatusBarElement(GIT_BRANCH, editor.t("status.git_branch"));
99
+
100
+ // Refresh the branch label when:
101
+ // - The user switches to a different buffer (the per-buffer value may not
102
+ // be set yet for that buffer).
103
+ // - A file is freshly opened (same reason).
104
+ // - A file is saved (best-effort UX: the user may have committed via an
105
+ // external terminal between events; the watchPath below catches actual
106
+ // HEAD mutations).
107
+ // - The editor regains focus from another window — covers the case of
108
+ // running `git checkout` in an external terminal while fresh was unfocused.
109
+ //
110
+ // Notably *not* in this list (compared to the legacy version): render_start,
111
+ // cursor_moved, after_insert, after_delete, buffer_deactivated, buffer_closed.
112
+ // None of them can change the current branch, and render_start was being
113
+ // fired ~300/s — see #2009 for the feedback-loop investigation.
114
+ [
115
+ "buffer_activated",
116
+ "after_file_open",
117
+ "after_file_save",
118
+ "focus_gained",
119
+ ].forEach((event) => {
120
+ editor.on(event, async () => {
121
+ await refreshForActiveBuffer();
122
+ });
123
+ });
124
+
125
+ // path_changed → HEAD file mutated → branch may have changed.
126
+ editor.on("path_changed", async (args) => {
127
+ if (args.handle !== headWatchHandle) return;
128
+ await refreshForActiveBuffer();
129
+ });
130
+
131
+ // Kick off the first detection at load time so the status bar populates
132
+ // before any user event fires.
133
+ refreshForActiveBuffer();