@jx0/jmux 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.
- package/config/core.conf +5 -0
- package/config/defaults.conf +3 -2
- package/package.json +1 -1
- package/src/main.ts +39 -13
- package/src/sidebar.ts +9 -0
package/config/core.conf
CHANGED
|
@@ -12,6 +12,11 @@ set -g mouse on
|
|
|
12
12
|
unbind n
|
|
13
13
|
bind-key n display-popup -E -w 60% -h 70% -b heavy -S 'fg=#4f565d' "$JMUX_DIR/config/new-session.sh"
|
|
14
14
|
|
|
15
|
+
# Window naming — ignore application-set titles, show useful names
|
|
16
|
+
set -g allow-rename off
|
|
17
|
+
set -g automatic-rename on
|
|
18
|
+
set -g automatic-rename-format "#{b:pane_current_path}"
|
|
19
|
+
|
|
15
20
|
# Status bar — session info is in the sidebar, keep status bar for windows only
|
|
16
21
|
set -g status-left ""
|
|
17
22
|
set -g status-left-length 0
|
package/config/defaults.conf
CHANGED
|
@@ -13,7 +13,8 @@ set -g base-index 1
|
|
|
13
13
|
set -g pane-base-index 1
|
|
14
14
|
set -g renumber-windows on
|
|
15
15
|
set -g automatic-rename on
|
|
16
|
-
set -g
|
|
16
|
+
set -g allow-rename off
|
|
17
|
+
set -g automatic-rename-format "#{b:pane_current_path}"
|
|
17
18
|
bind c new-window -c ~
|
|
18
19
|
bind -n C-Right next-window
|
|
19
20
|
bind -n C-Left previous-window
|
|
@@ -44,7 +45,7 @@ set -g pane-border-lines heavy
|
|
|
44
45
|
set -g pane-border-status off
|
|
45
46
|
set -g pane-border-style 'fg=#3a4450'
|
|
46
47
|
set -g pane-active-border-style 'fg=#4f565d'
|
|
47
|
-
set -g pane-border-format "#{?pane_active, #[fg=#9fe8c3 bold]#{pane_title}
|
|
48
|
+
set -g pane-border-format "#{?pane_active, #[fg=#9fe8c3 bold]#{?#{m:*Claude*,#{pane_title}},claude,#{pane_current_command}} , #[fg=#4f565d]#{?#{m:*Claude*,#{pane_title}},claude,#{pane_current_command}} }"
|
|
48
49
|
|
|
49
50
|
# Auto-show pane borders only when window has multiple panes
|
|
50
51
|
set-hook -g window-layout-changed 'if -F "#{==:#{window_panes},1}" "set -w pane-border-status off" "set -w pane-border-status top"'
|
package/package.json
CHANGED
package/src/main.ts
CHANGED
|
@@ -12,7 +12,7 @@ import { homedir } from "os";
|
|
|
12
12
|
|
|
13
13
|
// --- CLI commands (run and exit before TUI) ---
|
|
14
14
|
|
|
15
|
-
const VERSION = "0.3.
|
|
15
|
+
const VERSION = "0.3.8";
|
|
16
16
|
|
|
17
17
|
const HELP = `jmux — a persistent session sidebar for tmux
|
|
18
18
|
|
|
@@ -252,21 +252,10 @@ async function switchSession(sessionId: string): Promise<void> {
|
|
|
252
252
|
await control.sendCommand(
|
|
253
253
|
`switch-client -c ${ptyClientName} -t '${sessionId}'`,
|
|
254
254
|
);
|
|
255
|
-
lastViewedTimestamps.set(sessionId, Math.floor(Date.now() / 1000));
|
|
256
|
-
sidebar.setActivity(sessionId, false);
|
|
257
255
|
currentSessionId = sessionId;
|
|
258
256
|
sidebar.setActiveSession(sessionId);
|
|
259
257
|
sidebar.scrollToActive();
|
|
260
258
|
renderFrame();
|
|
261
|
-
|
|
262
|
-
// Clear attention flag if set
|
|
263
|
-
try {
|
|
264
|
-
await control.sendCommand(
|
|
265
|
-
`set-option -t '${sessionId}' -u @jmux-attention`,
|
|
266
|
-
);
|
|
267
|
-
} catch {
|
|
268
|
-
// Option may not be set
|
|
269
|
-
}
|
|
270
259
|
} catch {
|
|
271
260
|
// Session may have been killed
|
|
272
261
|
}
|
|
@@ -290,12 +279,35 @@ function scheduleRender(): void {
|
|
|
290
279
|
}, 16); // ~60fps cap
|
|
291
280
|
}
|
|
292
281
|
|
|
282
|
+
// --- Indicator clearing on interaction ---
|
|
283
|
+
|
|
284
|
+
function clearSessionIndicators(): void {
|
|
285
|
+
if (!currentSessionId) return;
|
|
286
|
+
const id = currentSessionId;
|
|
287
|
+
|
|
288
|
+
// Only clear if there's something to clear
|
|
289
|
+
const needsActivityClear = sidebar.hasActivity(id);
|
|
290
|
+
const needsAttentionClear = sidebar.hasAttention(id);
|
|
291
|
+
if (!needsActivityClear && !needsAttentionClear) return;
|
|
292
|
+
|
|
293
|
+
lastViewedTimestamps.set(id, Math.floor(Date.now() / 1000));
|
|
294
|
+
sidebar.setActivity(id, false);
|
|
295
|
+
scheduleRender();
|
|
296
|
+
|
|
297
|
+
if (needsAttentionClear) {
|
|
298
|
+
control.sendCommand(`set-option -t '${id}' -u @jmux-attention`).catch(() => {});
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
|
|
293
302
|
// --- Input Router ---
|
|
294
303
|
|
|
295
304
|
const inputRouter = new InputRouter(
|
|
296
305
|
{
|
|
297
306
|
sidebarCols: SIDEBAR_WIDTH,
|
|
298
|
-
onPtyData: (data) =>
|
|
307
|
+
onPtyData: (data) => {
|
|
308
|
+
pty.write(data);
|
|
309
|
+
clearSessionIndicators();
|
|
310
|
+
},
|
|
299
311
|
onSidebarClick: (row) => {
|
|
300
312
|
const session = sidebar.getSessionByRow(row);
|
|
301
313
|
if (session) switchSession(session.id);
|
|
@@ -483,6 +495,20 @@ async function start(): Promise<void> {
|
|
|
483
495
|
// Set JMUX_DIR in tmux's global environment so config bindings can reference it
|
|
484
496
|
await control.sendCommand(`set-environment -g JMUX_DIR ${jmuxDir}`);
|
|
485
497
|
await control.sendCommand(`source-file ${configFile}`);
|
|
498
|
+
// Re-enable automatic-rename on all windows — clears any application-set names
|
|
499
|
+
try {
|
|
500
|
+
const windowLines = await control.sendCommand(
|
|
501
|
+
"list-windows -a -F '#{window_id}'"
|
|
502
|
+
);
|
|
503
|
+
for (const line of windowLines) {
|
|
504
|
+
const winId = line.trim();
|
|
505
|
+
if (winId) {
|
|
506
|
+
await control.sendCommand(`set-option -w -t ${winId} automatic-rename on`);
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
} catch {
|
|
510
|
+
// Non-critical — windows will rename on next command change
|
|
511
|
+
}
|
|
486
512
|
|
|
487
513
|
// Fetch initial sessions, then resolve client name (needs sessions list)
|
|
488
514
|
await fetchSessions();
|
package/src/sidebar.ts
CHANGED
|
@@ -198,6 +198,15 @@ export class Sidebar {
|
|
|
198
198
|
}
|
|
199
199
|
}
|
|
200
200
|
|
|
201
|
+
hasActivity(sessionId: string): boolean {
|
|
202
|
+
return this.activitySet.has(sessionId);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
hasAttention(sessionId: string): boolean {
|
|
206
|
+
const session = this.sessions.find((s) => s.id === sessionId);
|
|
207
|
+
return session?.attention === true;
|
|
208
|
+
}
|
|
209
|
+
|
|
201
210
|
getDisplayOrderIds(): string[] {
|
|
202
211
|
return this.displayOrder
|
|
203
212
|
.map((idx) => this.sessions[idx]?.id)
|