@jx0/jmux 0.3.4 → 0.3.5

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jx0/jmux",
3
- "version": "0.3.4",
3
+ "version": "0.3.5",
4
4
  "description": "The terminal workspace for agentic development",
5
5
  "type": "module",
6
6
  "bin": {
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.4";
15
+ const VERSION = "0.3.5";
16
16
 
17
17
  const HELP = `jmux — a persistent session sidebar for tmux
18
18
 
@@ -313,17 +313,51 @@ const inputRouter = new InputRouter(
313
313
 
314
314
  let writesPending = 0;
315
315
 
316
- // OSC 52 clipboard: \x1b]52;...;...\x07 or \x1b]52;...;...\x1b\\
317
- const OSC52_RE = /\x1b\]52;[^;]*;[^\x07\x1b]*(?:\x07|\x1b\\)/g;
316
+ // OSC 52 clipboard passthrough buffers across split chunks
317
+ const OSC52_START = "\x1b]52;";
318
+ let osc52Pending = "";
319
+
320
+ function forwardOsc52(data: string): void {
321
+ let search = osc52Pending ? osc52Pending + data : data;
322
+ osc52Pending = "";
323
+
324
+ let pos = 0;
325
+ while (pos < search.length) {
326
+ const start = search.indexOf(OSC52_START, pos);
327
+ if (start < 0) break;
328
+
329
+ // Find terminator: BEL (\x07) or ST (\x1b\\)
330
+ let end = -1;
331
+ let endLen = 0;
332
+ for (let i = start + OSC52_START.length; i < search.length; i++) {
333
+ if (search[i] === "\x07") {
334
+ end = i;
335
+ endLen = 1;
336
+ break;
337
+ }
338
+ if (search[i] === "\x1b" && i + 1 < search.length && search[i + 1] === "\\") {
339
+ end = i;
340
+ endLen = 2;
341
+ break;
342
+ }
343
+ }
318
344
 
319
- pty.onData((data: string) => {
320
- // Pass OSC 52 clipboard sequences directly to the outer terminal
321
- const osc52Matches = data.match(OSC52_RE);
322
- if (osc52Matches) {
323
- for (const seq of osc52Matches) {
324
- process.stdout.write(seq);
345
+ if (end >= 0) {
346
+ process.stdout.write(search.slice(start, end + endLen));
347
+ pos = end + endLen;
348
+ } else {
349
+ // Incomplete — buffer for next chunk (cap at 512KB to avoid leaks)
350
+ const remainder = search.slice(start);
351
+ if (remainder.length < 512 * 1024) {
352
+ osc52Pending = remainder;
353
+ }
354
+ return;
325
355
  }
326
356
  }
357
+ }
358
+
359
+ pty.onData((data: string) => {
360
+ forwardOsc52(data);
327
361
 
328
362
  writesPending++;
329
363
  bridge.write(data).then(() => {
package/src/renderer.ts CHANGED
@@ -67,7 +67,8 @@ export function compositeGrids(
67
67
  grid.cells[y][borderCol] = {
68
68
  ...DEFAULT_CELL,
69
69
  char: BORDER_CHAR,
70
- dim: true,
70
+ fg: 8,
71
+ fgMode: ColorMode.Palette,
71
72
  };
72
73
  // Copy main cells
73
74
  for (let x = 0; x < main.cols; x++) {
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: 15,
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, DIM_ATTRS);
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, DIM_ATTRS);
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, DIM_ATTRS);
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, DIM_ATTRS);
399
+ writeString(grid, detailRow, detailStart, displayDir, detailAttrs);
377
400
  }
378
401
  }
379
402
  }