claude-scope 0.5.3 → 0.5.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/README.md +26 -1
- package/dist/claude-scope.cjs +680 -127
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -55,7 +55,32 @@ Or for global install:
|
|
|
55
55
|
|
|
56
56
|
## Usage
|
|
57
57
|
|
|
58
|
-
Once configured, claude-scope displays
|
|
58
|
+
Once configured, claude-scope displays real-time session information in your statusline including:
|
|
59
|
+
- Git branch and changes
|
|
60
|
+
- Model information
|
|
61
|
+
- Context usage with progress bar
|
|
62
|
+
- Session duration
|
|
63
|
+
- Cost estimation
|
|
64
|
+
- Lines added/removed
|
|
65
|
+
- Configuration counts
|
|
66
|
+
- Poker hand (entertainment)
|
|
67
|
+
|
|
68
|
+
### Widget Display Styles
|
|
69
|
+
|
|
70
|
+
Each widget supports multiple display styles for customization:
|
|
71
|
+
|
|
72
|
+
| Style | Description |
|
|
73
|
+
|-------|-------------|
|
|
74
|
+
| `balanced` | Default balanced style (minimalism + informativeness) |
|
|
75
|
+
| `compact` | Maximally compact display |
|
|
76
|
+
| `playful` | Fun style with informative emojis |
|
|
77
|
+
| `verbose` | Detailed text descriptions |
|
|
78
|
+
| `technical` | Technical details (model IDs, milliseconds, etc.) |
|
|
79
|
+
| `symbolic` | Symbol-based representation |
|
|
80
|
+
| `labeled` | Prefix labels for clarity |
|
|
81
|
+
| `indicator` | Bullet indicator prefix |
|
|
82
|
+
| `fancy` | Decorative formatting (brackets, quotes) |
|
|
83
|
+
| `compact-verbose` | Compact with K-formatted numbers |
|
|
59
84
|
|
|
60
85
|
**Note:** This is an early release with basic functionality. Additional features (repository status, session analytics, etc.) are planned for future releases.
|
|
61
86
|
|
package/dist/claude-scope.cjs
CHANGED
|
@@ -112,12 +112,6 @@ var TIME = {
|
|
|
112
112
|
/** Seconds per hour */
|
|
113
113
|
SECONDS_PER_HOUR: 3600
|
|
114
114
|
};
|
|
115
|
-
var COST_THRESHOLDS = {
|
|
116
|
-
/** Below this value, show 4 decimal places ($0.0012) */
|
|
117
|
-
SMALL: 0.01,
|
|
118
|
-
/** Above this value, show no decimal places ($123) */
|
|
119
|
-
LARGE: 100
|
|
120
|
-
};
|
|
121
115
|
var DEFAULTS = {
|
|
122
116
|
/** Default separator between widgets */
|
|
123
117
|
SEPARATOR: " ",
|
|
@@ -266,13 +260,9 @@ var NativeGit = class {
|
|
|
266
260
|
}
|
|
267
261
|
async latestTag() {
|
|
268
262
|
try {
|
|
269
|
-
const { stdout } = await execFileAsync(
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
{
|
|
273
|
-
cwd: this.cwd
|
|
274
|
-
}
|
|
275
|
-
);
|
|
263
|
+
const { stdout } = await execFileAsync("git", ["describe", "--tags", "--abbrev=0"], {
|
|
264
|
+
cwd: this.cwd
|
|
265
|
+
});
|
|
276
266
|
return stdout.trim();
|
|
277
267
|
} catch {
|
|
278
268
|
return null;
|
|
@@ -283,6 +273,55 @@ function createGit(cwd) {
|
|
|
283
273
|
return new NativeGit(cwd);
|
|
284
274
|
}
|
|
285
275
|
|
|
276
|
+
// src/ui/utils/style-utils.ts
|
|
277
|
+
function withLabel(prefix, value) {
|
|
278
|
+
if (prefix === "") return value;
|
|
279
|
+
return `${prefix}: ${value}`;
|
|
280
|
+
}
|
|
281
|
+
function withIndicator(value) {
|
|
282
|
+
return `\u25CF ${value}`;
|
|
283
|
+
}
|
|
284
|
+
function withFancy(value) {
|
|
285
|
+
return `\xAB${value}\xBB`;
|
|
286
|
+
}
|
|
287
|
+
function withBrackets(value) {
|
|
288
|
+
return `[${value}]`;
|
|
289
|
+
}
|
|
290
|
+
function withAngleBrackets(value) {
|
|
291
|
+
return `\u27E8${value}\u27E9`;
|
|
292
|
+
}
|
|
293
|
+
function progressBar(percent, width = 10) {
|
|
294
|
+
const clamped = Math.max(0, Math.min(100, percent));
|
|
295
|
+
const filled = Math.round(clamped / 100 * width);
|
|
296
|
+
const empty = width - filled;
|
|
297
|
+
return "\u2588".repeat(filled) + "\u2591".repeat(empty);
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
// src/widgets/git/styles.ts
|
|
301
|
+
var gitStyles = {
|
|
302
|
+
balanced: (data) => {
|
|
303
|
+
return data.branch;
|
|
304
|
+
},
|
|
305
|
+
compact: (data) => {
|
|
306
|
+
return data.branch;
|
|
307
|
+
},
|
|
308
|
+
playful: (data) => {
|
|
309
|
+
return `\u{1F500} ${data.branch}`;
|
|
310
|
+
},
|
|
311
|
+
verbose: (data) => {
|
|
312
|
+
return `branch: ${data.branch} (HEAD)`;
|
|
313
|
+
},
|
|
314
|
+
labeled: (data) => {
|
|
315
|
+
return withLabel("Git", data.branch);
|
|
316
|
+
},
|
|
317
|
+
indicator: (data) => {
|
|
318
|
+
return withIndicator(data.branch);
|
|
319
|
+
},
|
|
320
|
+
fancy: (data) => {
|
|
321
|
+
return withBrackets(data.branch);
|
|
322
|
+
}
|
|
323
|
+
};
|
|
324
|
+
|
|
286
325
|
// src/widgets/git/git-widget.ts
|
|
287
326
|
var GitWidget = class {
|
|
288
327
|
id = "git";
|
|
@@ -298,6 +337,7 @@ var GitWidget = class {
|
|
|
298
337
|
git = null;
|
|
299
338
|
enabled = true;
|
|
300
339
|
cwd = null;
|
|
340
|
+
styleFn = gitStyles.balanced;
|
|
301
341
|
/**
|
|
302
342
|
* @param gitFactory - Optional factory function for creating IGit instances
|
|
303
343
|
* If not provided, uses default createGit (production)
|
|
@@ -306,6 +346,12 @@ var GitWidget = class {
|
|
|
306
346
|
constructor(gitFactory) {
|
|
307
347
|
this.gitFactory = gitFactory || createGit;
|
|
308
348
|
}
|
|
349
|
+
setStyle(style = "balanced") {
|
|
350
|
+
const fn = gitStyles[style];
|
|
351
|
+
if (fn) {
|
|
352
|
+
this.styleFn = fn;
|
|
353
|
+
}
|
|
354
|
+
}
|
|
309
355
|
async initialize(context) {
|
|
310
356
|
this.enabled = context.config?.enabled !== false;
|
|
311
357
|
}
|
|
@@ -319,7 +365,8 @@ var GitWidget = class {
|
|
|
319
365
|
if (!branch) {
|
|
320
366
|
return null;
|
|
321
367
|
}
|
|
322
|
-
|
|
368
|
+
const renderData = { branch };
|
|
369
|
+
return this.styleFn(renderData);
|
|
323
370
|
} catch {
|
|
324
371
|
return null;
|
|
325
372
|
}
|
|
@@ -337,13 +384,32 @@ var GitWidget = class {
|
|
|
337
384
|
}
|
|
338
385
|
};
|
|
339
386
|
|
|
340
|
-
// src/
|
|
341
|
-
var
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
387
|
+
// src/widgets/git-tag/styles.ts
|
|
388
|
+
var gitTagStyles = {
|
|
389
|
+
balanced: (data) => {
|
|
390
|
+
return data.tag || "\u2014";
|
|
391
|
+
},
|
|
392
|
+
compact: (data) => {
|
|
393
|
+
if (!data.tag) return "\u2014";
|
|
394
|
+
return data.tag.replace(/^v/, "");
|
|
395
|
+
},
|
|
396
|
+
playful: (data) => {
|
|
397
|
+
return `\u{1F3F7}\uFE0F ${data.tag || "\u2014"}`;
|
|
398
|
+
},
|
|
399
|
+
verbose: (data) => {
|
|
400
|
+
if (!data.tag) return "version: none";
|
|
401
|
+
return `version ${data.tag}`;
|
|
402
|
+
},
|
|
403
|
+
labeled: (data) => {
|
|
404
|
+
return withLabel("Tag", data.tag || "none");
|
|
405
|
+
},
|
|
406
|
+
indicator: (data) => {
|
|
407
|
+
return withIndicator(data.tag || "\u2014");
|
|
408
|
+
},
|
|
409
|
+
fancy: (data) => {
|
|
410
|
+
return withAngleBrackets(data.tag || "\u2014");
|
|
411
|
+
}
|
|
412
|
+
};
|
|
347
413
|
|
|
348
414
|
// src/widgets/git/git-tag-widget.ts
|
|
349
415
|
var GitTagWidget = class {
|
|
@@ -360,7 +426,7 @@ var GitTagWidget = class {
|
|
|
360
426
|
git = null;
|
|
361
427
|
enabled = true;
|
|
362
428
|
cwd = null;
|
|
363
|
-
|
|
429
|
+
styleFn = gitTagStyles.balanced;
|
|
364
430
|
/**
|
|
365
431
|
* @param gitFactory - Optional factory function for creating IGit instances
|
|
366
432
|
* If not provided, uses default createGit (production)
|
|
@@ -369,6 +435,12 @@ var GitTagWidget = class {
|
|
|
369
435
|
constructor(gitFactory) {
|
|
370
436
|
this.gitFactory = gitFactory || createGit;
|
|
371
437
|
}
|
|
438
|
+
setStyle(style = "balanced") {
|
|
439
|
+
const fn = gitTagStyles[style];
|
|
440
|
+
if (fn) {
|
|
441
|
+
this.styleFn = fn;
|
|
442
|
+
}
|
|
443
|
+
}
|
|
372
444
|
async initialize(context) {
|
|
373
445
|
this.enabled = context.config?.enabled !== false;
|
|
374
446
|
}
|
|
@@ -377,12 +449,9 @@ var GitTagWidget = class {
|
|
|
377
449
|
return null;
|
|
378
450
|
}
|
|
379
451
|
try {
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
}
|
|
384
|
-
const tagValue = `${green}${this.latestTag}${reset}`;
|
|
385
|
-
return `${gray}Tag:${reset} ${tagValue}`;
|
|
452
|
+
const latestTag = await (this.git.latestTag?.() ?? Promise.resolve(null));
|
|
453
|
+
const renderData = { tag: latestTag };
|
|
454
|
+
return this.styleFn(renderData);
|
|
386
455
|
} catch {
|
|
387
456
|
return null;
|
|
388
457
|
}
|
|
@@ -400,6 +469,37 @@ var GitTagWidget = class {
|
|
|
400
469
|
}
|
|
401
470
|
};
|
|
402
471
|
|
|
472
|
+
// src/widgets/model/styles.ts
|
|
473
|
+
function getShortName(displayName) {
|
|
474
|
+
return displayName.replace(/^Claude\s+/, "");
|
|
475
|
+
}
|
|
476
|
+
var modelStyles = {
|
|
477
|
+
balanced: (data) => {
|
|
478
|
+
return data.displayName;
|
|
479
|
+
},
|
|
480
|
+
compact: (data) => {
|
|
481
|
+
return getShortName(data.displayName);
|
|
482
|
+
},
|
|
483
|
+
playful: (data) => {
|
|
484
|
+
return `\u{1F916} ${getShortName(data.displayName)}`;
|
|
485
|
+
},
|
|
486
|
+
technical: (data) => {
|
|
487
|
+
return data.id;
|
|
488
|
+
},
|
|
489
|
+
symbolic: (data) => {
|
|
490
|
+
return `\u25C6 ${getShortName(data.displayName)}`;
|
|
491
|
+
},
|
|
492
|
+
labeled: (data) => {
|
|
493
|
+
return withLabel("Model", getShortName(data.displayName));
|
|
494
|
+
},
|
|
495
|
+
indicator: (data) => {
|
|
496
|
+
return withIndicator(getShortName(data.displayName));
|
|
497
|
+
},
|
|
498
|
+
fancy: (data) => {
|
|
499
|
+
return withBrackets(getShortName(data.displayName));
|
|
500
|
+
}
|
|
501
|
+
};
|
|
502
|
+
|
|
403
503
|
// src/widgets/core/stdin-data-widget.ts
|
|
404
504
|
var StdinDataWidget = class {
|
|
405
505
|
/**
|
|
@@ -469,8 +569,39 @@ var ModelWidget = class extends StdinDataWidget {
|
|
|
469
569
|
0
|
|
470
570
|
// First line
|
|
471
571
|
);
|
|
472
|
-
|
|
473
|
-
|
|
572
|
+
styleFn = modelStyles.balanced;
|
|
573
|
+
setStyle(style = "balanced") {
|
|
574
|
+
const fn = modelStyles[style];
|
|
575
|
+
if (fn) {
|
|
576
|
+
this.styleFn = fn;
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
renderWithData(data, _context) {
|
|
580
|
+
const renderData = {
|
|
581
|
+
displayName: data.model.display_name,
|
|
582
|
+
id: data.model.id
|
|
583
|
+
};
|
|
584
|
+
return this.styleFn(renderData);
|
|
585
|
+
}
|
|
586
|
+
};
|
|
587
|
+
|
|
588
|
+
// src/ui/utils/colors.ts
|
|
589
|
+
var reset = "\x1B[0m";
|
|
590
|
+
var red = "\x1B[31m";
|
|
591
|
+
var gray = "\x1B[90m";
|
|
592
|
+
var lightGray = "\x1B[37m";
|
|
593
|
+
var bold = "\x1B[1m";
|
|
594
|
+
|
|
595
|
+
// src/ui/theme/default-theme.ts
|
|
596
|
+
var DEFAULT_THEME = {
|
|
597
|
+
context: {
|
|
598
|
+
low: gray,
|
|
599
|
+
medium: gray,
|
|
600
|
+
high: gray
|
|
601
|
+
},
|
|
602
|
+
lines: {
|
|
603
|
+
added: gray,
|
|
604
|
+
removed: gray
|
|
474
605
|
}
|
|
475
606
|
};
|
|
476
607
|
|
|
@@ -495,37 +626,45 @@ function formatDuration(ms) {
|
|
|
495
626
|
return parts.join(" ");
|
|
496
627
|
}
|
|
497
628
|
function formatCostUSD(usd) {
|
|
498
|
-
|
|
499
|
-
if (usd < 0) {
|
|
500
|
-
return `$${usd.toFixed(2)}`;
|
|
501
|
-
} else if (absUsd < COST_THRESHOLDS.SMALL) {
|
|
502
|
-
return `$${usd.toFixed(4)}`;
|
|
503
|
-
} else if (absUsd < COST_THRESHOLDS.LARGE) {
|
|
504
|
-
return `$${usd.toFixed(2)}`;
|
|
505
|
-
} else {
|
|
506
|
-
return `$${Math.floor(usd).toFixed(0)}`;
|
|
507
|
-
}
|
|
508
|
-
}
|
|
509
|
-
function progressBar(percent, width = DEFAULTS.PROGRESS_BAR_WIDTH) {
|
|
510
|
-
const clampedPercent = Math.max(0, Math.min(100, percent));
|
|
511
|
-
const filled = Math.round(clampedPercent / 100 * width);
|
|
512
|
-
const empty = width - filled;
|
|
513
|
-
return "\u2588".repeat(filled) + "\u2591".repeat(empty);
|
|
629
|
+
return `$${usd.toFixed(2)}`;
|
|
514
630
|
}
|
|
515
631
|
function colorize(text, color) {
|
|
516
632
|
return `${color}${text}${ANSI_COLORS.RESET}`;
|
|
517
633
|
}
|
|
518
634
|
|
|
519
|
-
// src/
|
|
520
|
-
var
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
high: gray
|
|
635
|
+
// src/widgets/context/styles.ts
|
|
636
|
+
var contextStyles = {
|
|
637
|
+
balanced: (data) => {
|
|
638
|
+
const bar = progressBar(data.percent, 10);
|
|
639
|
+
return `[${bar}] ${data.percent}%`;
|
|
525
640
|
},
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
641
|
+
compact: (data) => {
|
|
642
|
+
return `${data.percent}%`;
|
|
643
|
+
},
|
|
644
|
+
playful: (data) => {
|
|
645
|
+
const bar = progressBar(data.percent, 10);
|
|
646
|
+
return `\u{1F9E0} [${bar}] ${data.percent}%`;
|
|
647
|
+
},
|
|
648
|
+
verbose: (data) => {
|
|
649
|
+
const usedFormatted = data.used.toLocaleString();
|
|
650
|
+
const maxFormatted = data.contextWindowSize.toLocaleString();
|
|
651
|
+
return `${usedFormatted} / ${maxFormatted} tokens (${data.percent}%)`;
|
|
652
|
+
},
|
|
653
|
+
symbolic: (data) => {
|
|
654
|
+
const filled = Math.round(data.percent / 100 * 5);
|
|
655
|
+
const empty = 5 - filled;
|
|
656
|
+
return `${"\u25AE".repeat(filled)}${"\u25AF".repeat(empty)} ${data.percent}%`;
|
|
657
|
+
},
|
|
658
|
+
"compact-verbose": (data) => {
|
|
659
|
+
const usedK = data.used >= 1e3 ? `${Math.floor(data.used / 1e3)}K` : data.used.toString();
|
|
660
|
+
const maxK = data.contextWindowSize >= 1e3 ? `${Math.floor(data.contextWindowSize / 1e3)}K` : data.contextWindowSize.toString();
|
|
661
|
+
return `${data.percent}% (${usedK}/${maxK})`;
|
|
662
|
+
},
|
|
663
|
+
indicator: (data) => {
|
|
664
|
+
return `\u25CF ${data.percent}%`;
|
|
665
|
+
},
|
|
666
|
+
fancy: (data) => {
|
|
667
|
+
return `\u27E8${data.percent}%\u27E9`;
|
|
529
668
|
}
|
|
530
669
|
};
|
|
531
670
|
|
|
@@ -541,18 +680,30 @@ var ContextWidget = class extends StdinDataWidget {
|
|
|
541
680
|
// First line
|
|
542
681
|
);
|
|
543
682
|
colors;
|
|
683
|
+
styleFn = contextStyles.balanced;
|
|
544
684
|
constructor(colors) {
|
|
545
685
|
super();
|
|
546
686
|
this.colors = colors ?? DEFAULT_THEME.context;
|
|
547
687
|
}
|
|
548
|
-
|
|
688
|
+
setStyle(style = "balanced") {
|
|
689
|
+
const fn = contextStyles[style];
|
|
690
|
+
if (fn) {
|
|
691
|
+
this.styleFn = fn;
|
|
692
|
+
}
|
|
693
|
+
}
|
|
694
|
+
renderWithData(data, _context) {
|
|
549
695
|
const { current_usage, context_window_size } = data.context_window;
|
|
550
696
|
if (!current_usage) return null;
|
|
551
697
|
const used = current_usage.input_tokens + current_usage.cache_creation_input_tokens + current_usage.cache_read_input_tokens + current_usage.output_tokens;
|
|
552
698
|
const percent = Math.round(used / context_window_size * 100);
|
|
553
|
-
const
|
|
699
|
+
const renderData = {
|
|
700
|
+
used,
|
|
701
|
+
contextWindowSize: context_window_size,
|
|
702
|
+
percent
|
|
703
|
+
};
|
|
704
|
+
const output = this.styleFn(renderData);
|
|
554
705
|
const color = this.getContextColor(percent);
|
|
555
|
-
return colorize(
|
|
706
|
+
return colorize(output, color);
|
|
556
707
|
}
|
|
557
708
|
getContextColor(percent) {
|
|
558
709
|
const clampedPercent = Math.max(0, Math.min(100, percent));
|
|
@@ -566,6 +717,28 @@ var ContextWidget = class extends StdinDataWidget {
|
|
|
566
717
|
}
|
|
567
718
|
};
|
|
568
719
|
|
|
720
|
+
// src/widgets/cost/styles.ts
|
|
721
|
+
var costStyles = {
|
|
722
|
+
balanced: (data) => {
|
|
723
|
+
return formatCostUSD(data.costUsd);
|
|
724
|
+
},
|
|
725
|
+
compact: (data) => {
|
|
726
|
+
return formatCostUSD(data.costUsd);
|
|
727
|
+
},
|
|
728
|
+
playful: (data) => {
|
|
729
|
+
return `\u{1F4B0} ${formatCostUSD(data.costUsd)}`;
|
|
730
|
+
},
|
|
731
|
+
labeled: (data) => {
|
|
732
|
+
return withLabel("Cost", formatCostUSD(data.costUsd));
|
|
733
|
+
},
|
|
734
|
+
indicator: (data) => {
|
|
735
|
+
return withIndicator(formatCostUSD(data.costUsd));
|
|
736
|
+
},
|
|
737
|
+
fancy: (data) => {
|
|
738
|
+
return withFancy(formatCostUSD(data.costUsd));
|
|
739
|
+
}
|
|
740
|
+
};
|
|
741
|
+
|
|
569
742
|
// src/widgets/cost-widget.ts
|
|
570
743
|
var CostWidget = class extends StdinDataWidget {
|
|
571
744
|
id = "cost";
|
|
@@ -577,12 +750,71 @@ var CostWidget = class extends StdinDataWidget {
|
|
|
577
750
|
0
|
|
578
751
|
// First line
|
|
579
752
|
);
|
|
580
|
-
|
|
753
|
+
styleFn = costStyles.balanced;
|
|
754
|
+
setStyle(style = "balanced") {
|
|
755
|
+
const fn = costStyles[style];
|
|
756
|
+
if (fn) {
|
|
757
|
+
this.styleFn = fn;
|
|
758
|
+
}
|
|
759
|
+
}
|
|
760
|
+
renderWithData(data, _context) {
|
|
581
761
|
if (!data.cost || data.cost.total_cost_usd === void 0) return null;
|
|
582
|
-
|
|
762
|
+
const renderData = {
|
|
763
|
+
costUsd: data.cost.total_cost_usd
|
|
764
|
+
};
|
|
765
|
+
return this.styleFn(renderData);
|
|
583
766
|
}
|
|
584
767
|
};
|
|
585
768
|
|
|
769
|
+
// src/widgets/lines/styles.ts
|
|
770
|
+
function createLinesStyles(colors) {
|
|
771
|
+
return {
|
|
772
|
+
balanced: (data) => {
|
|
773
|
+
const addedStr = colorize(`+${data.added}`, colors.added);
|
|
774
|
+
const removedStr = colorize(`-${data.removed}`, colors.removed);
|
|
775
|
+
return `${addedStr}/${removedStr}`;
|
|
776
|
+
},
|
|
777
|
+
compact: (data) => {
|
|
778
|
+
const addedStr = colorize(`+${data.added}`, colors.added);
|
|
779
|
+
const removedStr = colorize(`-${data.removed}`, colors.removed);
|
|
780
|
+
return `${addedStr}${removedStr}`;
|
|
781
|
+
},
|
|
782
|
+
playful: (data) => {
|
|
783
|
+
const addedStr = colorize(`\u2795${data.added}`, colors.added);
|
|
784
|
+
const removedStr = colorize(`\u2796${data.removed}`, colors.removed);
|
|
785
|
+
return `${addedStr} ${removedStr}`;
|
|
786
|
+
},
|
|
787
|
+
verbose: (data) => {
|
|
788
|
+
const parts = [];
|
|
789
|
+
if (data.added > 0) {
|
|
790
|
+
parts.push(colorize(`+${data.added} added`, colors.added));
|
|
791
|
+
}
|
|
792
|
+
if (data.removed > 0) {
|
|
793
|
+
parts.push(colorize(`-${data.removed} removed`, colors.removed));
|
|
794
|
+
}
|
|
795
|
+
return parts.join(", ");
|
|
796
|
+
},
|
|
797
|
+
labeled: (data) => {
|
|
798
|
+
const addedStr = colorize(`+${data.added}`, colors.added);
|
|
799
|
+
const removedStr = colorize(`-${data.removed}`, colors.removed);
|
|
800
|
+
const lines = `${addedStr}/${removedStr}`;
|
|
801
|
+
return withLabel("Lines", lines);
|
|
802
|
+
},
|
|
803
|
+
indicator: (data) => {
|
|
804
|
+
const addedStr = colorize(`+${data.added}`, colors.added);
|
|
805
|
+
const removedStr = colorize(`-${data.removed}`, colors.removed);
|
|
806
|
+
const lines = `${addedStr}/${removedStr}`;
|
|
807
|
+
return withIndicator(lines);
|
|
808
|
+
},
|
|
809
|
+
fancy: (data) => {
|
|
810
|
+
const addedStr = colorize(`+${data.added}`, colors.added);
|
|
811
|
+
const removedStr = colorize(`-${data.removed}`, colors.removed);
|
|
812
|
+
const lines = `${addedStr}|${removedStr}`;
|
|
813
|
+
return withAngleBrackets(lines);
|
|
814
|
+
}
|
|
815
|
+
};
|
|
816
|
+
}
|
|
817
|
+
|
|
586
818
|
// src/widgets/lines-widget.ts
|
|
587
819
|
var LinesWidget = class extends StdinDataWidget {
|
|
588
820
|
id = "lines";
|
|
@@ -595,16 +827,62 @@ var LinesWidget = class extends StdinDataWidget {
|
|
|
595
827
|
// First line
|
|
596
828
|
);
|
|
597
829
|
colors;
|
|
830
|
+
linesStyles;
|
|
831
|
+
styleFn;
|
|
598
832
|
constructor(colors) {
|
|
599
833
|
super();
|
|
600
834
|
this.colors = colors ?? DEFAULT_THEME.lines;
|
|
835
|
+
this.linesStyles = createLinesStyles(this.colors);
|
|
836
|
+
this.styleFn = this.linesStyles.balanced;
|
|
837
|
+
}
|
|
838
|
+
setStyle(style = "balanced") {
|
|
839
|
+
const fn = this.linesStyles[style];
|
|
840
|
+
if (fn) {
|
|
841
|
+
this.styleFn = fn;
|
|
842
|
+
}
|
|
601
843
|
}
|
|
602
|
-
renderWithData(data,
|
|
844
|
+
renderWithData(data, _context) {
|
|
603
845
|
const added = data.cost?.total_lines_added ?? 0;
|
|
604
846
|
const removed = data.cost?.total_lines_removed ?? 0;
|
|
605
|
-
const
|
|
606
|
-
|
|
607
|
-
|
|
847
|
+
const renderData = { added, removed };
|
|
848
|
+
return this.styleFn(renderData);
|
|
849
|
+
}
|
|
850
|
+
};
|
|
851
|
+
|
|
852
|
+
// src/widgets/duration/styles.ts
|
|
853
|
+
var durationStyles = {
|
|
854
|
+
balanced: (data) => {
|
|
855
|
+
return formatDuration(data.durationMs);
|
|
856
|
+
},
|
|
857
|
+
compact: (data) => {
|
|
858
|
+
const totalSeconds = Math.floor(data.durationMs / 1e3);
|
|
859
|
+
const hours = Math.floor(totalSeconds / 3600);
|
|
860
|
+
const minutes = Math.floor(totalSeconds % 3600 / 60);
|
|
861
|
+
if (hours > 0) {
|
|
862
|
+
return `${hours}h${minutes}m`;
|
|
863
|
+
}
|
|
864
|
+
return `${minutes}m`;
|
|
865
|
+
},
|
|
866
|
+
playful: (data) => {
|
|
867
|
+
const totalSeconds = Math.floor(data.durationMs / 1e3);
|
|
868
|
+
const hours = Math.floor(totalSeconds / 3600);
|
|
869
|
+
const minutes = Math.floor(totalSeconds % 3600 / 60);
|
|
870
|
+
if (hours > 0) {
|
|
871
|
+
return `\u231B ${hours}h ${minutes}m`;
|
|
872
|
+
}
|
|
873
|
+
return `\u231B ${minutes}m`;
|
|
874
|
+
},
|
|
875
|
+
technical: (data) => {
|
|
876
|
+
return `${Math.floor(data.durationMs)}ms`;
|
|
877
|
+
},
|
|
878
|
+
labeled: (data) => {
|
|
879
|
+
return withLabel("Time", formatDuration(data.durationMs));
|
|
880
|
+
},
|
|
881
|
+
indicator: (data) => {
|
|
882
|
+
return withIndicator(formatDuration(data.durationMs));
|
|
883
|
+
},
|
|
884
|
+
fancy: (data) => {
|
|
885
|
+
return withAngleBrackets(formatDuration(data.durationMs));
|
|
608
886
|
}
|
|
609
887
|
};
|
|
610
888
|
|
|
@@ -619,9 +897,80 @@ var DurationWidget = class extends StdinDataWidget {
|
|
|
619
897
|
0
|
|
620
898
|
// First line
|
|
621
899
|
);
|
|
622
|
-
|
|
900
|
+
styleFn = durationStyles.balanced;
|
|
901
|
+
setStyle(style = "balanced") {
|
|
902
|
+
const fn = durationStyles[style];
|
|
903
|
+
if (fn) {
|
|
904
|
+
this.styleFn = fn;
|
|
905
|
+
}
|
|
906
|
+
}
|
|
907
|
+
renderWithData(data, _context) {
|
|
623
908
|
if (!data.cost || data.cost.total_duration_ms === void 0) return null;
|
|
624
|
-
|
|
909
|
+
const renderData = {
|
|
910
|
+
durationMs: data.cost.total_duration_ms
|
|
911
|
+
};
|
|
912
|
+
return this.styleFn(renderData);
|
|
913
|
+
}
|
|
914
|
+
};
|
|
915
|
+
|
|
916
|
+
// src/widgets/git-changes/styles.ts
|
|
917
|
+
var gitChangesStyles = {
|
|
918
|
+
balanced: (data) => {
|
|
919
|
+
const parts = [];
|
|
920
|
+
if (data.insertions > 0) parts.push(`+${data.insertions}`);
|
|
921
|
+
if (data.deletions > 0) parts.push(`-${data.deletions}`);
|
|
922
|
+
return parts.join(" ");
|
|
923
|
+
},
|
|
924
|
+
compact: (data) => {
|
|
925
|
+
const parts = [];
|
|
926
|
+
if (data.insertions > 0) parts.push(`+${data.insertions}`);
|
|
927
|
+
if (data.deletions > 0) parts.push(`-${data.deletions}`);
|
|
928
|
+
return parts.join("/");
|
|
929
|
+
},
|
|
930
|
+
playful: (data) => {
|
|
931
|
+
const parts = [];
|
|
932
|
+
if (data.insertions > 0) parts.push(`\u2B06${data.insertions}`);
|
|
933
|
+
if (data.deletions > 0) parts.push(`\u2B07${data.deletions}`);
|
|
934
|
+
return parts.join(" ");
|
|
935
|
+
},
|
|
936
|
+
verbose: (data) => {
|
|
937
|
+
const parts = [];
|
|
938
|
+
if (data.insertions > 0) parts.push(`+${data.insertions} insertions`);
|
|
939
|
+
if (data.deletions > 0) parts.push(`-${data.deletions} deletions`);
|
|
940
|
+
return parts.join(", ");
|
|
941
|
+
},
|
|
942
|
+
technical: (data) => {
|
|
943
|
+
const parts = [];
|
|
944
|
+
if (data.insertions > 0) parts.push(`${data.insertions}`);
|
|
945
|
+
if (data.deletions > 0) parts.push(`${data.deletions}`);
|
|
946
|
+
return parts.join("/");
|
|
947
|
+
},
|
|
948
|
+
symbolic: (data) => {
|
|
949
|
+
const parts = [];
|
|
950
|
+
if (data.insertions > 0) parts.push(`\u25B2${data.insertions}`);
|
|
951
|
+
if (data.deletions > 0) parts.push(`\u25BC${data.deletions}`);
|
|
952
|
+
return parts.join(" ");
|
|
953
|
+
},
|
|
954
|
+
labeled: (data) => {
|
|
955
|
+
const parts = [];
|
|
956
|
+
if (data.insertions > 0) parts.push(`+${data.insertions}`);
|
|
957
|
+
if (data.deletions > 0) parts.push(`-${data.deletions}`);
|
|
958
|
+
const changes = parts.join(" ");
|
|
959
|
+
return withLabel("Diff", changes);
|
|
960
|
+
},
|
|
961
|
+
indicator: (data) => {
|
|
962
|
+
const parts = [];
|
|
963
|
+
if (data.insertions > 0) parts.push(`+${data.insertions}`);
|
|
964
|
+
if (data.deletions > 0) parts.push(`-${data.deletions}`);
|
|
965
|
+
const changes = parts.join(" ");
|
|
966
|
+
return withIndicator(changes);
|
|
967
|
+
},
|
|
968
|
+
fancy: (data) => {
|
|
969
|
+
const parts = [];
|
|
970
|
+
if (data.insertions > 0) parts.push(`+${data.insertions}`);
|
|
971
|
+
if (data.deletions > 0) parts.push(`-${data.deletions}`);
|
|
972
|
+
const changes = parts.join("|");
|
|
973
|
+
return withAngleBrackets(changes);
|
|
625
974
|
}
|
|
626
975
|
};
|
|
627
976
|
|
|
@@ -640,6 +989,7 @@ var GitChangesWidget = class {
|
|
|
640
989
|
git = null;
|
|
641
990
|
enabled = true;
|
|
642
991
|
cwd = null;
|
|
992
|
+
styleFn = gitChangesStyles.balanced;
|
|
643
993
|
/**
|
|
644
994
|
* @param gitFactory - Optional factory function for creating IGit instances
|
|
645
995
|
* If not provided, uses default createGit (production)
|
|
@@ -648,6 +998,12 @@ var GitChangesWidget = class {
|
|
|
648
998
|
constructor(gitFactory) {
|
|
649
999
|
this.gitFactory = gitFactory || createGit;
|
|
650
1000
|
}
|
|
1001
|
+
setStyle(style = "balanced") {
|
|
1002
|
+
const fn = gitChangesStyles[style];
|
|
1003
|
+
if (fn) {
|
|
1004
|
+
this.styleFn = fn;
|
|
1005
|
+
}
|
|
1006
|
+
}
|
|
651
1007
|
async initialize(context) {
|
|
652
1008
|
this.enabled = context.config?.enabled !== false;
|
|
653
1009
|
}
|
|
@@ -687,10 +1043,8 @@ var GitChangesWidget = class {
|
|
|
687
1043
|
if (changes.insertions === 0 && changes.deletions === 0) {
|
|
688
1044
|
return null;
|
|
689
1045
|
}
|
|
690
|
-
const
|
|
691
|
-
|
|
692
|
-
if (changes.deletions > 0) parts.push(`-${changes.deletions}`);
|
|
693
|
-
return parts.join(",");
|
|
1046
|
+
const renderData = changes;
|
|
1047
|
+
return this.styleFn(renderData);
|
|
694
1048
|
}
|
|
695
1049
|
isEnabled() {
|
|
696
1050
|
return this.enabled;
|
|
@@ -846,6 +1200,82 @@ var ConfigProvider = class {
|
|
|
846
1200
|
}
|
|
847
1201
|
};
|
|
848
1202
|
|
|
1203
|
+
// src/widgets/config-count/styles.ts
|
|
1204
|
+
var configCountStyles = {
|
|
1205
|
+
balanced: (data) => {
|
|
1206
|
+
const { claudeMdCount, rulesCount, mcpCount, hooksCount } = data;
|
|
1207
|
+
const parts = [];
|
|
1208
|
+
if (claudeMdCount > 0) {
|
|
1209
|
+
parts.push(`CLAUDE.md:${claudeMdCount}`);
|
|
1210
|
+
}
|
|
1211
|
+
if (rulesCount > 0) {
|
|
1212
|
+
parts.push(`rules:${rulesCount}`);
|
|
1213
|
+
}
|
|
1214
|
+
if (mcpCount > 0) {
|
|
1215
|
+
parts.push(`MCPs:${mcpCount}`);
|
|
1216
|
+
}
|
|
1217
|
+
if (hooksCount > 0) {
|
|
1218
|
+
parts.push(`hooks:${hooksCount}`);
|
|
1219
|
+
}
|
|
1220
|
+
return parts.join(" \u2502 ");
|
|
1221
|
+
},
|
|
1222
|
+
compact: (data) => {
|
|
1223
|
+
const { claudeMdCount, rulesCount, mcpCount, hooksCount } = data;
|
|
1224
|
+
const parts = [];
|
|
1225
|
+
if (claudeMdCount > 0) {
|
|
1226
|
+
parts.push(`${claudeMdCount} docs`);
|
|
1227
|
+
}
|
|
1228
|
+
if (rulesCount > 0) {
|
|
1229
|
+
parts.push(`${rulesCount} rules`);
|
|
1230
|
+
}
|
|
1231
|
+
if (mcpCount > 0) {
|
|
1232
|
+
parts.push(`${mcpCount} MCPs`);
|
|
1233
|
+
}
|
|
1234
|
+
if (hooksCount > 0) {
|
|
1235
|
+
const hookLabel = hooksCount === 1 ? "hook" : "hooks";
|
|
1236
|
+
parts.push(`${hooksCount} ${hookLabel}`);
|
|
1237
|
+
}
|
|
1238
|
+
return parts.join(" \u2502 ");
|
|
1239
|
+
},
|
|
1240
|
+
playful: (data) => {
|
|
1241
|
+
const { claudeMdCount, rulesCount, mcpCount, hooksCount } = data;
|
|
1242
|
+
const parts = [];
|
|
1243
|
+
if (claudeMdCount > 0) {
|
|
1244
|
+
parts.push(`\u{1F4C4} CLAUDE.md:${claudeMdCount}`);
|
|
1245
|
+
}
|
|
1246
|
+
if (rulesCount > 0) {
|
|
1247
|
+
parts.push(`\u{1F4DC} rules:${rulesCount}`);
|
|
1248
|
+
}
|
|
1249
|
+
if (mcpCount > 0) {
|
|
1250
|
+
parts.push(`\u{1F50C} MCPs:${mcpCount}`);
|
|
1251
|
+
}
|
|
1252
|
+
if (hooksCount > 0) {
|
|
1253
|
+
parts.push(`\u{1FA9D} hooks:${hooksCount}`);
|
|
1254
|
+
}
|
|
1255
|
+
return parts.join(" \u2502 ");
|
|
1256
|
+
},
|
|
1257
|
+
verbose: (data) => {
|
|
1258
|
+
const { claudeMdCount, rulesCount, mcpCount, hooksCount } = data;
|
|
1259
|
+
const parts = [];
|
|
1260
|
+
if (claudeMdCount > 0) {
|
|
1261
|
+
parts.push(`${claudeMdCount} CLAUDE.md`);
|
|
1262
|
+
}
|
|
1263
|
+
if (rulesCount > 0) {
|
|
1264
|
+
parts.push(`${rulesCount} rules`);
|
|
1265
|
+
}
|
|
1266
|
+
if (mcpCount > 0) {
|
|
1267
|
+
parts.push(`${mcpCount} MCP servers`);
|
|
1268
|
+
}
|
|
1269
|
+
if (hooksCount > 0) {
|
|
1270
|
+
parts.push(`${hooksCount} hook`);
|
|
1271
|
+
}
|
|
1272
|
+
return parts.join(" \u2502 ");
|
|
1273
|
+
}
|
|
1274
|
+
};
|
|
1275
|
+
|
|
1276
|
+
// src/core/style-types.ts
|
|
1277
|
+
var DEFAULT_WIDGET_STYLE = "balanced";
|
|
1278
|
+
|
|
849
1279
|
// src/widgets/config-count-widget.ts
|
|
850
1280
|
var ConfigCountWidget = class {
|
|
851
1281
|
id = "config-count";
|
|
@@ -860,6 +1290,13 @@ var ConfigCountWidget = class {
|
|
|
860
1290
|
configProvider = new ConfigProvider();
|
|
861
1291
|
configs;
|
|
862
1292
|
cwd;
|
|
1293
|
+
styleFn = configCountStyles.balanced;
|
|
1294
|
+
setStyle(style = DEFAULT_WIDGET_STYLE) {
|
|
1295
|
+
const fn = configCountStyles[style];
|
|
1296
|
+
if (fn) {
|
|
1297
|
+
this.styleFn = fn;
|
|
1298
|
+
}
|
|
1299
|
+
}
|
|
863
1300
|
async initialize() {
|
|
864
1301
|
}
|
|
865
1302
|
async update(data) {
|
|
@@ -878,20 +1315,13 @@ var ConfigCountWidget = class {
|
|
|
878
1315
|
return null;
|
|
879
1316
|
}
|
|
880
1317
|
const { claudeMdCount, rulesCount, mcpCount, hooksCount } = this.configs;
|
|
881
|
-
const
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
if (mcpCount > 0) {
|
|
889
|
-
parts.push(`\u{1F50C} ${mcpCount} MCPs`);
|
|
890
|
-
}
|
|
891
|
-
if (hooksCount > 0) {
|
|
892
|
-
parts.push(`\u{1FA9D} ${hooksCount} hooks`);
|
|
893
|
-
}
|
|
894
|
-
return parts.join(" \u2502 ") || null;
|
|
1318
|
+
const renderData = {
|
|
1319
|
+
claudeMdCount,
|
|
1320
|
+
rulesCount,
|
|
1321
|
+
mcpCount,
|
|
1322
|
+
hooksCount
|
|
1323
|
+
};
|
|
1324
|
+
return this.styleFn(renderData);
|
|
895
1325
|
}
|
|
896
1326
|
async cleanup() {
|
|
897
1327
|
}
|
|
@@ -942,10 +1372,10 @@ function getRankValue(rank) {
|
|
|
942
1372
|
"8": 8,
|
|
943
1373
|
"9": 9,
|
|
944
1374
|
"10": 10,
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
1375
|
+
J: 11,
|
|
1376
|
+
Q: 12,
|
|
1377
|
+
K: 13,
|
|
1378
|
+
A: 14
|
|
949
1379
|
};
|
|
950
1380
|
return values[rank];
|
|
951
1381
|
}
|
|
@@ -1246,7 +1676,11 @@ function evaluateHand(hole, board) {
|
|
|
1246
1676
|
const sfHighCard = getStraightFlushHighCard(allCards, flushSuit);
|
|
1247
1677
|
if (sfHighCard === 14) {
|
|
1248
1678
|
const participatingCards = getStraightFlushIndices(allCards, 14, flushSuit);
|
|
1249
|
-
return {
|
|
1679
|
+
return {
|
|
1680
|
+
rank: 10 /* RoyalFlush */,
|
|
1681
|
+
...HAND_DISPLAY[10 /* RoyalFlush */],
|
|
1682
|
+
participatingCards
|
|
1683
|
+
};
|
|
1250
1684
|
}
|
|
1251
1685
|
}
|
|
1252
1686
|
if (flush) {
|
|
@@ -1254,13 +1688,21 @@ function evaluateHand(hole, board) {
|
|
|
1254
1688
|
const sfHighCard = getStraightFlushHighCard(allCards, flushSuit);
|
|
1255
1689
|
if (sfHighCard !== null) {
|
|
1256
1690
|
const participatingCards = getStraightFlushIndices(allCards, sfHighCard, flushSuit);
|
|
1257
|
-
return {
|
|
1691
|
+
return {
|
|
1692
|
+
rank: 9 /* StraightFlush */,
|
|
1693
|
+
...HAND_DISPLAY[9 /* StraightFlush */],
|
|
1694
|
+
participatingCards
|
|
1695
|
+
};
|
|
1258
1696
|
}
|
|
1259
1697
|
}
|
|
1260
1698
|
if (maxCount === 4) {
|
|
1261
1699
|
const rank = getMostCommonRank(allCards);
|
|
1262
1700
|
const participatingCards = findCardsOfRank(allCards, rank);
|
|
1263
|
-
return {
|
|
1701
|
+
return {
|
|
1702
|
+
rank: 8 /* FourOfAKind */,
|
|
1703
|
+
...HAND_DISPLAY[8 /* FourOfAKind */],
|
|
1704
|
+
participatingCards
|
|
1705
|
+
};
|
|
1264
1706
|
}
|
|
1265
1707
|
if (maxCount === 3 && pairCount >= 1) {
|
|
1266
1708
|
const participatingCards = getFullHouseIndices(allCards);
|
|
@@ -1279,7 +1721,11 @@ function evaluateHand(hole, board) {
|
|
|
1279
1721
|
if (maxCount === 3) {
|
|
1280
1722
|
const rank = getMostCommonRank(allCards);
|
|
1281
1723
|
const participatingCards = findCardsOfRank(allCards, rank);
|
|
1282
|
-
return {
|
|
1724
|
+
return {
|
|
1725
|
+
rank: 4 /* ThreeOfAKind */,
|
|
1726
|
+
...HAND_DISPLAY[4 /* ThreeOfAKind */],
|
|
1727
|
+
participatingCards
|
|
1728
|
+
};
|
|
1283
1729
|
}
|
|
1284
1730
|
if (pairCount >= 2) {
|
|
1285
1731
|
const [rank1, rank2] = getTwoPairRanks(allCards);
|
|
@@ -1294,9 +1740,101 @@ function evaluateHand(hole, board) {
|
|
|
1294
1740
|
return { rank: 2 /* OnePair */, ...HAND_DISPLAY[2 /* OnePair */], participatingCards };
|
|
1295
1741
|
}
|
|
1296
1742
|
const highestIdx = getHighestCardIndex(allCards);
|
|
1297
|
-
return {
|
|
1743
|
+
return {
|
|
1744
|
+
rank: 1 /* HighCard */,
|
|
1745
|
+
...HAND_DISPLAY[1 /* HighCard */],
|
|
1746
|
+
participatingCards: [highestIdx]
|
|
1747
|
+
};
|
|
1298
1748
|
}
|
|
1299
1749
|
|
|
1750
|
+
// src/widgets/poker/styles.ts
|
|
1751
|
+
var HAND_ABBREVIATIONS = {
|
|
1752
|
+
"Royal Flush": "RF",
|
|
1753
|
+
"Straight Flush": "SF",
|
|
1754
|
+
"Four of a Kind": "4K",
|
|
1755
|
+
"Full House": "FH",
|
|
1756
|
+
"Flush": "FL",
|
|
1757
|
+
"Straight": "ST",
|
|
1758
|
+
"Three of a Kind": "3K",
|
|
1759
|
+
"Two Pair": "2P",
|
|
1760
|
+
"One Pair": "1P",
|
|
1761
|
+
"High Card": "HC",
|
|
1762
|
+
"Nothing": "\u2014"
|
|
1763
|
+
};
|
|
1764
|
+
function formatCardByParticipation(cardData, isParticipating) {
|
|
1765
|
+
const color = isRedSuit(cardData.card.suit) ? red : gray;
|
|
1766
|
+
const cardText = formatCard(cardData.card);
|
|
1767
|
+
if (isParticipating) {
|
|
1768
|
+
return `${color}${bold}(${cardText})${reset} `;
|
|
1769
|
+
} else {
|
|
1770
|
+
return `${color}${cardText}${reset} `;
|
|
1771
|
+
}
|
|
1772
|
+
}
|
|
1773
|
+
function formatCardCompact(cardData, isParticipating) {
|
|
1774
|
+
const color = isRedSuit(cardData.card.suit) ? red : gray;
|
|
1775
|
+
const cardText = formatCardTextCompact(cardData.card);
|
|
1776
|
+
if (isParticipating) {
|
|
1777
|
+
return `${color}${bold}(${cardText})${reset}`;
|
|
1778
|
+
} else {
|
|
1779
|
+
return `${color}${cardText}${reset}`;
|
|
1780
|
+
}
|
|
1781
|
+
}
|
|
1782
|
+
function formatCardTextCompact(card) {
|
|
1783
|
+
const rankSymbols = {
|
|
1784
|
+
"10": "T",
|
|
1785
|
+
"11": "J",
|
|
1786
|
+
"12": "Q",
|
|
1787
|
+
"13": "K",
|
|
1788
|
+
"14": "A"
|
|
1789
|
+
};
|
|
1790
|
+
const rank = String(card.rank);
|
|
1791
|
+
const rankSymbol = rankSymbols[rank] ?? rank;
|
|
1792
|
+
return `${rankSymbol}${card.suit}`;
|
|
1793
|
+
}
|
|
1794
|
+
function formatHandResult(handResult) {
|
|
1795
|
+
if (!handResult) {
|
|
1796
|
+
return "\u2014";
|
|
1797
|
+
}
|
|
1798
|
+
const playerParticipates = handResult.participatingIndices.some((idx) => idx < 2);
|
|
1799
|
+
if (!playerParticipates) {
|
|
1800
|
+
return `Nothing \u{1F0CF}`;
|
|
1801
|
+
} else {
|
|
1802
|
+
return `${handResult.name}! ${handResult.emoji}`;
|
|
1803
|
+
}
|
|
1804
|
+
}
|
|
1805
|
+
function getHandAbbreviation(handResult) {
|
|
1806
|
+
if (!handResult) {
|
|
1807
|
+
return "\u2014 (\u2014)";
|
|
1808
|
+
}
|
|
1809
|
+
const abbreviation = HAND_ABBREVIATIONS[handResult.name] ?? "\u2014";
|
|
1810
|
+
return `${abbreviation} (${handResult.name})`;
|
|
1811
|
+
}
|
|
1812
|
+
var pokerStyles = {
|
|
1813
|
+
balanced: (data) => {
|
|
1814
|
+
const { holeCards, boardCards, handResult } = data;
|
|
1815
|
+
const participatingSet = new Set(handResult?.participatingIndices || []);
|
|
1816
|
+
const handStr = holeCards.map((hc, idx) => formatCardByParticipation(hc, participatingSet.has(idx))).join("");
|
|
1817
|
+
const boardStr = boardCards.map((bc, idx) => formatCardByParticipation(bc, participatingSet.has(idx + 2))).join("");
|
|
1818
|
+
const handLabel = colorize("Hand:", lightGray);
|
|
1819
|
+
const boardLabel = colorize("Board:", lightGray);
|
|
1820
|
+
return `${handLabel} ${handStr}| ${boardLabel} ${boardStr}\u2192 ${formatHandResult(handResult)}`;
|
|
1821
|
+
},
|
|
1822
|
+
compact: (data) => {
|
|
1823
|
+
return pokerStyles.balanced(data);
|
|
1824
|
+
},
|
|
1825
|
+
playful: (data) => {
|
|
1826
|
+
return pokerStyles.balanced(data);
|
|
1827
|
+
},
|
|
1828
|
+
"compact-verbose": (data) => {
|
|
1829
|
+
const { holeCards, boardCards, handResult } = data;
|
|
1830
|
+
const participatingSet = new Set(handResult?.participatingIndices || []);
|
|
1831
|
+
const handStr = holeCards.map((hc, idx) => formatCardCompact(hc, participatingSet.has(idx))).join("");
|
|
1832
|
+
const boardStr = boardCards.map((bc, idx) => formatCardCompact(bc, participatingSet.has(idx + 2))).join("");
|
|
1833
|
+
const abbreviation = getHandAbbreviation(handResult);
|
|
1834
|
+
return `${handStr}| ${boardStr}\u2192 ${abbreviation}`;
|
|
1835
|
+
}
|
|
1836
|
+
};
|
|
1837
|
+
|
|
1300
1838
|
// src/widgets/poker-widget.ts
|
|
1301
1839
|
var PokerWidget = class extends StdinDataWidget {
|
|
1302
1840
|
id = "poker";
|
|
@@ -1314,8 +1852,12 @@ var PokerWidget = class extends StdinDataWidget {
|
|
|
1314
1852
|
lastUpdateTimestamp = 0;
|
|
1315
1853
|
THROTTLE_MS = 5e3;
|
|
1316
1854
|
// 5 seconds
|
|
1317
|
-
|
|
1318
|
-
|
|
1855
|
+
styleFn = pokerStyles.balanced;
|
|
1856
|
+
setStyle(style = DEFAULT_WIDGET_STYLE) {
|
|
1857
|
+
const fn = pokerStyles[style];
|
|
1858
|
+
if (fn) {
|
|
1859
|
+
this.styleFn = fn;
|
|
1860
|
+
}
|
|
1319
1861
|
}
|
|
1320
1862
|
/**
|
|
1321
1863
|
* Generate new poker hand on each update
|
|
@@ -1356,30 +1898,37 @@ var PokerWidget = class extends StdinDataWidget {
|
|
|
1356
1898
|
* Format card with appropriate color (red for ♥♦, gray for ♠♣)
|
|
1357
1899
|
*/
|
|
1358
1900
|
formatCardColor(card) {
|
|
1359
|
-
const color = isRedSuit(card.suit) ? red : gray;
|
|
1360
|
-
return
|
|
1361
|
-
}
|
|
1362
|
-
/**
|
|
1363
|
-
* Format card based on participation in best hand
|
|
1364
|
-
* Participating cards: (K♠) with color + BOLD
|
|
1365
|
-
* Non-participating cards: K♠ with color, no brackets
|
|
1366
|
-
*/
|
|
1367
|
-
formatCardByParticipation(cardData, isParticipating) {
|
|
1368
|
-
const color = isRedSuit(cardData.card.suit) ? red : gray;
|
|
1369
|
-
const cardText = formatCard(cardData.card);
|
|
1370
|
-
if (isParticipating) {
|
|
1371
|
-
return `${color}${bold}(${cardText})${reset} `;
|
|
1372
|
-
} else {
|
|
1373
|
-
return `${color}${cardText}${reset} `;
|
|
1374
|
-
}
|
|
1901
|
+
const color = isRedSuit(card.suit) ? "red" : "gray";
|
|
1902
|
+
return formatCard(card);
|
|
1375
1903
|
}
|
|
1376
1904
|
renderWithData(_data, _context) {
|
|
1377
|
-
const
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
const
|
|
1382
|
-
|
|
1905
|
+
const holeCardsData = this.holeCards.map((hc, idx) => ({
|
|
1906
|
+
card: hc.card,
|
|
1907
|
+
isParticipating: (this.handResult?.participatingIndices || []).includes(idx)
|
|
1908
|
+
}));
|
|
1909
|
+
const boardCardsData = this.boardCards.map((bc, idx) => ({
|
|
1910
|
+
card: bc.card,
|
|
1911
|
+
isParticipating: (this.handResult?.participatingIndices || []).includes(idx + 2)
|
|
1912
|
+
}));
|
|
1913
|
+
const handResult = this.handResult ? {
|
|
1914
|
+
name: this.getHandName(this.handResult.text),
|
|
1915
|
+
emoji: this.getHandEmoji(this.handResult.text),
|
|
1916
|
+
participatingIndices: this.handResult.participatingIndices
|
|
1917
|
+
} : null;
|
|
1918
|
+
const renderData = {
|
|
1919
|
+
holeCards: holeCardsData,
|
|
1920
|
+
boardCards: boardCardsData,
|
|
1921
|
+
handResult
|
|
1922
|
+
};
|
|
1923
|
+
return this.styleFn(renderData);
|
|
1924
|
+
}
|
|
1925
|
+
getHandName(text) {
|
|
1926
|
+
const match = text.match(/^([^!]+)/);
|
|
1927
|
+
return match ? match[1].trim() : "Nothing";
|
|
1928
|
+
}
|
|
1929
|
+
getHandEmoji(text) {
|
|
1930
|
+
const match = text.match(/([🃏♠️♥️♦️♣️🎉✨🌟])/);
|
|
1931
|
+
return match ? match[1] : "\u{1F0CF}";
|
|
1383
1932
|
}
|
|
1384
1933
|
};
|
|
1385
1934
|
|
|
@@ -1395,11 +1944,17 @@ var EmptyLineWidget = class extends StdinDataWidget {
|
|
|
1395
1944
|
// Fourth line (0-indexed)
|
|
1396
1945
|
);
|
|
1397
1946
|
/**
|
|
1398
|
-
*
|
|
1399
|
-
*
|
|
1947
|
+
* All styles return the same value (Braille Pattern Blank).
|
|
1948
|
+
* This method exists for API consistency with other widgets.
|
|
1949
|
+
*/
|
|
1950
|
+
setStyle(_style) {
|
|
1951
|
+
}
|
|
1952
|
+
/**
|
|
1953
|
+
* Return Braille Pattern Blank to create a visible empty separator line.
|
|
1954
|
+
* U+2800 occupies cell width but appears blank, ensuring the line renders.
|
|
1400
1955
|
*/
|
|
1401
1956
|
renderWithData(_data, _context) {
|
|
1402
|
-
return "
|
|
1957
|
+
return "\u2800";
|
|
1403
1958
|
}
|
|
1404
1959
|
};
|
|
1405
1960
|
|
|
@@ -1558,9 +2113,7 @@ var StdinProvider = class {
|
|
|
1558
2113
|
}
|
|
1559
2114
|
const result = StdinDataSchema.validate(data);
|
|
1560
2115
|
if (!result.success) {
|
|
1561
|
-
throw new StdinValidationError(
|
|
1562
|
-
`Validation failed: ${formatError(result.error)}`
|
|
1563
|
-
);
|
|
2116
|
+
throw new StdinValidationError(`Validation failed: ${formatError(result.error)}`);
|
|
1564
2117
|
}
|
|
1565
2118
|
return result.data;
|
|
1566
2119
|
}
|
|
@@ -1618,10 +2171,10 @@ async function main() {
|
|
|
1618
2171
|
for (const widget of registry.getAll()) {
|
|
1619
2172
|
await widget.update(stdinData);
|
|
1620
2173
|
}
|
|
1621
|
-
const lines = await renderer.render(
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
);
|
|
2174
|
+
const lines = await renderer.render(registry.getEnabledWidgets(), {
|
|
2175
|
+
width: 80,
|
|
2176
|
+
timestamp: Date.now()
|
|
2177
|
+
});
|
|
1625
2178
|
return lines.join("\n");
|
|
1626
2179
|
} catch (error) {
|
|
1627
2180
|
const fallback = await tryGitFallback();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-scope",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.5",
|
|
4
4
|
"description": "Claude Code plugin for session status and analytics",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -28,6 +28,7 @@
|
|
|
28
28
|
"dev": "tsx src/index.ts"
|
|
29
29
|
},
|
|
30
30
|
"devDependencies": {
|
|
31
|
+
"@biomejs/biome": "^2.3.11",
|
|
31
32
|
"@types/node": "^22.10.2",
|
|
32
33
|
"c8": "^10.1.3",
|
|
33
34
|
"chai": "^6.2.2",
|