@jx0/jmux 0.3.4 → 0.3.6
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/package.json +1 -1
- package/src/main.ts +45 -9
- package/src/renderer.ts +2 -1
- package/src/sidebar.ts +28 -5
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.6";
|
|
16
16
|
|
|
17
17
|
const HELP = `jmux — a persistent session sidebar for tmux
|
|
18
18
|
|
|
@@ -145,6 +145,7 @@ process.stdout.write("\x1b[?1049h");
|
|
|
145
145
|
process.stdout.write("\x1b[?1000h"); // mouse button tracking
|
|
146
146
|
process.stdout.write("\x1b[?1002h"); // mouse drag tracking
|
|
147
147
|
process.stdout.write("\x1b[?1006h"); // SGR extended mouse mode
|
|
148
|
+
process.stdout.write("\x1b[?2004h"); // bracketed paste mode
|
|
148
149
|
if (process.stdin.setRawMode) {
|
|
149
150
|
process.stdin.setRawMode(true);
|
|
150
151
|
}
|
|
@@ -313,17 +314,51 @@ const inputRouter = new InputRouter(
|
|
|
313
314
|
|
|
314
315
|
let writesPending = 0;
|
|
315
316
|
|
|
316
|
-
// OSC 52 clipboard
|
|
317
|
-
const
|
|
317
|
+
// OSC 52 clipboard passthrough — buffers across split chunks
|
|
318
|
+
const OSC52_START = "\x1b]52;";
|
|
319
|
+
let osc52Pending = "";
|
|
320
|
+
|
|
321
|
+
function forwardOsc52(data: string): void {
|
|
322
|
+
let search = osc52Pending ? osc52Pending + data : data;
|
|
323
|
+
osc52Pending = "";
|
|
324
|
+
|
|
325
|
+
let pos = 0;
|
|
326
|
+
while (pos < search.length) {
|
|
327
|
+
const start = search.indexOf(OSC52_START, pos);
|
|
328
|
+
if (start < 0) break;
|
|
329
|
+
|
|
330
|
+
// Find terminator: BEL (\x07) or ST (\x1b\\)
|
|
331
|
+
let end = -1;
|
|
332
|
+
let endLen = 0;
|
|
333
|
+
for (let i = start + OSC52_START.length; i < search.length; i++) {
|
|
334
|
+
if (search[i] === "\x07") {
|
|
335
|
+
end = i;
|
|
336
|
+
endLen = 1;
|
|
337
|
+
break;
|
|
338
|
+
}
|
|
339
|
+
if (search[i] === "\x1b" && i + 1 < search.length && search[i + 1] === "\\") {
|
|
340
|
+
end = i;
|
|
341
|
+
endLen = 2;
|
|
342
|
+
break;
|
|
343
|
+
}
|
|
344
|
+
}
|
|
318
345
|
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
346
|
+
if (end >= 0) {
|
|
347
|
+
process.stdout.write(search.slice(start, end + endLen));
|
|
348
|
+
pos = end + endLen;
|
|
349
|
+
} else {
|
|
350
|
+
// Incomplete — buffer for next chunk (cap at 512KB to avoid leaks)
|
|
351
|
+
const remainder = search.slice(start);
|
|
352
|
+
if (remainder.length < 512 * 1024) {
|
|
353
|
+
osc52Pending = remainder;
|
|
354
|
+
}
|
|
355
|
+
return;
|
|
325
356
|
}
|
|
326
357
|
}
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
pty.onData((data: string) => {
|
|
361
|
+
forwardOsc52(data);
|
|
327
362
|
|
|
328
363
|
writesPending++;
|
|
329
364
|
bridge.write(data).then(() => {
|
|
@@ -466,6 +501,7 @@ async function start(): Promise<void> {
|
|
|
466
501
|
|
|
467
502
|
function cleanup(): void {
|
|
468
503
|
control.close().catch(() => {});
|
|
504
|
+
process.stdout.write("\x1b[?2004l"); // disable bracketed paste mode
|
|
469
505
|
process.stdout.write("\x1b[?1000l"); // disable mouse button tracking
|
|
470
506
|
process.stdout.write("\x1b[?1002l"); // disable mouse drag tracking
|
|
471
507
|
process.stdout.write("\x1b[?1006l"); // disable SGR mouse mode
|
package/src/renderer.ts
CHANGED
package/src/sidebar.ts
CHANGED
|
@@ -9,10 +9,14 @@ const ACCENT_ATTRS: CellAttrs = {
|
|
|
9
9
|
fg: 2,
|
|
10
10
|
fgMode: ColorMode.Palette,
|
|
11
11
|
};
|
|
12
|
+
// #1e2a35 as packed RGB for subtle active row background
|
|
13
|
+
const ACTIVE_BG = (0x1e << 16) | (0x2a << 8) | 0x35;
|
|
12
14
|
const ACTIVE_MARKER_ATTRS: CellAttrs = {
|
|
13
15
|
fg: 2,
|
|
14
16
|
fgMode: ColorMode.Palette,
|
|
15
17
|
bold: true,
|
|
18
|
+
bg: ACTIVE_BG,
|
|
19
|
+
bgMode: ColorMode.RGB,
|
|
16
20
|
};
|
|
17
21
|
const ACTIVITY_ATTRS: CellAttrs = {
|
|
18
22
|
fg: 2,
|
|
@@ -24,9 +28,16 @@ const ATTENTION_ATTRS: CellAttrs = {
|
|
|
24
28
|
bold: true,
|
|
25
29
|
};
|
|
26
30
|
const ACTIVE_NAME_ATTRS: CellAttrs = {
|
|
27
|
-
fg:
|
|
31
|
+
fg: 2,
|
|
28
32
|
fgMode: ColorMode.Palette,
|
|
29
33
|
bold: true,
|
|
34
|
+
bg: ACTIVE_BG,
|
|
35
|
+
bgMode: ColorMode.RGB,
|
|
36
|
+
};
|
|
37
|
+
const ACTIVE_DETAIL_ATTRS: CellAttrs = {
|
|
38
|
+
dim: true,
|
|
39
|
+
bg: ACTIVE_BG,
|
|
40
|
+
bgMode: ColorMode.RGB,
|
|
30
41
|
};
|
|
31
42
|
const INACTIVE_NAME_ATTRS: CellAttrs = {
|
|
32
43
|
fg: 7,
|
|
@@ -314,6 +325,14 @@ export class Sidebar {
|
|
|
314
325
|
this.rowToSessionIndex.set(detailRow, sessionIdx);
|
|
315
326
|
}
|
|
316
327
|
|
|
328
|
+
// Paint active background across both rows
|
|
329
|
+
if (isActive) {
|
|
330
|
+
const bgFill = " ".repeat(this.width);
|
|
331
|
+
const bgAttrs: CellAttrs = { bg: ACTIVE_BG, bgMode: ColorMode.RGB };
|
|
332
|
+
writeString(grid, nameRow, 0, bgFill, bgAttrs);
|
|
333
|
+
writeString(grid, detailRow, 0, bgFill, bgAttrs);
|
|
334
|
+
}
|
|
335
|
+
|
|
317
336
|
// Active marker
|
|
318
337
|
if (isActive) {
|
|
319
338
|
writeString(grid, nameRow, 0, "\u258e", ACTIVE_MARKER_ATTRS);
|
|
@@ -342,11 +361,15 @@ export class Sidebar {
|
|
|
342
361
|
: { ...INACTIVE_NAME_ATTRS };
|
|
343
362
|
writeString(grid, nameRow, nameStart, displayName, nameAttrs);
|
|
344
363
|
|
|
364
|
+
const wcAttrs: CellAttrs = isActive
|
|
365
|
+
? { ...DIM_ATTRS, bg: ACTIVE_BG, bgMode: ColorMode.RGB }
|
|
366
|
+
: DIM_ATTRS;
|
|
345
367
|
if (windowCountCol > nameStart) {
|
|
346
|
-
writeString(grid, nameRow, windowCountCol, windowCountStr,
|
|
368
|
+
writeString(grid, nameRow, windowCountCol, windowCountStr, wcAttrs);
|
|
347
369
|
}
|
|
348
370
|
|
|
349
371
|
// Detail line
|
|
372
|
+
const detailAttrs: CellAttrs = isActive ? ACTIVE_DETAIL_ATTRS : DIM_ATTRS;
|
|
350
373
|
if (item.grouped) {
|
|
351
374
|
if (session.gitBranch) {
|
|
352
375
|
const detailStart = 3;
|
|
@@ -355,7 +378,7 @@ export class Sidebar {
|
|
|
355
378
|
if (branch.length > maxLen) {
|
|
356
379
|
branch = branch.slice(0, maxLen - 1) + "\u2026";
|
|
357
380
|
}
|
|
358
|
-
writeString(grid, detailRow, detailStart, branch,
|
|
381
|
+
writeString(grid, detailRow, detailStart, branch, detailAttrs);
|
|
359
382
|
}
|
|
360
383
|
} else {
|
|
361
384
|
const detailStart = 3;
|
|
@@ -363,7 +386,7 @@ export class Sidebar {
|
|
|
363
386
|
if (session.gitBranch) {
|
|
364
387
|
const branchCol = this.width - session.gitBranch.length - 1;
|
|
365
388
|
if (branchCol > detailStart + 1) {
|
|
366
|
-
writeString(grid, detailRow, branchCol, session.gitBranch,
|
|
389
|
+
writeString(grid, detailRow, branchCol, session.gitBranch, detailAttrs);
|
|
367
390
|
branchCols = session.gitBranch.length + 2;
|
|
368
391
|
}
|
|
369
392
|
}
|
|
@@ -373,7 +396,7 @@ export class Sidebar {
|
|
|
373
396
|
if (displayDir.length > dirMaxLen) {
|
|
374
397
|
displayDir = displayDir.slice(0, dirMaxLen - 1) + "\u2026";
|
|
375
398
|
}
|
|
376
|
-
writeString(grid, detailRow, detailStart, displayDir,
|
|
399
|
+
writeString(grid, detailRow, detailStart, displayDir, detailAttrs);
|
|
377
400
|
}
|
|
378
401
|
}
|
|
379
402
|
}
|