claude-highlight 1.0.0 → 1.0.1
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/README.md +54 -392
- package/dist/claude-highlight-egzaxzbg.js +72 -0
- package/dist/claude-highlight.js +106 -293
- package/dist/pty-bun-2y4wmvve.js +159 -0
- package/dist/pty-node-6j2dj9ta.js +63 -0
- package/dist/pty-read-worker.js +2 -1
- package/dist/pty-write-worker.js +2 -1
- package/image.png +0 -0
- package/man/claude-highlight.1 +6 -3
- package/package.json +17 -12
package/dist/claude-highlight.js
CHANGED
|
@@ -1,78 +1,16 @@
|
|
|
1
|
-
#!/
|
|
2
|
-
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
':' //; exec "$(command -v node || command -v bun)" "$0" "$@"
|
|
3
|
+
import {
|
|
4
|
+
configFile,
|
|
5
|
+
decodeIgnore,
|
|
6
|
+
environ
|
|
7
|
+
} from "./claude-highlight-egzaxzbg.js";
|
|
8
|
+
import { createRequire } from "node:module";
|
|
9
|
+
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
3
10
|
|
|
4
11
|
// src/claude-highlight.ts
|
|
5
|
-
import { existsSync, mkdirSync, openSync, readFileSync, statSync, writeFileSync, writeSync } from "fs";
|
|
6
|
-
import { basename, dirname, resolve } from "path";
|
|
7
|
-
|
|
8
|
-
// src/util.ts
|
|
9
|
-
import { homedir } from "os";
|
|
10
|
-
import { join } from "path";
|
|
11
|
-
function configFile(app) {
|
|
12
|
-
const base = process.env["XDG_CONFIG_HOME"] || join(process.env["HOME"] || homedir(), ".config");
|
|
13
|
-
return join(base, app, "config.json");
|
|
14
|
-
}
|
|
15
|
-
function decodeIgnore(buf) {
|
|
16
|
-
let out = "";
|
|
17
|
-
const n = buf.length;
|
|
18
|
-
let i = 0;
|
|
19
|
-
while (i < n) {
|
|
20
|
-
const b = buf[i] ?? 0;
|
|
21
|
-
if (b < 128) {
|
|
22
|
-
out += String.fromCharCode(b);
|
|
23
|
-
i++;
|
|
24
|
-
continue;
|
|
25
|
-
}
|
|
26
|
-
let len, cp;
|
|
27
|
-
if (b >= 194 && b <= 223) {
|
|
28
|
-
len = 2;
|
|
29
|
-
cp = b & 31;
|
|
30
|
-
} else if (b >= 224 && b <= 239) {
|
|
31
|
-
len = 3;
|
|
32
|
-
cp = b & 15;
|
|
33
|
-
} else if (b >= 240 && b <= 244) {
|
|
34
|
-
len = 4;
|
|
35
|
-
cp = b & 7;
|
|
36
|
-
} else {
|
|
37
|
-
i++;
|
|
38
|
-
continue;
|
|
39
|
-
}
|
|
40
|
-
if (i + len > n)
|
|
41
|
-
break;
|
|
42
|
-
let ok = true;
|
|
43
|
-
for (let k = 1;k < len; k++) {
|
|
44
|
-
const c = buf[i + k] ?? 128;
|
|
45
|
-
if ((c & 192) !== 128) {
|
|
46
|
-
ok = false;
|
|
47
|
-
break;
|
|
48
|
-
}
|
|
49
|
-
cp = cp << 6 | c & 63;
|
|
50
|
-
}
|
|
51
|
-
if (!ok) {
|
|
52
|
-
i++;
|
|
53
|
-
continue;
|
|
54
|
-
}
|
|
55
|
-
if (len === 3 && (cp < 2048 || cp >= 55296 && cp <= 57343))
|
|
56
|
-
ok = false;
|
|
57
|
-
if (len === 4 && (cp < 65536 || cp > 1114111))
|
|
58
|
-
ok = false;
|
|
59
|
-
if (!ok) {
|
|
60
|
-
i++;
|
|
61
|
-
continue;
|
|
62
|
-
}
|
|
63
|
-
out += String.fromCodePoint(cp);
|
|
64
|
-
i += len;
|
|
65
|
-
}
|
|
66
|
-
return out;
|
|
67
|
-
}
|
|
68
|
-
function environ() {
|
|
69
|
-
const out = {};
|
|
70
|
-
for (const [key, value] of Object.entries(process.env)) {
|
|
71
|
-
if (value !== undefined)
|
|
72
|
-
out[key] = value;
|
|
73
|
-
}
|
|
74
|
-
return out;
|
|
75
|
-
}
|
|
12
|
+
import { existsSync as existsSync2, mkdirSync, openSync, readFileSync, statSync as statSync2, writeFileSync, writeSync as writeSync2 } from "node:fs";
|
|
13
|
+
import { basename, dirname, resolve } from "node:path";
|
|
76
14
|
|
|
77
15
|
// src/highlight_filter.ts
|
|
78
16
|
var WORD_TAIL = /[A-Za-z0-9'_-]+$/;
|
|
@@ -93,7 +31,7 @@ function finditer(pat, s) {
|
|
|
93
31
|
return out;
|
|
94
32
|
}
|
|
95
33
|
function asciiReplace(b) {
|
|
96
|
-
return b.toString("latin1").replace(/[\u0080-\u00ff]/g, "
|
|
34
|
+
return b.toString("latin1").replace(/[\u0080-\u00ff]/g, "�");
|
|
97
35
|
}
|
|
98
36
|
var isDigits = (s) => /^[0-9]+$/.test(s);
|
|
99
37
|
|
|
@@ -576,7 +514,7 @@ var FRAME_END = /\x1b\[\?2026l/g;
|
|
|
576
514
|
var PARTIAL_CSI = /^\x1b\[[\x30-\x3f]*[\x20-\x2f]*$/;
|
|
577
515
|
var MAX_FIX = 4096;
|
|
578
516
|
var MAX_PENDING = 4096;
|
|
579
|
-
var RULE_CHARS = new Set("
|
|
517
|
+
var RULE_CHARS = new Set("─━╌╍┄┅┈┉│┃╭╮╰╯┌┐└┘├┤┬┴┼");
|
|
580
518
|
var BOTTOM_CHROME = 10;
|
|
581
519
|
var MAX_COMPOSER = 24;
|
|
582
520
|
var WIDE = [
|
|
@@ -1420,186 +1358,66 @@ function span(a, b) {
|
|
|
1420
1358
|
}
|
|
1421
1359
|
|
|
1422
1360
|
// src/pty.ts
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
FFIType.u64,
|
|
1432
|
-
FFIType.u64,
|
|
1433
|
-
FFIType.u64,
|
|
1434
|
-
FFIType.u64
|
|
1435
|
-
];
|
|
1436
|
-
var IOCTL = {
|
|
1437
|
-
ioctl: {
|
|
1438
|
-
args: APPLE_VARARGS ? [FFIType.i32, FFIType.u64, ...IOCTL_PAD, FFIType.ptr] : [FFIType.i32, FFIType.u64, FFIType.ptr],
|
|
1439
|
-
returns: FFIType.i32
|
|
1440
|
-
}
|
|
1441
|
-
};
|
|
1442
|
-
var CORE = {
|
|
1443
|
-
read: { args: [FFIType.i32, FFIType.ptr, FFIType.u64], returns: FFIType.i64 },
|
|
1444
|
-
write: { args: [FFIType.i32, FFIType.ptr, FFIType.u64], returns: FFIType.i64 },
|
|
1445
|
-
close: { args: [FFIType.i32], returns: FFIType.i32 },
|
|
1446
|
-
kill: { args: [FFIType.i32, FFIType.i32], returns: FFIType.i32 },
|
|
1447
|
-
tcgetattr: { args: [FFIType.i32, FFIType.ptr], returns: FFIType.i32 },
|
|
1448
|
-
tcsetattr: { args: [FFIType.i32, FFIType.i32, FFIType.ptr], returns: FFIType.i32 },
|
|
1449
|
-
cfmakeraw: { args: [FFIType.ptr], returns: FFIType.i32 }
|
|
1450
|
-
};
|
|
1451
|
-
var OPENPTY = {
|
|
1452
|
-
openpty: {
|
|
1453
|
-
args: [FFIType.ptr, FFIType.ptr, FFIType.ptr, FFIType.ptr, FFIType.ptr],
|
|
1454
|
-
returns: FFIType.i32
|
|
1455
|
-
}
|
|
1456
|
-
};
|
|
1457
|
-
function bind(symbols) {
|
|
1458
|
-
return symbols;
|
|
1361
|
+
var IS_BUN = typeof globalThis.Bun !== "undefined";
|
|
1362
|
+
async function ptySpawn(file, args, opts) {
|
|
1363
|
+
if (IS_BUN) {
|
|
1364
|
+
const { ptySpawnBun } = await import("./pty-bun-2y4wmvve.js");
|
|
1365
|
+
return ptySpawnBun(file, args, opts);
|
|
1366
|
+
}
|
|
1367
|
+
const { ptySpawnNode } = await import("./pty-node-6j2dj9ta.js");
|
|
1368
|
+
return ptySpawnNode(file, args, opts);
|
|
1459
1369
|
}
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1370
|
+
|
|
1371
|
+
// src/sys.ts
|
|
1372
|
+
import { existsSync, statSync, writeSync } from "node:fs";
|
|
1373
|
+
import { join } from "node:path";
|
|
1374
|
+
import { isatty } from "node:tty";
|
|
1375
|
+
function setRawStdin() {
|
|
1376
|
+
if (!isatty(0) || typeof process.stdin.setRawMode !== "function")
|
|
1377
|
+
return null;
|
|
1378
|
+
process.stdin.setRawMode(true);
|
|
1379
|
+
return () => {
|
|
1468
1380
|
try {
|
|
1469
|
-
|
|
1381
|
+
process.stdin.setRawMode(false);
|
|
1470
1382
|
} catch {}
|
|
1471
|
-
}
|
|
1472
|
-
throw new Error("openpty not found in libc.so.6, libutil.so.1 or libutil.so");
|
|
1473
|
-
}
|
|
1474
|
-
var ffi = load();
|
|
1475
|
-
var TCSANOW = 0;
|
|
1476
|
-
var TIOCGWINSZ = process.platform === "darwin" ? 1074295912 : 21523;
|
|
1477
|
-
var TIOCSWINSZ = process.platform === "darwin" ? 2148037735 : 21524;
|
|
1478
|
-
var SIGWINCH = 28;
|
|
1479
|
-
var SIGHUP = 1;
|
|
1480
|
-
var SIGTERM = 15;
|
|
1481
|
-
function saveAndSetRawStdin() {
|
|
1482
|
-
const cur = Buffer.alloc(128);
|
|
1483
|
-
if (ffi.core.tcgetattr(0, cur) !== 0)
|
|
1484
|
-
return null;
|
|
1485
|
-
const saved = Buffer.from(cur);
|
|
1486
|
-
ffi.core.cfmakeraw(cur);
|
|
1487
|
-
ffi.core.tcsetattr(0, TCSANOW, cur);
|
|
1488
|
-
return saved;
|
|
1489
|
-
}
|
|
1490
|
-
function restoreStdin(saved) {
|
|
1491
|
-
ffi.core.tcsetattr(0, TCSANOW, saved);
|
|
1492
|
-
}
|
|
1493
|
-
function setWinsize(master, rows, cols) {
|
|
1494
|
-
const ws = Buffer.alloc(8);
|
|
1495
|
-
ws.writeUInt16LE(Math.max(rows, 1) & 65535, 0);
|
|
1496
|
-
ws.writeUInt16LE(Math.max(cols, 1) & 65535, 2);
|
|
1497
|
-
return ioctlPtr(master, TIOCSWINSZ, ws);
|
|
1383
|
+
};
|
|
1498
1384
|
}
|
|
1499
|
-
function
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
if (ioctlPtr(fd, TIOCGWINSZ, ws) !== 0)
|
|
1505
|
-
return null;
|
|
1506
|
-
return [ws.readUInt16LE(0), ws.readUInt16LE(2)];
|
|
1385
|
+
function winsize() {
|
|
1386
|
+
const rows = process.stdout.rows, cols = process.stdout.columns;
|
|
1387
|
+
if (rows && cols)
|
|
1388
|
+
return [rows, cols];
|
|
1389
|
+
return [24, Number(process.env["COLUMNS"]) || 80];
|
|
1507
1390
|
}
|
|
1508
1391
|
function writeAll(fd, data) {
|
|
1509
1392
|
let off = 0;
|
|
1510
1393
|
while (off < data.length) {
|
|
1511
|
-
|
|
1512
|
-
|
|
1394
|
+
try {
|
|
1395
|
+
off += writeSync(fd, data, off);
|
|
1396
|
+
} catch (e) {
|
|
1397
|
+
const code = e.code;
|
|
1398
|
+
if (code === "EAGAIN")
|
|
1399
|
+
continue;
|
|
1513
1400
|
return;
|
|
1514
|
-
|
|
1401
|
+
}
|
|
1515
1402
|
}
|
|
1516
1403
|
}
|
|
1517
1404
|
var SLEEPER = new Int32Array(new SharedArrayBuffer(4));
|
|
1518
1405
|
function sleepSync(ms) {
|
|
1519
1406
|
Atomics.wait(SLEEPER, 0, 0, ms);
|
|
1520
1407
|
}
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
if (rc !== 0)
|
|
1535
|
-
throw new Error(`openpty failed (${rc})`);
|
|
1536
|
-
const master = m.readInt32LE(0);
|
|
1537
|
-
const slave = s.readInt32LE(0);
|
|
1538
|
-
const proc = Bun.spawn([file, ...args], {
|
|
1539
|
-
stdin: slave,
|
|
1540
|
-
stdout: slave,
|
|
1541
|
-
stderr: slave,
|
|
1542
|
-
env: opts.env ?? environ(),
|
|
1543
|
-
...opts.cwd === undefined ? {} : { cwd: opts.cwd }
|
|
1544
|
-
});
|
|
1545
|
-
closeSync(slave);
|
|
1546
|
-
const reader = new Worker(workerUrl("pty-read-worker"));
|
|
1547
|
-
const writer = new Worker(workerUrl("pty-write-worker"));
|
|
1548
|
-
let dataCb = null;
|
|
1549
|
-
let markDrained = () => {};
|
|
1550
|
-
const drained = new Promise((res) => {
|
|
1551
|
-
markDrained = res;
|
|
1552
|
-
});
|
|
1553
|
-
reader.addEventListener("message", (event) => {
|
|
1554
|
-
const chunk = event.data;
|
|
1555
|
-
if (chunk === null)
|
|
1556
|
-
markDrained();
|
|
1557
|
-
else
|
|
1558
|
-
dataCb?.(Buffer.from(chunk));
|
|
1559
|
-
});
|
|
1560
|
-
const exited = (async () => Number(await proc.exited))();
|
|
1561
|
-
let reading = false;
|
|
1562
|
-
return {
|
|
1563
|
-
pid: proc.pid,
|
|
1564
|
-
get exited() {
|
|
1565
|
-
return exited;
|
|
1566
|
-
},
|
|
1567
|
-
get drained() {
|
|
1568
|
-
return drained;
|
|
1569
|
-
},
|
|
1570
|
-
write(data) {
|
|
1571
|
-
writer.postMessage({ fd: master, data: new Uint8Array(data) });
|
|
1572
|
-
},
|
|
1573
|
-
onData(cb) {
|
|
1574
|
-
dataCb = cb;
|
|
1575
|
-
if (!reading) {
|
|
1576
|
-
reading = true;
|
|
1577
|
-
reader.postMessage({ fd: master });
|
|
1578
|
-
}
|
|
1579
|
-
},
|
|
1580
|
-
resize(rows, cols) {
|
|
1581
|
-
setWinsize(master, rows, cols);
|
|
1582
|
-
try {
|
|
1583
|
-
proc.kill(SIGWINCH);
|
|
1584
|
-
} catch {}
|
|
1585
|
-
},
|
|
1586
|
-
kill(signal = SIGTERM) {
|
|
1587
|
-
try {
|
|
1588
|
-
proc.kill(signal);
|
|
1589
|
-
} catch {}
|
|
1590
|
-
},
|
|
1591
|
-
destroy() {
|
|
1592
|
-
try {
|
|
1593
|
-
proc.kill(SIGHUP);
|
|
1594
|
-
} catch {}
|
|
1595
|
-
try {
|
|
1596
|
-
closeSync(master);
|
|
1597
|
-
} catch {}
|
|
1598
|
-
markDrained();
|
|
1599
|
-
reader.terminate();
|
|
1600
|
-
writer.terminate();
|
|
1601
|
-
}
|
|
1602
|
-
};
|
|
1408
|
+
function which(name) {
|
|
1409
|
+
if (name.includes("/"))
|
|
1410
|
+
return null;
|
|
1411
|
+
for (const dir of (process.env["PATH"] ?? "").split(":")) {
|
|
1412
|
+
if (!dir)
|
|
1413
|
+
continue;
|
|
1414
|
+
const candidate = join(dir, name);
|
|
1415
|
+
try {
|
|
1416
|
+
if (existsSync(candidate) && statSync(candidate).isFile())
|
|
1417
|
+
return candidate;
|
|
1418
|
+
} catch {}
|
|
1419
|
+
}
|
|
1420
|
+
return null;
|
|
1603
1421
|
}
|
|
1604
1422
|
|
|
1605
1423
|
// src/json.ts
|
|
@@ -1628,15 +1446,16 @@ function truthy(v) {
|
|
|
1628
1446
|
}
|
|
1629
1447
|
|
|
1630
1448
|
// src/claude-highlight.ts
|
|
1631
|
-
|
|
1449
|
+
":";
|
|
1450
|
+
var DOC = `claude-highlight — run Claude Code behind a PTY that colors epistemic markers.
|
|
1632
1451
|
|
|
1633
1452
|
claude-highlight [any claude args...]
|
|
1634
1453
|
|
|
1635
1454
|
Spawns the real \`claude\` on a pseudo-terminal and forwards bytes both ways,
|
|
1636
1455
|
injecting SGR color around matched words on the way out. Because SGR is
|
|
1637
|
-
zero-width, the child's layout math is untouched
|
|
1456
|
+
zero-width, the child's layout math is untouched — see highlight_filter.ts.
|
|
1638
1457
|
|
|
1639
|
-
Hotkey (default F9, or bind cmd+/ in Ghostty
|
|
1458
|
+
Hotkey (default F9, or bind cmd+/ in Ghostty — see README) opens a plugin
|
|
1640
1459
|
menu to toggle categories live. Config lives at
|
|
1641
1460
|
~/.config/claude-highlight/config.json and is re-read whenever it changes.
|
|
1642
1461
|
`;
|
|
@@ -1667,7 +1486,7 @@ function text(v, fallback) {
|
|
|
1667
1486
|
return v === undefined ? fallback : String(v);
|
|
1668
1487
|
}
|
|
1669
1488
|
function loadConfig() {
|
|
1670
|
-
const parsed =
|
|
1489
|
+
const parsed = existsSync2(CONFIG) ? parseJson(readFileSync(CONFIG, "utf8")) : null;
|
|
1671
1490
|
const user = isObject(parsed) ? parsed : {};
|
|
1672
1491
|
const catsRaw = user["categories"];
|
|
1673
1492
|
const cats = isObject(catsRaw) ? catsRaw : {};
|
|
@@ -1709,7 +1528,7 @@ function loadConfig() {
|
|
|
1709
1528
|
prose_only: truthy(user["prose_only"] ?? true),
|
|
1710
1529
|
idle_repaint: truthy(user["idle_repaint"] ?? false)
|
|
1711
1530
|
};
|
|
1712
|
-
if (!
|
|
1531
|
+
if (!existsSync2(CONFIG)) {
|
|
1713
1532
|
mkdirSync(dirname(CONFIG), { recursive: true });
|
|
1714
1533
|
writeFileSync(CONFIG, JSON.stringify(cfgAll, null, 2));
|
|
1715
1534
|
}
|
|
@@ -1725,11 +1544,11 @@ function selfName() {
|
|
|
1725
1544
|
base.replace(/\.[jt]s$/, "")
|
|
1726
1545
|
];
|
|
1727
1546
|
for (const name of candidates) {
|
|
1728
|
-
const found =
|
|
1547
|
+
const found = which(name);
|
|
1729
1548
|
if (!found)
|
|
1730
1549
|
continue;
|
|
1731
1550
|
try {
|
|
1732
|
-
const a =
|
|
1551
|
+
const a = statSync2(found), b = statSync2(resolve(argv0));
|
|
1733
1552
|
if (a.ino === b.ino && a.dev === b.dev)
|
|
1734
1553
|
return name;
|
|
1735
1554
|
} catch {}
|
|
@@ -1819,17 +1638,17 @@ var SEL_BG = c_("48;2;64;74;112", "48;5;238");
|
|
|
1819
1638
|
var SEL_FG = c_("38;2;255;255;255", "38;5;255");
|
|
1820
1639
|
var SEL_BAR = c_("38;2;255;214;102", "38;5;221");
|
|
1821
1640
|
var G = UNICODE ? {
|
|
1822
|
-
tl: "
|
|
1823
|
-
tr: "
|
|
1824
|
-
bl: "
|
|
1825
|
-
br: "
|
|
1826
|
-
h: "
|
|
1827
|
-
v: "
|
|
1828
|
-
vsel: "
|
|
1829
|
-
mark: "
|
|
1830
|
-
swatch: "
|
|
1831
|
-
up: "
|
|
1832
|
-
dot: "
|
|
1641
|
+
tl: "╭",
|
|
1642
|
+
tr: "╮",
|
|
1643
|
+
bl: "╰",
|
|
1644
|
+
br: "╯",
|
|
1645
|
+
h: "─",
|
|
1646
|
+
v: "│",
|
|
1647
|
+
vsel: "┃",
|
|
1648
|
+
mark: " ▸ ",
|
|
1649
|
+
swatch: "██",
|
|
1650
|
+
up: "↑↓",
|
|
1651
|
+
dot: "·"
|
|
1833
1652
|
} : {
|
|
1834
1653
|
tl: "+",
|
|
1835
1654
|
tr: "+",
|
|
@@ -1902,37 +1721,37 @@ function drawMenu(cfg, rows, cols, sel) {
|
|
|
1902
1721
|
}
|
|
1903
1722
|
var PALETTE = [
|
|
1904
1723
|
[
|
|
1905
|
-
"reds
|
|
1724
|
+
"reds — loudest, for the claim you most want to catch",
|
|
1906
1725
|
"inference",
|
|
1907
1726
|
[203, 196, 202, 209, 167, 174, 210, 168]
|
|
1908
1727
|
],
|
|
1909
1728
|
[
|
|
1910
|
-
"pinks and magentas
|
|
1729
|
+
"pinks and magentas — loud but not alarming",
|
|
1911
1730
|
"unknown",
|
|
1912
1731
|
[170, 176, 177, 183, 213, 205, 141, 218]
|
|
1913
1732
|
],
|
|
1914
1733
|
[
|
|
1915
|
-
"ambers and yellows
|
|
1734
|
+
"ambers and yellows — warm, reads as 'check this'",
|
|
1916
1735
|
"assumption",
|
|
1917
1736
|
[214, 215, 220, 221, 222, 178, 136, 223]
|
|
1918
1737
|
],
|
|
1919
1738
|
[
|
|
1920
|
-
"golds and tans
|
|
1739
|
+
"golds and tans — quieter warmth, good for a busy category",
|
|
1921
1740
|
"appearance",
|
|
1922
1741
|
[179, 180, 187, 144, 137, 173, 143, 229]
|
|
1923
1742
|
],
|
|
1924
1743
|
[
|
|
1925
|
-
"cyans and teals
|
|
1744
|
+
"cyans and teals — cold, opposite end from the reds",
|
|
1926
1745
|
"overclaim",
|
|
1927
1746
|
[51, 45, 44, 80, 87, 116, 73, 37]
|
|
1928
1747
|
],
|
|
1929
1748
|
[
|
|
1930
1749
|
"greens",
|
|
1931
|
-
"unused
|
|
1750
|
+
"unused — free for a category of your own",
|
|
1932
1751
|
[71, 78, 108, 114, 150, 84, 42, 155]
|
|
1933
1752
|
],
|
|
1934
1753
|
[
|
|
1935
|
-
"blues and violets
|
|
1754
|
+
"blues and violets — cool, and nothing in warm prose competes with them",
|
|
1936
1755
|
"modal, vagueness, softener",
|
|
1937
1756
|
[33, 39, 99, 105, 27, 63, 93, 135]
|
|
1938
1757
|
]
|
|
@@ -1959,7 +1778,7 @@ function paletteLines(cfg, cols, full = false) {
|
|
|
1959
1778
|
for (let base = 16;base < 256; base += 12) {
|
|
1960
1779
|
let line = "";
|
|
1961
1780
|
for (let n = base;n < Math.min(base + 12, 256); n++) {
|
|
1962
|
-
line += `\x1B[38;5;${n}m
|
|
1781
|
+
line += `\x1B[38;5;${n}m██\x1B[39m${String(n).padEnd(4)}`;
|
|
1963
1782
|
}
|
|
1964
1783
|
out.push(" " + line);
|
|
1965
1784
|
}
|
|
@@ -2072,10 +1891,7 @@ function parseArgs(argv) {
|
|
|
2072
1891
|
return a;
|
|
2073
1892
|
}
|
|
2074
1893
|
function stdoutCols() {
|
|
2075
|
-
|
|
2076
|
-
if (sz && sz[1])
|
|
2077
|
-
return sz[1];
|
|
2078
|
-
return Number(process.env["COLUMNS"]) || 100;
|
|
1894
|
+
return process.stdout.columns || Number(process.env["COLUMNS"]) || 100;
|
|
2079
1895
|
}
|
|
2080
1896
|
async function main(argv) {
|
|
2081
1897
|
const known = parseArgs(argv);
|
|
@@ -2100,7 +1916,7 @@ async function main(argv) {
|
|
|
2100
1916
|
`, "utf8"));
|
|
2101
1917
|
return 0;
|
|
2102
1918
|
}
|
|
2103
|
-
let mtime =
|
|
1919
|
+
let mtime = existsSync2(CONFIG) ? statSync2(CONFIG).mtimeMs : 0;
|
|
2104
1920
|
const hl = new AnsiHighlighter(buildRules(cfg), cfg.prose_only);
|
|
2105
1921
|
hl.rewrites = buildRewrites();
|
|
2106
1922
|
hl.holdPrefixes = growablePrefixes(userFragments(cfg));
|
|
@@ -2108,13 +1924,12 @@ async function main(argv) {
|
|
|
2108
1924
|
const child = process.env["CLAUDE_HIGHLIGHT_CMD"] ?? "claude";
|
|
2109
1925
|
const recRaw = known.hlRecord === null ? null : openSync(known.hlRecord + ".raw", "w");
|
|
2110
1926
|
const recOut = known.hlRecord === null ? null : openSync(known.hlRecord + ".out", "w");
|
|
2111
|
-
let [rows, cols] =
|
|
2112
|
-
const pty = ptySpawn(child, known.rest, { rows, cols, env: environ() });
|
|
1927
|
+
let [rows, cols] = winsize();
|
|
1928
|
+
const pty = await ptySpawn(child, known.rest, { rows, cols, env: environ() });
|
|
2113
1929
|
screen.resize(rows, cols);
|
|
2114
|
-
const
|
|
1930
|
+
const restoreStdin = setRawStdin();
|
|
2115
1931
|
process.on("SIGWINCH", () => {
|
|
2116
|
-
|
|
2117
|
-
[rows, cols] = sz ?? [24, 80];
|
|
1932
|
+
[rows, cols] = winsize();
|
|
2118
1933
|
pty.resize(rows, cols);
|
|
2119
1934
|
screen.resize(rows, cols);
|
|
2120
1935
|
});
|
|
@@ -2128,14 +1943,14 @@ async function main(argv) {
|
|
|
2128
1943
|
return;
|
|
2129
1944
|
writeAll(1, out);
|
|
2130
1945
|
if (recOut !== null)
|
|
2131
|
-
|
|
1946
|
+
writeSync2(recOut, out);
|
|
2132
1947
|
};
|
|
2133
1948
|
const closeMenu = () => {
|
|
2134
1949
|
menu = false;
|
|
2135
1950
|
screen.invalidate();
|
|
2136
1951
|
writeAll(1, Buffer.from("\x1B[?25h", "latin1"));
|
|
2137
1952
|
writeFileSync(CONFIG, JSON.stringify(cfg, null, 2));
|
|
2138
|
-
mtime =
|
|
1953
|
+
mtime = statSync2(CONFIG).mtimeMs;
|
|
2139
1954
|
forceRepaint(pty, rows, cols);
|
|
2140
1955
|
};
|
|
2141
1956
|
pty.onData((data) => {
|
|
@@ -2143,7 +1958,7 @@ async function main(argv) {
|
|
|
2143
1958
|
lastData = performance.now();
|
|
2144
1959
|
repainted = false;
|
|
2145
1960
|
if (recRaw !== null)
|
|
2146
|
-
|
|
1961
|
+
writeSync2(recRaw, data);
|
|
2147
1962
|
if (!menu) {
|
|
2148
1963
|
emit(screen.reconcile(hl.feed(data), hl.rules, hl.onlyUnstyled));
|
|
2149
1964
|
} else {
|
|
@@ -2216,15 +2031,14 @@ async function main(argv) {
|
|
|
2216
2031
|
if (toChild.length)
|
|
2217
2032
|
pty.write(Buffer.from(toChild.join(""), "latin1"));
|
|
2218
2033
|
};
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
onStdin(Buffer.from(chunk));
|
|
2034
|
+
process.stdin.on("data", (chunk) => {
|
|
2035
|
+
if (stdinOpen)
|
|
2036
|
+
onStdin(chunk);
|
|
2037
|
+
});
|
|
2038
|
+
process.stdin.on("end", () => {
|
|
2039
|
+
stdinOpen = false;
|
|
2226
2040
|
});
|
|
2227
|
-
|
|
2041
|
+
process.stdin.resume();
|
|
2228
2042
|
const tick = () => {
|
|
2229
2043
|
if (sawData) {
|
|
2230
2044
|
sawData = false;
|
|
@@ -2236,8 +2050,8 @@ async function main(argv) {
|
|
|
2236
2050
|
repainted = true;
|
|
2237
2051
|
forceRepaint(pty, rows, cols);
|
|
2238
2052
|
}
|
|
2239
|
-
if (
|
|
2240
|
-
mtime =
|
|
2053
|
+
if (existsSync2(CONFIG) && statSync2(CONFIG).mtimeMs !== mtime) {
|
|
2054
|
+
mtime = statSync2(CONFIG).mtimeMs;
|
|
2241
2055
|
cfg = loadConfig();
|
|
2242
2056
|
hl.rules = buildRules(cfg);
|
|
2243
2057
|
hl.onlyUnstyled = cfg.prose_only;
|
|
@@ -2249,9 +2063,8 @@ async function main(argv) {
|
|
|
2249
2063
|
const timer = setInterval(tick, IDLE);
|
|
2250
2064
|
await pty.drained;
|
|
2251
2065
|
clearInterval(timer);
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
restoreStdin(old);
|
|
2066
|
+
process.stdin.pause();
|
|
2067
|
+
restoreStdin?.();
|
|
2255
2068
|
try {
|
|
2256
2069
|
emit(hl.drain(true));
|
|
2257
2070
|
} catch {}
|
|
@@ -2259,7 +2072,7 @@ async function main(argv) {
|
|
|
2259
2072
|
pty.destroy();
|
|
2260
2073
|
return code;
|
|
2261
2074
|
}
|
|
2262
|
-
if (
|
|
2075
|
+
if (__require.main == __require.module) {
|
|
2263
2076
|
process.exit(await main(process.argv.slice(2)));
|
|
2264
2077
|
}
|
|
2265
2078
|
export {
|