claude-doom-statusbar 0.1.1 → 0.2.0
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/assets/images/hud.png +0 -0
- package/package.json +1 -1
- package/src/render.js +21 -15
- package/src/statusline.js +2 -2
package/assets/images/hud.png
CHANGED
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-doom-statusbar",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "DOOM-inspired status bar for the Claude Code CLI — a mugshot that tracks session health, plus usage, model, project, system, and a live subagent list.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
package/src/render.js
CHANGED
|
@@ -36,10 +36,10 @@ export const SAMPLE = {
|
|
|
36
36
|
"pr.state": "#1234",
|
|
37
37
|
"act.subagents": [["hook events", "2m13s"], ["find configs", "12s"]], "act.agents": "2",
|
|
38
38
|
"act.tasklist": [
|
|
39
|
-
{ mark:"
|
|
40
|
-
{ mark:"
|
|
41
|
-
{ mark:"
|
|
42
|
-
{ mark:"
|
|
39
|
+
{ mark:"✅", markRgb: OK, text:"scaffold project" },
|
|
40
|
+
{ mark:"✅", markRgb: OK, text:"render engine" },
|
|
41
|
+
{ mark:"❌", markRgb: CRIT, text:"port PIL alpha" },
|
|
42
|
+
{ mark:"⏩", markRgb: null, text:"statusline values" },
|
|
43
43
|
{ mark:"🎯", markRgb: null, text:"hook bus" },
|
|
44
44
|
{ mark:"🎯", markRgb: null, text:"installer" },
|
|
45
45
|
],
|
|
@@ -58,7 +58,8 @@ export function vlen(s) {
|
|
|
58
58
|
let n = 0;
|
|
59
59
|
for (const ch of String(s).replace(ANSI_RE, "")) {
|
|
60
60
|
const cp = ch.codePointAt(0);
|
|
61
|
-
n += (cp >= 0x1f300 && cp <= 0x1faff) || (cp >= 0x23e9 && cp <= 0x23ec)
|
|
61
|
+
n += (cp >= 0x1f300 && cp <= 0x1faff) || (cp >= 0x23e9 && cp <= 0x23ec)
|
|
62
|
+
|| cp === 0x2705 || cp === 0x274c ? 2 : 1; // ✅ ❌ are emoji-presentation (2 cols)
|
|
62
63
|
}
|
|
63
64
|
return n;
|
|
64
65
|
}
|
|
@@ -368,30 +369,35 @@ export function buildBar(cfg, target, spriteFor) {
|
|
|
368
369
|
const items = VALUES[m.id] || [];
|
|
369
370
|
const H = totalRows - (headers ? 1 : 0);
|
|
370
371
|
const boundary = items.filter((it) => !Array.isArray(it) &&
|
|
371
|
-
(it.mark === "
|
|
372
|
+
(it.mark === "✅" || it.mark === "❌")).length; // settled count (ignored for top anchor)
|
|
372
373
|
const win = scrollWindow(items.length, H, m.anchor || "top", boundary);
|
|
373
374
|
const shown = items.slice(win.start, win.start + H);
|
|
374
375
|
shown.forEach((item, k) => {
|
|
375
376
|
const first = k === 0, last = k === shown.length - 1;
|
|
376
|
-
const
|
|
377
|
+
const marker = first && win.up > 0 ? `↑${win.up}` : last && win.down > 0 ? `↓${win.down}` : "";
|
|
378
|
+
const tail = marker ? " " + marker : ""; // right-aligned scroll marker (gap + ↑k/↓k)
|
|
379
|
+
const tailW = vlen(tail);
|
|
377
380
|
let body;
|
|
378
381
|
if (Array.isArray(item)) { // [left, right] (agents)
|
|
379
|
-
const right = f(TEXT) + String(item[1]);
|
|
380
|
-
const
|
|
381
|
-
const labelMax = Math.max(0, w - vlen(
|
|
382
|
+
const right = f(TEXT) + String(item[1]) + (marker ? f(TEXT) + tail : "");
|
|
383
|
+
const rightW = vlen(String(item[1])) + tailW;
|
|
384
|
+
const labelMax = Math.max(0, w - vlen(lbl) - rightW - 1); // 1 = min gap
|
|
382
385
|
let label = String(item[0]);
|
|
383
386
|
if (vlen(label) > labelMax) label = [...label].slice(0, Math.max(0, labelMax - 1)).join("") + "…";
|
|
384
|
-
const left =
|
|
385
|
-
const room = Math.max(0, w - vlen(left) -
|
|
387
|
+
const left = lbl + f(TEXT) + label;
|
|
388
|
+
const room = Math.max(0, w - vlen(left) - rightW);
|
|
386
389
|
body = left + " ".repeat(room) + right;
|
|
387
390
|
} else { // {mark, markRgb, text} (tasks)
|
|
388
391
|
const markCol = item.markRgb ? f(item.markRgb) : f(TEXT);
|
|
392
|
+
const m = String(item.mark);
|
|
393
|
+
const mPad = m + (vlen(m) < 2 ? " " : ""); // normalize mark to 2 cols so text aligns
|
|
389
394
|
let text = String(item.text);
|
|
390
|
-
const head =
|
|
391
|
-
const max = w - vlen(
|
|
395
|
+
const head = markCol + mPad + " " + f(TEXT);
|
|
396
|
+
const max = w - vlen(mPad) - 1 - tailW; // reserve gap + marker on the right
|
|
392
397
|
if (vlen(text) > max) text = [...text].slice(0, Math.max(0, max - 1)).join("") + "…";
|
|
393
398
|
body = head + text;
|
|
394
|
-
body += " ".repeat(Math.max(0, w - vlen(body)));
|
|
399
|
+
body += " ".repeat(Math.max(0, w - tailW - vlen(body)));
|
|
400
|
+
if (tail) body += f(TEXT) + tail;
|
|
395
401
|
}
|
|
396
402
|
col.push(bgsgrBox(boxRgb) + " " + body + " " + RESET);
|
|
397
403
|
});
|
package/src/statusline.js
CHANGED
|
@@ -218,8 +218,8 @@ function sysValues(cwd) {
|
|
|
218
218
|
const PERM = { plan: "📋 plan", auto: "⏩ auto", acceptEdits: "⏩ auto", bypassPermissions: "⏩ bypass" };
|
|
219
219
|
const OK_RGB = [96, 200, 104]; // matches render.js OK (done, green)
|
|
220
220
|
const CRIT_RGB = [224, 84, 64]; // matches render.js CRIT (deleted, red)
|
|
221
|
-
const TASK_MARK = { completed: ["
|
|
222
|
-
const TASK_ORDER = { completed: 0, deleted:
|
|
221
|
+
const TASK_MARK = { completed: ["✅", OK_RGB], deleted: ["❌", CRIT_RGB], in_progress: ["⏩", null], pending: ["🎯", null] };
|
|
222
|
+
const TASK_ORDER = { completed: 0, deleted: 0, in_progress: 1, pending: 2 }; // settled (done+deleted, by time) first, then open
|
|
223
223
|
|
|
224
224
|
export function activityValues(st, now) {
|
|
225
225
|
const v = {};
|