terminal-richjs 0.1.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/dist/index.js ADDED
@@ -0,0 +1,2674 @@
1
+ import process2 from 'process';
2
+ import wrapAnsi from 'wrap-ansi';
3
+ import terminalSize from 'terminal-size';
4
+ import os from 'os';
5
+ import stringWidth3 from 'string-width';
6
+ import chalk from 'chalk';
7
+ import tinycolor from 'tinycolor2';
8
+ import fs from 'fs';
9
+ import hljs from 'highlight.js';
10
+ import ansiEscapes from 'ansi-escapes';
11
+ import cliSpinners from 'cli-spinners';
12
+ import boxes from 'cli-boxes';
13
+ import readline from 'readline';
14
+ import { marked } from 'marked';
15
+ import TerminalRenderer from 'marked-terminal';
16
+
17
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
18
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
19
+ }) : x)(function(x) {
20
+ if (typeof require !== "undefined") return require.apply(this, arguments);
21
+ throw Error('Dynamic require of "' + x + '" is not supported');
22
+ });
23
+ var Terminal = class {
24
+ constructor() {
25
+ }
26
+ get width() {
27
+ return terminalSize().columns;
28
+ }
29
+ get height() {
30
+ return terminalSize().rows;
31
+ }
32
+ get isInteractive() {
33
+ return !!process2.stdout.isTTY;
34
+ }
35
+ get isLegacyWindows() {
36
+ return os.platform() === "win32" && !process2.env.WT_SESSION;
37
+ }
38
+ get colorSystem() {
39
+ const env = process2.env;
40
+ if (env.NO_COLOR) return "none";
41
+ if (env.COLORTERM === "truecolor" || env.COLORTERM === "24bit") {
42
+ return "truecolor";
43
+ }
44
+ if (this.isLegacyWindows) {
45
+ return "standard";
46
+ }
47
+ if (env.TERM && env.TERM.includes("256")) {
48
+ return "256";
49
+ }
50
+ return "standard";
51
+ }
52
+ };
53
+ var Style = class _Style {
54
+ color;
55
+ backgroundColor;
56
+ bold;
57
+ italic;
58
+ underline;
59
+ strikethrough;
60
+ dim;
61
+ reverse;
62
+ blink;
63
+ hidden;
64
+ constructor(options = {}) {
65
+ this.color = options.color;
66
+ this.backgroundColor = options.backgroundColor;
67
+ this.bold = options.bold;
68
+ this.italic = options.italic;
69
+ this.underline = options.underline;
70
+ this.strikethrough = options.strikethrough;
71
+ this.dim = options.dim;
72
+ this.reverse = options.reverse;
73
+ this.blink = options.blink;
74
+ this.hidden = options.hidden;
75
+ }
76
+ static null() {
77
+ return new _Style({});
78
+ }
79
+ /**
80
+ * Parse a style string into a Style object.
81
+ * Supports:
82
+ * - Modifiers: bold, italic, underline, dim, strike, reverse, blink, hidden
83
+ * - Named colors: red, green, blue, cyan, magenta, yellow, white, black
84
+ * - Bright colors: bright_red, bright_green, etc.
85
+ * - Hex colors: #ff0000
86
+ * - RGB colors: rgb(255,0,0)
87
+ * - 256 colors: color(196)
88
+ * - Background: on red, on #ff0000, on rgb(255,0,0)
89
+ */
90
+ static parse(styleString) {
91
+ if (!styleString.trim()) return _Style.null();
92
+ const options = {};
93
+ const words = styleString.trim().split(/\s+/);
94
+ let i = 0;
95
+ while (i < words.length) {
96
+ const word = words[i];
97
+ if (word === "bold") {
98
+ options.bold = true;
99
+ i++;
100
+ continue;
101
+ }
102
+ if (word === "italic") {
103
+ options.italic = true;
104
+ i++;
105
+ continue;
106
+ }
107
+ if (word === "underline") {
108
+ options.underline = true;
109
+ i++;
110
+ continue;
111
+ }
112
+ if (word === "strike" || word === "strikethrough") {
113
+ options.strikethrough = true;
114
+ i++;
115
+ continue;
116
+ }
117
+ if (word === "dim") {
118
+ options.dim = true;
119
+ i++;
120
+ continue;
121
+ }
122
+ if (word === "reverse") {
123
+ options.reverse = true;
124
+ i++;
125
+ continue;
126
+ }
127
+ if (word === "blink") {
128
+ options.blink = true;
129
+ i++;
130
+ continue;
131
+ }
132
+ if (word === "hidden") {
133
+ options.hidden = true;
134
+ i++;
135
+ continue;
136
+ }
137
+ if (word === "on") {
138
+ if (i + 1 < words.length) {
139
+ const bgColor = _Style.parseColor(words[i + 1]);
140
+ if (bgColor !== null) {
141
+ options.backgroundColor = bgColor;
142
+ i += 2;
143
+ continue;
144
+ }
145
+ }
146
+ i++;
147
+ continue;
148
+ }
149
+ const color = _Style.parseColor(word);
150
+ if (color !== null) {
151
+ options.color = color;
152
+ i++;
153
+ continue;
154
+ }
155
+ i++;
156
+ }
157
+ return new _Style(options);
158
+ }
159
+ /**
160
+ * Parse a single color value.
161
+ * Supports hex (#ff0000), RGB (rgb(255,0,0)), 256-color (color(196)), and named colors.
162
+ */
163
+ static parseColor(word) {
164
+ if (word.startsWith("#")) {
165
+ if (/^#[0-9a-fA-F]{6}$/.test(word) || /^#[0-9a-fA-F]{3}$/.test(word)) {
166
+ return word;
167
+ }
168
+ return null;
169
+ }
170
+ const rgbMatch = word.match(/^rgb\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$/i);
171
+ if (rgbMatch) {
172
+ return {
173
+ r: Math.min(255, parseInt(rgbMatch[1], 10)),
174
+ g: Math.min(255, parseInt(rgbMatch[2], 10)),
175
+ b: Math.min(255, parseInt(rgbMatch[3], 10))
176
+ };
177
+ }
178
+ const color256Match = word.match(/^color\(\s*(\d+)\s*\)$/i);
179
+ if (color256Match) {
180
+ return Math.min(255, parseInt(color256Match[1], 10));
181
+ }
182
+ const namedColors = [
183
+ "black",
184
+ "red",
185
+ "green",
186
+ "yellow",
187
+ "blue",
188
+ "magenta",
189
+ "cyan",
190
+ "white",
191
+ "gray",
192
+ "grey",
193
+ "blackBright",
194
+ "redBright",
195
+ "greenBright",
196
+ "yellowBright",
197
+ "blueBright",
198
+ "magentaBright",
199
+ "cyanBright",
200
+ "whiteBright",
201
+ // Underscore variants commonly used
202
+ "bright_black",
203
+ "bright_red",
204
+ "bright_green",
205
+ "bright_yellow",
206
+ "bright_blue",
207
+ "bright_magenta",
208
+ "bright_cyan",
209
+ "bright_white"
210
+ ];
211
+ let normalizedWord = word;
212
+ if (word.startsWith("bright_")) {
213
+ const base = word.slice(7);
214
+ normalizedWord = `${base}Bright`;
215
+ }
216
+ if (namedColors.includes(word) || namedColors.includes(normalizedWord)) {
217
+ return word;
218
+ }
219
+ if (/^[a-zA-Z]+$/.test(word)) {
220
+ return word;
221
+ }
222
+ return null;
223
+ }
224
+ combine(other) {
225
+ return new _Style({
226
+ color: other.color ?? this.color,
227
+ backgroundColor: other.backgroundColor ?? this.backgroundColor,
228
+ bold: other.bold ?? this.bold,
229
+ italic: other.italic ?? this.italic,
230
+ underline: other.underline ?? this.underline,
231
+ strikethrough: other.strikethrough ?? this.strikethrough,
232
+ dim: other.dim ?? this.dim,
233
+ reverse: other.reverse ?? this.reverse,
234
+ blink: other.blink ?? this.blink,
235
+ hidden: other.hidden ?? this.hidden
236
+ });
237
+ }
238
+ render(text) {
239
+ let result = chalk;
240
+ if (this.color) {
241
+ result = this.applyColor(result, this.color, false);
242
+ }
243
+ if (this.backgroundColor) {
244
+ result = this.applyColor(result, this.backgroundColor, true);
245
+ }
246
+ if (this.bold) result = result.bold;
247
+ if (this.italic) result = result.italic;
248
+ if (this.underline) result = result.underline;
249
+ if (this.strikethrough) result = result.strikethrough;
250
+ if (this.dim) result = result.dim;
251
+ if (this.reverse) result = result.inverse;
252
+ if (this.blink) result = result.blink;
253
+ if (this.hidden) result = result.hidden;
254
+ return result(text);
255
+ }
256
+ /**
257
+ * Apply a color to a chalk instance.
258
+ */
259
+ applyColor(chalkInstance, color, isBackground) {
260
+ if (typeof color === "string") {
261
+ if (color.startsWith("#")) {
262
+ return isBackground ? chalkInstance.bgHex(color) : chalkInstance.hex(color);
263
+ }
264
+ let colorName = color;
265
+ if (color.startsWith("bright_")) {
266
+ const base = color.slice(7);
267
+ colorName = `${base}Bright`;
268
+ }
269
+ if (isBackground) {
270
+ const bgMethod = `bg${colorName.charAt(0).toUpperCase()}${colorName.slice(1)}`;
271
+ if (bgMethod in chalkInstance) {
272
+ return chalkInstance[bgMethod];
273
+ }
274
+ const altMethod = `bg${color.charAt(0).toUpperCase()}${color.slice(1)}`;
275
+ if (altMethod in chalkInstance) {
276
+ return chalkInstance[altMethod];
277
+ }
278
+ } else {
279
+ if (colorName in chalkInstance) {
280
+ return chalkInstance[colorName];
281
+ }
282
+ if (color in chalkInstance) {
283
+ return chalkInstance[color];
284
+ }
285
+ }
286
+ return chalkInstance;
287
+ }
288
+ if (this.isRGB(color)) {
289
+ return isBackground ? chalkInstance.bgRgb(color.r, color.g, color.b) : chalkInstance.rgb(color.r, color.g, color.b);
290
+ }
291
+ if (typeof color === "number") {
292
+ return isBackground ? chalkInstance.bgAnsi256(color) : chalkInstance.ansi256(color);
293
+ }
294
+ return chalkInstance;
295
+ }
296
+ isRGB(color) {
297
+ return typeof color === "object" && color !== null && "r" in color && "g" in color && "b" in color;
298
+ }
299
+ };
300
+
301
+ // src/core/segment.ts
302
+ var Segment = class _Segment {
303
+ constructor(text, style = Style.null(), isControl = false) {
304
+ this.text = text;
305
+ this.style = style;
306
+ this.isControl = isControl;
307
+ }
308
+ /**
309
+ * Implementation of Renderable protocol.
310
+ */
311
+ __rich_console__(_console, _options) {
312
+ return {
313
+ segments: [this],
314
+ width: this.cellLength()
315
+ };
316
+ }
317
+ /**
318
+ * Calculates the cell length of the text.
319
+ */
320
+ cellLength() {
321
+ if (this.isControl) return 0;
322
+ return stringWidth3(this.text);
323
+ }
324
+ /**
325
+ * Renders the segment to an ANSI string.
326
+ */
327
+ render() {
328
+ if (this.isControl) return this.text;
329
+ if (typeof this.style?.render === "function") {
330
+ return this.style.render(this.text);
331
+ }
332
+ return this.text;
333
+ }
334
+ /**
335
+ * Splits the segment into lines.
336
+ */
337
+ splitLines(_allowEmpty = false) {
338
+ const lines = this.text.split("\n");
339
+ return lines.map((line) => {
340
+ return [new _Segment(line, this.style, this.isControl)];
341
+ });
342
+ }
343
+ /**
344
+ * Creates a new Segment with modified properties.
345
+ */
346
+ clone(text, style, isControl) {
347
+ return new _Segment(text ?? this.text, style ?? this.style, isControl ?? this.isControl);
348
+ }
349
+ };
350
+ var Color = class _Color {
351
+ tc;
352
+ constructor(color) {
353
+ this.tc = tinycolor(color);
354
+ }
355
+ static parse(color) {
356
+ return new _Color(color);
357
+ }
358
+ get hex() {
359
+ return this.tc.toHexString();
360
+ }
361
+ get rgb() {
362
+ return this.tc.toRgb();
363
+ }
364
+ get isDark() {
365
+ return this.tc.isDark();
366
+ }
367
+ get isLight() {
368
+ return this.tc.isLight();
369
+ }
370
+ contrast(other) {
371
+ return tinycolor.readability(this.tc, other.tc);
372
+ }
373
+ lighten(amount = 10) {
374
+ return new _Color(this.tc.lighten(amount));
375
+ }
376
+ darken(amount = 10) {
377
+ return new _Color(this.tc.darken(amount));
378
+ }
379
+ /**
380
+ * Returns a readable foreground color (black or white) for this background color.
381
+ */
382
+ getContrastColor() {
383
+ return this.isDark ? new _Color("#ffffff") : new _Color("#000000");
384
+ }
385
+ };
386
+
387
+ // src/themes/palette.ts
388
+ var Palette = class _Palette {
389
+ constructor(colors = {}) {
390
+ this.colors = colors;
391
+ }
392
+ get(name) {
393
+ return this.colors[name];
394
+ }
395
+ /**
396
+ * Generates a simple palette from a primary color.
397
+ */
398
+ static fromPrimary(primary) {
399
+ const p = new Color(primary);
400
+ return new _Palette({
401
+ primary: p.hex,
402
+ secondary: p.lighten(20).hex,
403
+ background: "#121212",
404
+ surface: "#1e1e1e",
405
+ text: "#ffffff",
406
+ error: "#cf6679",
407
+ success: "#03dac6",
408
+ warning: "#bb86fc"
409
+ });
410
+ }
411
+ };
412
+ var DEFAULT_PALETTE = new Palette({
413
+ primary: "#007bff",
414
+ secondary: "#6c757d",
415
+ success: "#28a745",
416
+ info: "#17a2b8",
417
+ warning: "#ffc107",
418
+ danger: "#dc3545",
419
+ light: "#f8f9fa",
420
+ dark: "#343a40"
421
+ });
422
+
423
+ // src/themes/theme.ts
424
+ var Theme = class _Theme {
425
+ constructor(styles = {}, palette) {
426
+ this.styles = styles;
427
+ this.palette = palette ?? DEFAULT_PALETTE;
428
+ }
429
+ palette;
430
+ get(name) {
431
+ const style = this.styles[name];
432
+ if (style) {
433
+ return typeof style === "string" ? this.parseWithPalette(style) : style;
434
+ }
435
+ const paletteColor = this.palette.get(name);
436
+ if (paletteColor) {
437
+ return new Style({ color: paletteColor });
438
+ }
439
+ return Style.null();
440
+ }
441
+ /**
442
+ * Parses a style string replacing palette references.
443
+ * e.g. "bold primary" -> "bold #007bff"
444
+ */
445
+ parseWithPalette(styleString) {
446
+ const parts = styleString.split(" ");
447
+ const resolvedParts = parts.map((part) => {
448
+ const color = this.palette.get(part);
449
+ if (color) return color;
450
+ if (part.startsWith("on")) {
451
+ const bgName = part.startsWith("on_") ? part.slice(3) : part.slice(2) || parts[parts.indexOf(part) + 1];
452
+ const bgColor = this.palette.get(bgName);
453
+ if (bgColor) return `on ${bgColor}`;
454
+ }
455
+ return part;
456
+ });
457
+ return Style.parse(resolvedParts.join(" "));
458
+ }
459
+ static fromPalette(palette) {
460
+ return new _Theme({
461
+ "danger": `bold ${palette.get("danger")}`,
462
+ "success": `bold ${palette.get("success")}`,
463
+ "warning": `bold ${palette.get("warning")}`,
464
+ "info": `${palette.get("info")}`
465
+ }, palette);
466
+ }
467
+ };
468
+ var DEFAULT_THEME = new Theme({
469
+ "none": Style.null(),
470
+ "dim": Style.parse("dim"),
471
+ "bright": Style.parse("bold"),
472
+ // Semantic
473
+ "danger": Style.parse("bold red"),
474
+ "success": Style.parse("bold green"),
475
+ "warning": Style.parse("bold yellow"),
476
+ "info": Style.parse("cyan"),
477
+ // Components
478
+ "rule.line": Style.parse("green"),
479
+ "repr.str": Style.parse("green"),
480
+ "repr.brace": Style.parse("bold")
481
+ });
482
+
483
+ // src/core/markup.ts
484
+ var MarkupParser = class _MarkupParser {
485
+ // Regex that matches standard tags [tag] and closing tags [/] or [/tag]
486
+ // We use a non-greedy match for content inside brackets
487
+ static TAG_REGEX = /\[(\/)?([\w\s#.,()]*?)\]/g;
488
+ theme;
489
+ constructor(theme) {
490
+ this.theme = theme ?? DEFAULT_THEME;
491
+ }
492
+ parse(markup) {
493
+ const segments = [];
494
+ const styleStack = [Style.null()];
495
+ let lastIndex = 0;
496
+ let match;
497
+ _MarkupParser.TAG_REGEX.lastIndex = 0;
498
+ while ((match = _MarkupParser.TAG_REGEX.exec(markup)) !== null) {
499
+ const fullMatch = match[0];
500
+ const isClosing = !!match[1];
501
+ const tagContent = match[2];
502
+ const index = match.index;
503
+ if (!isClosing && !tagContent) {
504
+ continue;
505
+ }
506
+ if (index > lastIndex) {
507
+ const text = markup.substring(lastIndex, index);
508
+ segments.push(new Segment(text, styleStack[styleStack.length - 1]));
509
+ }
510
+ if (isClosing) {
511
+ if (styleStack.length > 1) {
512
+ styleStack.pop();
513
+ }
514
+ } else {
515
+ const currentStyle = styleStack[styleStack.length - 1];
516
+ let nextStyle = this.theme.get(tagContent);
517
+ if (nextStyle === Style.null() && !this.theme.styles[tagContent]) {
518
+ nextStyle = Style.parse(tagContent);
519
+ } else if (this.theme.styles[tagContent]) ;
520
+ if (tagContent.includes(" ")) {
521
+ nextStyle = Style.parse(tagContent);
522
+ } else {
523
+ const themeStyle = this.theme.styles[tagContent];
524
+ if (themeStyle) {
525
+ nextStyle = typeof themeStyle === "string" ? Style.parse(themeStyle) : themeStyle;
526
+ } else {
527
+ nextStyle = Style.parse(tagContent);
528
+ }
529
+ }
530
+ const newStyle = currentStyle.combine(nextStyle);
531
+ styleStack.push(newStyle);
532
+ }
533
+ lastIndex = index + fullMatch.length;
534
+ }
535
+ if (lastIndex < markup.length) {
536
+ const text = markup.substring(lastIndex);
537
+ segments.push(new Segment(text, styleStack[styleStack.length - 1]));
538
+ }
539
+ return segments.filter((s) => s.text.length > 0);
540
+ }
541
+ };
542
+
543
+ // src/types/renderable.ts
544
+ function isRenderable(obj) {
545
+ return typeof obj === "object" && obj !== null && "__rich_console__" in obj && typeof obj.__rich_console__ === "function";
546
+ }
547
+
548
+ // src/traceback/trace.ts
549
+ var Trace = class {
550
+ static parse(error) {
551
+ if (!error.stack) return [];
552
+ const lines = error.stack.split("\n");
553
+ const frames = [];
554
+ for (let i = 1; i < lines.length; i++) {
555
+ const line = lines[i].trim();
556
+ if (!line.startsWith("at ")) continue;
557
+ let functionName = "";
558
+ let location = "";
559
+ if (line.includes("(")) {
560
+ const parts = line.substring(3).split(" (");
561
+ functionName = parts[0];
562
+ location = parts[1].slice(0, -1);
563
+ } else {
564
+ location = line.substring(3);
565
+ }
566
+ const locParts = location.split(":");
567
+ const columnNumber = parseInt(locParts.pop() || "0");
568
+ const lineNumber = parseInt(locParts.pop() || "0");
569
+ const filePath = locParts.join(":");
570
+ frames.push({
571
+ functionName: functionName || "<anonymous>",
572
+ filePath,
573
+ lineNumber,
574
+ columnNumber
575
+ });
576
+ }
577
+ return frames;
578
+ }
579
+ };
580
+
581
+ // src/syntax/theme.ts
582
+ var MONOKAI = {
583
+ name: "monokai",
584
+ background: "#272822",
585
+ styles: {
586
+ // Keywords and control flow
587
+ keyword: Style.parse("#f92672 bold"),
588
+ built_in: Style.parse("#66d9ef"),
589
+ type: Style.parse("#66d9ef italic"),
590
+ literal: Style.parse("#ae81ff"),
591
+ // Values
592
+ number: Style.parse("#ae81ff"),
593
+ string: Style.parse("#e6db74"),
594
+ regexp: Style.parse("#e6db74"),
595
+ symbol: Style.parse("#ae81ff"),
596
+ // Comments and docs
597
+ comment: Style.parse("#75715e dim"),
598
+ doctag: Style.parse("#75715e"),
599
+ meta: Style.parse("#75715e"),
600
+ // Functions and classes
601
+ function: Style.parse("#a6e22e"),
602
+ title: Style.parse("#a6e22e"),
603
+ "title.function": Style.parse("#a6e22e"),
604
+ "title.class": Style.parse("#a6e22e italic"),
605
+ "title.class.inherited": Style.parse("#a6e22e"),
606
+ // Variables and parameters
607
+ params: Style.parse("#fd971f italic"),
608
+ variable: Style.parse("#f8f8f2"),
609
+ "variable.language": Style.parse("#fd971f"),
610
+ "variable.constant": Style.parse("#ae81ff"),
611
+ // Properties and attributes
612
+ property: Style.parse("#66d9ef"),
613
+ attr: Style.parse("#a6e22e"),
614
+ attribute: Style.parse("#a6e22e"),
615
+ // Operators and punctuation
616
+ operator: Style.parse("#f92672"),
617
+ punctuation: Style.parse("#f8f8f2"),
618
+ // Misc
619
+ tag: Style.parse("#f92672"),
620
+ name: Style.parse("#a6e22e"),
621
+ "selector-tag": Style.parse("#f92672"),
622
+ "selector-class": Style.parse("#a6e22e"),
623
+ "selector-id": Style.parse("#a6e22e"),
624
+ // Template literals
625
+ "template-variable": Style.parse("#e6db74"),
626
+ "template-tag": Style.parse("#f92672"),
627
+ subst: Style.parse("#f8f8f2")
628
+ }
629
+ };
630
+ var DRACULA = {
631
+ name: "dracula",
632
+ background: "#282a36",
633
+ styles: {
634
+ keyword: Style.parse("#ff79c6 bold"),
635
+ built_in: Style.parse("#8be9fd"),
636
+ type: Style.parse("#8be9fd italic"),
637
+ literal: Style.parse("#bd93f9"),
638
+ number: Style.parse("#bd93f9"),
639
+ string: Style.parse("#f1fa8c"),
640
+ regexp: Style.parse("#f1fa8c"),
641
+ comment: Style.parse("#6272a4 dim"),
642
+ function: Style.parse("#50fa7b"),
643
+ title: Style.parse("#50fa7b"),
644
+ "title.function": Style.parse("#50fa7b"),
645
+ "title.class": Style.parse("#50fa7b italic"),
646
+ params: Style.parse("#ffb86c italic"),
647
+ variable: Style.parse("#f8f8f2"),
648
+ property: Style.parse("#8be9fd"),
649
+ attr: Style.parse("#50fa7b"),
650
+ operator: Style.parse("#ff79c6"),
651
+ tag: Style.parse("#ff79c6")
652
+ }
653
+ };
654
+ var GITHUB_LIGHT = {
655
+ name: "github",
656
+ styles: {
657
+ keyword: Style.parse("#d73a49 bold"),
658
+ built_in: Style.parse("#005cc5"),
659
+ type: Style.parse("#005cc5"),
660
+ literal: Style.parse("#005cc5"),
661
+ number: Style.parse("#005cc5"),
662
+ string: Style.parse("#032f62"),
663
+ regexp: Style.parse("#032f62"),
664
+ comment: Style.parse("#6a737d dim"),
665
+ function: Style.parse("#6f42c1"),
666
+ title: Style.parse("#6f42c1"),
667
+ "title.function": Style.parse("#6f42c1"),
668
+ "title.class": Style.parse("#6f42c1 bold"),
669
+ params: Style.parse("#24292e"),
670
+ variable: Style.parse("#24292e"),
671
+ property: Style.parse("#005cc5"),
672
+ attr: Style.parse("#6f42c1"),
673
+ operator: Style.parse("#d73a49"),
674
+ tag: Style.parse("#22863a")
675
+ }
676
+ };
677
+ var ONE_DARK = {
678
+ name: "one-dark",
679
+ background: "#282c34",
680
+ styles: {
681
+ keyword: Style.parse("#c678dd bold"),
682
+ built_in: Style.parse("#e5c07b"),
683
+ type: Style.parse("#e5c07b italic"),
684
+ literal: Style.parse("#d19a66"),
685
+ number: Style.parse("#d19a66"),
686
+ string: Style.parse("#98c379"),
687
+ regexp: Style.parse("#98c379"),
688
+ comment: Style.parse("#5c6370 dim"),
689
+ function: Style.parse("#61afef"),
690
+ title: Style.parse("#61afef"),
691
+ "title.function": Style.parse("#61afef"),
692
+ "title.class": Style.parse("#e5c07b bold"),
693
+ params: Style.parse("#abb2bf italic"),
694
+ variable: Style.parse("#e06c75"),
695
+ property: Style.parse("#e06c75"),
696
+ attr: Style.parse("#d19a66"),
697
+ operator: Style.parse("#56b6c2"),
698
+ tag: Style.parse("#e06c75")
699
+ }
700
+ };
701
+ var SYNTAX_THEMES = {
702
+ monokai: MONOKAI,
703
+ dracula: DRACULA,
704
+ github: GITHUB_LIGHT,
705
+ "github-light": GITHUB_LIGHT,
706
+ "one-dark": ONE_DARK,
707
+ atom: ONE_DARK
708
+ };
709
+ function getTheme(name) {
710
+ return SYNTAX_THEMES[name] ?? MONOKAI;
711
+ }
712
+ var MONOKAI_THEME = {
713
+ keyword: Style.parse("bold magenta"),
714
+ string: Style.parse("yellow"),
715
+ number: Style.parse("magenta"),
716
+ comment: Style.parse("dim white"),
717
+ operator: Style.parse("bold white"),
718
+ function: Style.parse("green"),
719
+ class: Style.parse("bold blue"),
720
+ title: Style.parse("bold white")
721
+ };
722
+ var Syntax = class _Syntax {
723
+ constructor(code, lexer, options = {}) {
724
+ this.code = code;
725
+ this.lexer = lexer;
726
+ this.options = options;
727
+ this.syntaxTheme = getTheme(options.theme ?? "monokai");
728
+ }
729
+ syntaxTheme;
730
+ /**
731
+ * Create Syntax from a file path (convenience method).
732
+ */
733
+ static fromPath(filePath, options = {}) {
734
+ const fs2 = __require("fs");
735
+ const path = __require("path");
736
+ const code = fs2.readFileSync(filePath, "utf-8");
737
+ const ext = path.extname(filePath).slice(1);
738
+ const lexerMap = {
739
+ ts: "typescript",
740
+ tsx: "typescript",
741
+ js: "javascript",
742
+ jsx: "javascript",
743
+ py: "python",
744
+ rb: "ruby",
745
+ rs: "rust",
746
+ go: "go",
747
+ java: "java",
748
+ cpp: "cpp",
749
+ c: "c",
750
+ h: "c",
751
+ hpp: "cpp",
752
+ cs: "csharp",
753
+ php: "php",
754
+ sh: "bash",
755
+ bash: "bash",
756
+ zsh: "bash",
757
+ md: "markdown",
758
+ json: "json",
759
+ yaml: "yaml",
760
+ yml: "yaml",
761
+ toml: "ini",
762
+ css: "css",
763
+ scss: "scss",
764
+ html: "html",
765
+ xml: "xml",
766
+ sql: "sql"
767
+ };
768
+ const lexer = lexerMap[ext] ?? ext;
769
+ return new _Syntax(code, lexer, options);
770
+ }
771
+ __rich_console__(_console, _options) {
772
+ const segments = [];
773
+ const startLine = this.options.startLine ?? 1;
774
+ const showLineNumbers = this.options.lineNumbers ?? false;
775
+ const highlightLines = new Set(this.options.highlightLines ?? []);
776
+ let highlighted;
777
+ try {
778
+ highlighted = hljs.highlight(this.code, { language: this.lexer });
779
+ } catch {
780
+ highlighted = hljs.highlightAuto(this.code);
781
+ }
782
+ const tokens = this.parseHighlightedHtml(highlighted.value);
783
+ const lines = this.groupTokensByLine(tokens);
784
+ const lastLineNumber = startLine + lines.length - 1;
785
+ const lineNumberWidth = showLineNumbers ? String(lastLineNumber).length + 1 : 0;
786
+ let maxWidth = 0;
787
+ lines.forEach((lineTokens, i) => {
788
+ const lineNumber = startLine + i;
789
+ const isHighlighted = highlightLines.has(lineNumber);
790
+ if (isHighlighted) {
791
+ segments.push(new Segment("\u2771 ", Style.parse("#ff5555 bold")));
792
+ } else if (showLineNumbers) {
793
+ segments.push(new Segment(" ", Style.null()));
794
+ }
795
+ if (showLineNumbers) {
796
+ const lineNumStr = String(lineNumber).padStart(lineNumberWidth - 1);
797
+ const lineNumStyle = isHighlighted ? Style.parse("#ff5555 bold") : Style.parse("#6e7681 dim");
798
+ segments.push(new Segment(`${lineNumStr} \u2502 `, lineNumStyle));
799
+ }
800
+ let lineWidth = 0;
801
+ for (const token of lineTokens) {
802
+ let style = token.style;
803
+ if (isHighlighted) {
804
+ style = style.combine(Style.parse("on #3a1d1d"));
805
+ }
806
+ segments.push(new Segment(token.text, style));
807
+ lineWidth += stringWidth3(token.text);
808
+ }
809
+ segments.push(new Segment("\n", Style.null(), true));
810
+ const totalLineWidth = lineWidth + (showLineNumbers ? lineNumberWidth + 5 : 0);
811
+ if (totalLineWidth > maxWidth) maxWidth = totalLineWidth;
812
+ });
813
+ return {
814
+ segments,
815
+ width: maxWidth
816
+ };
817
+ }
818
+ /**
819
+ * Parse highlight.js HTML output into styled tokens.
820
+ */
821
+ parseHighlightedHtml(html) {
822
+ const tokens = [];
823
+ const processHtml = (input, inheritedScope = []) => {
824
+ let remaining = input;
825
+ while (remaining.length > 0) {
826
+ const openMatch = remaining.match(/^<span class="hljs-([^"]+)">/);
827
+ if (openMatch) {
828
+ remaining = remaining.slice(openMatch[0].length);
829
+ const scope = openMatch[1];
830
+ let depth = 1;
831
+ let innerEnd = 0;
832
+ for (let i = 0; i < remaining.length; i++) {
833
+ if (remaining.slice(i).startsWith("<span")) {
834
+ depth++;
835
+ } else if (remaining.slice(i).startsWith("</span>")) {
836
+ depth--;
837
+ if (depth === 0) {
838
+ innerEnd = i;
839
+ break;
840
+ }
841
+ }
842
+ }
843
+ const innerContent = remaining.slice(0, innerEnd);
844
+ remaining = remaining.slice(innerEnd + "</span>".length);
845
+ const newScope = [...inheritedScope, scope];
846
+ processHtml(innerContent, newScope);
847
+ continue;
848
+ }
849
+ const textMatch = remaining.match(/^([^<]+)/);
850
+ if (textMatch) {
851
+ const text = this.decodeHtmlEntities(textMatch[1]);
852
+ const scope = inheritedScope[inheritedScope.length - 1] ?? "";
853
+ const style = this.getStyleForScope(scope);
854
+ tokens.push({ text, style });
855
+ remaining = remaining.slice(textMatch[0].length);
856
+ continue;
857
+ }
858
+ const tagMatch = remaining.match(/^<[^>]+>/);
859
+ if (tagMatch) {
860
+ remaining = remaining.slice(tagMatch[0].length);
861
+ continue;
862
+ }
863
+ if (remaining.length > 0) {
864
+ tokens.push({ text: remaining[0], style: Style.null() });
865
+ remaining = remaining.slice(1);
866
+ }
867
+ }
868
+ };
869
+ processHtml(html);
870
+ return tokens;
871
+ }
872
+ /**
873
+ * Decode HTML entities to their character equivalents.
874
+ */
875
+ decodeHtmlEntities(text) {
876
+ return text.replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&amp;/g, "&").replace(/&quot;/g, '"').replace(/&#x27;/g, "'").replace(/&#39;/g, "'").replace(/&nbsp;/g, " ");
877
+ }
878
+ /**
879
+ * Get style for a highlight.js scope/class.
880
+ */
881
+ getStyleForScope(scope) {
882
+ if (!scope) return Style.null();
883
+ if (this.syntaxTheme.styles[scope]) {
884
+ return this.syntaxTheme.styles[scope];
885
+ }
886
+ const parts = scope.split(".");
887
+ for (let i = parts.length - 1; i >= 0; i--) {
888
+ const partialScope = parts.slice(0, i + 1).join(".");
889
+ if (this.syntaxTheme.styles[partialScope]) {
890
+ return this.syntaxTheme.styles[partialScope];
891
+ }
892
+ }
893
+ if (this.syntaxTheme.styles[parts[0]]) {
894
+ return this.syntaxTheme.styles[parts[0]];
895
+ }
896
+ return Style.null();
897
+ }
898
+ /**
899
+ * Group tokens by line (split on newlines).
900
+ */
901
+ groupTokensByLine(tokens) {
902
+ const lines = [[]];
903
+ for (const token of tokens) {
904
+ const parts = token.text.split("\n");
905
+ for (let i = 0; i < parts.length; i++) {
906
+ if (i > 0) {
907
+ lines.push([]);
908
+ }
909
+ if (parts[i]) {
910
+ lines[lines.length - 1].push({ text: parts[i], style: token.style });
911
+ }
912
+ }
913
+ }
914
+ return lines;
915
+ }
916
+ };
917
+
918
+ // src/traceback/traceback.ts
919
+ var Traceback = class {
920
+ constructor(error, options = {}) {
921
+ this.error = error;
922
+ this.options = options;
923
+ this.frames = Trace.parse(error);
924
+ }
925
+ frames;
926
+ __rich_console__(console, consoleOptions) {
927
+ const segments = [];
928
+ const extraLines = this.options.extraLines ?? 3;
929
+ const theme = this.options.theme ?? "monokai";
930
+ const suppressInternal = this.options.suppressInternal ?? true;
931
+ const maxFrames = this.options.maxFrames ?? 100;
932
+ const width = consoleOptions.width ?? console.width;
933
+ segments.push(new Segment("\n", Style.null(), true));
934
+ const headerStyle = Style.parse("#ff5555 bold");
935
+ segments.push(new Segment("Traceback", headerStyle));
936
+ segments.push(new Segment(" (most recent call last)\n", Style.parse("dim")));
937
+ segments.push(new Segment("\n", Style.null(), true));
938
+ let filteredFrames = this.frames;
939
+ if (suppressInternal) {
940
+ filteredFrames = filteredFrames.filter(
941
+ (f) => !f.filePath.startsWith("node:") && !f.filePath.includes("node_modules")
942
+ );
943
+ }
944
+ filteredFrames = filteredFrames.slice(0, maxFrames);
945
+ for (const frame of filteredFrames) {
946
+ const frameHeaderStyle = Style.parse("#6e7681");
947
+ segments.push(new Segment(" File ", frameHeaderStyle));
948
+ segments.push(new Segment(`"${frame.filePath}"`, Style.parse("#61afef")));
949
+ segments.push(new Segment(", line ", frameHeaderStyle));
950
+ segments.push(new Segment(String(frame.lineNumber), Style.parse("#e5c07b bold")));
951
+ segments.push(new Segment(", in ", frameHeaderStyle));
952
+ segments.push(new Segment(frame.functionName, Style.parse("#98c379 italic")));
953
+ segments.push(new Segment("\n", Style.null(), true));
954
+ let codeSnippet = "";
955
+ try {
956
+ if (fs.existsSync(frame.filePath)) {
957
+ const content = fs.readFileSync(frame.filePath, "utf-8");
958
+ const lines = content.split("\n");
959
+ const start = Math.max(0, frame.lineNumber - extraLines - 1);
960
+ const end = Math.min(lines.length, frame.lineNumber + extraLines);
961
+ codeSnippet = lines.slice(start, end).join("\n");
962
+ const ext = frame.filePath.split(".").pop() ?? "txt";
963
+ const lexerMap = {
964
+ ts: "typescript",
965
+ tsx: "typescript",
966
+ js: "javascript",
967
+ jsx: "javascript",
968
+ py: "python",
969
+ rb: "ruby",
970
+ rs: "rust",
971
+ go: "go"
972
+ };
973
+ const lexer = lexerMap[ext] ?? ext;
974
+ const syntax = new Syntax(codeSnippet, lexer, {
975
+ theme,
976
+ lineNumbers: true,
977
+ startLine: start + 1,
978
+ highlightLines: [frame.lineNumber]
979
+ });
980
+ const syntaxResult = syntax.__rich_console__(console, {
981
+ ...consoleOptions,
982
+ width: width - 4
983
+ });
984
+ segments.push(new Segment("\n", Style.null(), true));
985
+ for (const seg of syntaxResult.segments) {
986
+ if (seg.isControl && seg.text === "\n") {
987
+ segments.push(seg);
988
+ segments.push(new Segment(" "));
989
+ } else {
990
+ segments.push(seg);
991
+ }
992
+ }
993
+ }
994
+ } catch {
995
+ segments.push(new Segment(" ", Style.null()));
996
+ segments.push(new Segment("[source not available]", Style.parse("dim italic")));
997
+ segments.push(new Segment("\n", Style.null(), true));
998
+ }
999
+ segments.push(new Segment("\n", Style.null(), true));
1000
+ }
1001
+ const errorNameStyle = Style.parse("#ff5555 bold");
1002
+ const errorMsgStyle = Style.parse("#ff5555");
1003
+ segments.push(new Segment(this.error.name, errorNameStyle));
1004
+ segments.push(new Segment(": ", Style.parse("dim")));
1005
+ segments.push(new Segment(this.error.message, errorMsgStyle));
1006
+ segments.push(new Segment("\n", Style.null(), true));
1007
+ return { segments, width };
1008
+ }
1009
+ };
1010
+ function installTracebackHandler(options = {}) {
1011
+ const console = new Console();
1012
+ process.on("uncaughtException", (error) => {
1013
+ const traceback = new Traceback(error, options);
1014
+ console.print(traceback);
1015
+ process.exit(1);
1016
+ });
1017
+ process.on("unhandledRejection", (reason) => {
1018
+ const error = reason instanceof Error ? reason : new Error(String(reason));
1019
+ const traceback = new Traceback(error, options);
1020
+ console.print(traceback);
1021
+ process.exit(1);
1022
+ });
1023
+ }
1024
+
1025
+ // src/utils/render-utils.ts
1026
+ function getRenderResult(renderable, console, options) {
1027
+ const result = renderable.__rich_console__(console, options);
1028
+ if ("segments" in result) {
1029
+ return result;
1030
+ }
1031
+ return {
1032
+ segments: Array.from(result),
1033
+ width: options.width
1034
+ // approximation
1035
+ };
1036
+ }
1037
+ var Live = class {
1038
+ constructor(renderable, console, autoRefresh = true) {
1039
+ this.renderable = renderable;
1040
+ this.console = console;
1041
+ this.autoRefresh = autoRefresh;
1042
+ }
1043
+ _started = false;
1044
+ _lastHeight = 0;
1045
+ start() {
1046
+ this._started = true;
1047
+ this.refresh();
1048
+ }
1049
+ stop() {
1050
+ this._started = false;
1051
+ this.console.print("");
1052
+ }
1053
+ update(renderable) {
1054
+ this.renderable = renderable;
1055
+ this.refresh();
1056
+ }
1057
+ refresh() {
1058
+ if (!this._started) return;
1059
+ if (this._lastHeight > 0) {
1060
+ process.stdout.write(ansiEscapes.eraseLines(this._lastHeight));
1061
+ }
1062
+ const output = this.console.render(this.renderable);
1063
+ const lines = output.split("\n").length;
1064
+ this._lastHeight = lines;
1065
+ process.stdout.write(output);
1066
+ }
1067
+ };
1068
+ var Spinner = class {
1069
+ // Type definition issues with cli-spinners
1070
+ constructor(name = "dots", style = Style.null()) {
1071
+ this.name = name;
1072
+ this.style = style;
1073
+ this.spinner = cliSpinners[name];
1074
+ }
1075
+ frame = 0;
1076
+ // @ts-ignore
1077
+ spinner;
1078
+ get currentFrame() {
1079
+ return this.spinner.frames[this.frame];
1080
+ }
1081
+ __rich_console__(_console, _options) {
1082
+ return {
1083
+ segments: [new Segment(this.currentFrame, this.style)],
1084
+ width: 1
1085
+ // approximates
1086
+ };
1087
+ }
1088
+ nextFrame() {
1089
+ this.frame = (this.frame + 1) % this.spinner.frames.length;
1090
+ }
1091
+ };
1092
+
1093
+ // src/core/lines.ts
1094
+ function splitLines(segments) {
1095
+ const lines = [];
1096
+ let currentLine = [];
1097
+ for (const segment of segments) {
1098
+ if (segment.text.includes("\n")) {
1099
+ const parts = segment.text.split("\n");
1100
+ for (let i = 0; i < parts.length; i++) {
1101
+ const part = parts[i];
1102
+ if (part) {
1103
+ currentLine.push(new Segment(part, segment.style, segment.isControl));
1104
+ }
1105
+ if (i < parts.length - 1) {
1106
+ lines.push(currentLine);
1107
+ currentLine = [];
1108
+ }
1109
+ }
1110
+ } else {
1111
+ currentLine.push(segment);
1112
+ }
1113
+ }
1114
+ if (currentLine.length > 0) {
1115
+ lines.push(currentLine);
1116
+ }
1117
+ return lines;
1118
+ }
1119
+ function padLine(line, width, style = Style.null()) {
1120
+ const currentWidth = line.reduce((acc, s) => acc + s.cellLength(), 0);
1121
+ if (currentWidth >= width) return line;
1122
+ const padding = width - currentWidth;
1123
+ return [...line, new Segment(" ".repeat(padding), style)];
1124
+ }
1125
+
1126
+ // src/layout/layout.ts
1127
+ var Layout = class _Layout {
1128
+ _renderable = null;
1129
+ _children = [];
1130
+ _direction = "column";
1131
+ size;
1132
+ ratio = 1;
1133
+ minimumSize = 0;
1134
+ visible = true;
1135
+ constructor(renderable, options = {}) {
1136
+ if (renderable) this._renderable = renderable;
1137
+ this.size = options.size;
1138
+ this.ratio = options.ratio ?? 1;
1139
+ this.minimumSize = options.minimumSize ?? 0;
1140
+ this.visible = options.visible ?? true;
1141
+ }
1142
+ /**
1143
+ * Split the layout into a row (horizontal split).
1144
+ */
1145
+ splitRow(...layouts) {
1146
+ this._direction = "row";
1147
+ this._children = layouts.map((l) => l instanceof _Layout ? l : new _Layout(l));
1148
+ }
1149
+ /**
1150
+ * Split the layout into a column (vertical split).
1151
+ */
1152
+ splitColumn(...layouts) {
1153
+ this._direction = "column";
1154
+ this._children = layouts.map((l) => l instanceof _Layout ? l : new _Layout(l));
1155
+ }
1156
+ get renderable() {
1157
+ return this._renderable;
1158
+ }
1159
+ update(renderable) {
1160
+ this._renderable = renderable;
1161
+ }
1162
+ __rich_console__(console, options) {
1163
+ if (!this.visible) return { segments: [], width: 0, height: 0 };
1164
+ const width = options.width ?? console.width;
1165
+ const height = options.height ?? console.height;
1166
+ if (this._children.length === 0) {
1167
+ if (this._renderable) {
1168
+ return getRenderResult(this._renderable, console, { ...options, width, height });
1169
+ }
1170
+ return { segments: [], width, height: 0 };
1171
+ }
1172
+ const segments = [];
1173
+ if (this._direction === "column") {
1174
+ for (const child of this._children) {
1175
+ if (!child.visible) continue;
1176
+ const result = getRenderResult(child, console, { ...options, width });
1177
+ segments.push(...result.segments);
1178
+ const last = result.segments[result.segments.length - 1];
1179
+ if (last && !last.text.endsWith("\n")) {
1180
+ segments.push(new Segment("\n"));
1181
+ }
1182
+ }
1183
+ } else {
1184
+ const childWidths = this.calculateSizes(width, this._children);
1185
+ const renderedLines = [];
1186
+ let maxHeight = 0;
1187
+ this._children.forEach((child, i) => {
1188
+ if (!child.visible) {
1189
+ renderedLines.push([]);
1190
+ return;
1191
+ }
1192
+ const w = childWidths[i];
1193
+ const result = getRenderResult(child, console, { ...options, width: w });
1194
+ let childSegments = result.segments;
1195
+ const lines = splitLines(childSegments);
1196
+ renderedLines.push(lines);
1197
+ if (lines.length > maxHeight) maxHeight = lines.length;
1198
+ });
1199
+ for (let y = 0; y < maxHeight; y++) {
1200
+ for (let x = 0; x < this._children.length; x++) {
1201
+ if (!this._children[x].visible) continue;
1202
+ const lines = renderedLines[x];
1203
+ const w = childWidths[x];
1204
+ if (y < lines.length) {
1205
+ const line = lines[y];
1206
+ segments.push(...padLine(line, w));
1207
+ } else {
1208
+ segments.push(new Segment(" ".repeat(w)));
1209
+ }
1210
+ }
1211
+ segments.push(new Segment("\n"));
1212
+ }
1213
+ }
1214
+ return { segments, width, height };
1215
+ }
1216
+ /**
1217
+ * Calculates the size (width for rows, height for columns) for each child
1218
+ * based on constraints.
1219
+ */
1220
+ calculateSizes(availableSpace, children) {
1221
+ const sizes = new Array(children.length).fill(0);
1222
+ const visibleChildren = children.map((c, i) => ({ child: c, index: i })).filter((x) => x.child.visible);
1223
+ if (visibleChildren.length === 0) return sizes;
1224
+ let remainingSpace = availableSpace;
1225
+ let totalRatio = 0;
1226
+ for (const { child, index } of visibleChildren) {
1227
+ if (child.size !== void 0) {
1228
+ const size = Math.min(child.size, remainingSpace);
1229
+ sizes[index] = size;
1230
+ remainingSpace -= size;
1231
+ } else if (child.minimumSize > 0) {
1232
+ sizes[index] = child.minimumSize;
1233
+ remainingSpace -= child.minimumSize;
1234
+ }
1235
+ if (child.size === void 0) {
1236
+ totalRatio += child.ratio;
1237
+ }
1238
+ }
1239
+ if (remainingSpace <= 0) return sizes;
1240
+ if (totalRatio > 0) {
1241
+ let distributed = 0;
1242
+ for (let i = 0; i < visibleChildren.length; i++) {
1243
+ const { child, index } = visibleChildren[i];
1244
+ if (child.size === void 0) {
1245
+ const share = Math.floor(child.ratio / totalRatio * remainingSpace);
1246
+ sizes[index] += share;
1247
+ distributed += share;
1248
+ }
1249
+ }
1250
+ const dust = remainingSpace - distributed;
1251
+ if (dust > 0) {
1252
+ for (let i = visibleChildren.length - 1; i >= 0; i--) {
1253
+ const { child, index } = visibleChildren[i];
1254
+ if (child.size === void 0) {
1255
+ sizes[index] += dust;
1256
+ break;
1257
+ }
1258
+ }
1259
+ }
1260
+ }
1261
+ return sizes;
1262
+ }
1263
+ };
1264
+ var Text = class {
1265
+ constructor(content, style = Style.null(), justify = "left", overflow = "fold", noWrap = false) {
1266
+ this.style = style;
1267
+ this.justify = justify;
1268
+ this.overflow = overflow;
1269
+ this.noWrap = noWrap;
1270
+ if (typeof content === "string") {
1271
+ const parser = new MarkupParser();
1272
+ this.segments = parser.parse(content);
1273
+ } else {
1274
+ this.segments = content;
1275
+ }
1276
+ }
1277
+ segments;
1278
+ __rich_console__(console, options) {
1279
+ const width = options.width ?? console.width;
1280
+ const text = this.segments.map((s) => s.render()).join("");
1281
+ let wrapped = text;
1282
+ if (!this.noWrap) {
1283
+ wrapped = wrapAnsi(text, width, { hard: true, trim: false });
1284
+ }
1285
+ const resultSegments = wrapped.split("\n").flatMap((line) => {
1286
+ return [new Segment(line), new Segment("\n", Style.null(), true)];
1287
+ });
1288
+ return {
1289
+ segments: resultSegments,
1290
+ width
1291
+ };
1292
+ }
1293
+ };
1294
+
1295
+ // src/status/status.ts
1296
+ var Status = class {
1297
+ live;
1298
+ spinner;
1299
+ message;
1300
+ interval = null;
1301
+ constructor(message, options = {}) {
1302
+ this.message = message;
1303
+ this.spinner = new Spinner(options.spinner ?? "dots");
1304
+ const console = options.console ?? new Console();
1305
+ this.live = new Live(this.render(), console);
1306
+ }
1307
+ start() {
1308
+ this.live.start();
1309
+ this.interval = setInterval(() => {
1310
+ this.spinner.nextFrame();
1311
+ this.live.update(this.render());
1312
+ }, 80);
1313
+ }
1314
+ stop() {
1315
+ if (this.interval) clearInterval(this.interval);
1316
+ this.live.stop();
1317
+ }
1318
+ update(message) {
1319
+ this.message = message;
1320
+ this.live.update(this.render());
1321
+ }
1322
+ render() {
1323
+ const layout = new Layout();
1324
+ layout.splitRow(
1325
+ this.spinner,
1326
+ new Text(" " + this.message)
1327
+ );
1328
+ return layout;
1329
+ }
1330
+ };
1331
+
1332
+ // src/console/console.ts
1333
+ var Console = class {
1334
+ terminal;
1335
+ markupParser;
1336
+ options;
1337
+ theme;
1338
+ constructor(options = {}) {
1339
+ this.options = options;
1340
+ this.terminal = new Terminal();
1341
+ this.theme = options.theme ?? DEFAULT_THEME;
1342
+ this.markupParser = new MarkupParser(this.theme);
1343
+ }
1344
+ get width() {
1345
+ return this.options.width ?? this.terminal.width;
1346
+ }
1347
+ get height() {
1348
+ return this.options.height ?? this.terminal.height;
1349
+ }
1350
+ /**
1351
+ * Prints objects to the console.
1352
+ */
1353
+ print(...objects) {
1354
+ const lastObj = objects[objects.length - 1];
1355
+ let printObjects = objects;
1356
+ let options = {};
1357
+ if (objects.length > 1 && typeof lastObj === "object" && lastObj !== null && !isRenderable(lastObj) && ("style" in lastObj || "markup" in lastObj)) {
1358
+ options = objects.pop();
1359
+ printObjects = objects;
1360
+ }
1361
+ const output = printObjects.map((obj) => {
1362
+ if (typeof obj === "string") {
1363
+ return this.renderString(obj, options.markup ?? true);
1364
+ }
1365
+ if (isRenderable(obj)) {
1366
+ return this.render(obj);
1367
+ }
1368
+ return String(obj);
1369
+ }).join(" ");
1370
+ this.write(output + "\n");
1371
+ }
1372
+ /**
1373
+ * Prints a formatted exception.
1374
+ */
1375
+ printException(error) {
1376
+ const traceback = new Traceback(error);
1377
+ this.print(traceback);
1378
+ }
1379
+ /**
1380
+ * Displays a status spinner.
1381
+ */
1382
+ status(message, options = {}) {
1383
+ return new Status(message, { console: this, ...options });
1384
+ }
1385
+ /**
1386
+ * Run a task with a status spinner.
1387
+ */
1388
+ async withStatus(message, task, options = {}) {
1389
+ const status = new Status(message, { console: this, ...options });
1390
+ status.start();
1391
+ try {
1392
+ return await task(status);
1393
+ } finally {
1394
+ status.stop();
1395
+ }
1396
+ }
1397
+ /**
1398
+ * Renders a renderable object to a string.
1399
+ */
1400
+ render(renderable) {
1401
+ const result = getRenderResult(renderable, this, this.options);
1402
+ return result.segments.map((s) => s.render()).join("");
1403
+ }
1404
+ /**
1405
+ * Internal string rendering with markup and wrapping.
1406
+ */
1407
+ renderString(text, markup = true) {
1408
+ const segments = markup ? this.markupParser.parse(text) : [new Segment(text)];
1409
+ const rendered = segments.map((s) => s.render()).join("");
1410
+ return wrapAnsi(rendered, this.width, { hard: true });
1411
+ }
1412
+ /**
1413
+ * Low-level write to stdout.
1414
+ */
1415
+ write(text) {
1416
+ process2.stdout.write(text);
1417
+ }
1418
+ };
1419
+ var CUSTOM_BOXES = {
1420
+ // Rounded corners (may not be in all versions of cli-boxes)
1421
+ rounded: {
1422
+ topLeft: "\u256D",
1423
+ top: "\u2500",
1424
+ topRight: "\u256E",
1425
+ right: "\u2502",
1426
+ bottomRight: "\u256F",
1427
+ bottom: "\u2500",
1428
+ bottomLeft: "\u2570",
1429
+ left: "\u2502",
1430
+ topMid: "\u252C",
1431
+ midMid: "\u253C",
1432
+ bottomMid: "\u2534",
1433
+ leftMid: "\u251C",
1434
+ rightMid: "\u2524",
1435
+ mid: "\u2500",
1436
+ verticalMid: "\u2502"
1437
+ },
1438
+ round: {
1439
+ topLeft: "\u256D",
1440
+ top: "\u2500",
1441
+ topRight: "\u256E",
1442
+ right: "\u2502",
1443
+ bottomRight: "\u256F",
1444
+ bottom: "\u2500",
1445
+ bottomLeft: "\u2570",
1446
+ left: "\u2502",
1447
+ topMid: "\u252C",
1448
+ midMid: "\u253C",
1449
+ bottomMid: "\u2534",
1450
+ leftMid: "\u251C",
1451
+ rightMid: "\u2524",
1452
+ mid: "\u2500",
1453
+ verticalMid: "\u2502"
1454
+ },
1455
+ // Heavy/bold lines
1456
+ heavy: {
1457
+ topLeft: "\u250F",
1458
+ top: "\u2501",
1459
+ topRight: "\u2513",
1460
+ right: "\u2503",
1461
+ bottomRight: "\u251B",
1462
+ bottom: "\u2501",
1463
+ bottomLeft: "\u2517",
1464
+ left: "\u2503",
1465
+ topMid: "\u2533",
1466
+ midMid: "\u254B",
1467
+ bottomMid: "\u253B",
1468
+ leftMid: "\u2523",
1469
+ rightMid: "\u252B",
1470
+ mid: "\u2501",
1471
+ verticalMid: "\u2503"
1472
+ },
1473
+ // Double lines
1474
+ double: {
1475
+ topLeft: "\u2554",
1476
+ top: "\u2550",
1477
+ topRight: "\u2557",
1478
+ right: "\u2551",
1479
+ bottomRight: "\u255D",
1480
+ bottom: "\u2550",
1481
+ bottomLeft: "\u255A",
1482
+ left: "\u2551",
1483
+ topMid: "\u2566",
1484
+ midMid: "\u256C",
1485
+ bottomMid: "\u2569",
1486
+ leftMid: "\u2560",
1487
+ rightMid: "\u2563",
1488
+ mid: "\u2550",
1489
+ verticalMid: "\u2551"
1490
+ },
1491
+ // Single/square lines
1492
+ single: {
1493
+ topLeft: "\u250C",
1494
+ top: "\u2500",
1495
+ topRight: "\u2510",
1496
+ right: "\u2502",
1497
+ bottomRight: "\u2518",
1498
+ bottom: "\u2500",
1499
+ bottomLeft: "\u2514",
1500
+ left: "\u2502",
1501
+ topMid: "\u252C",
1502
+ midMid: "\u253C",
1503
+ bottomMid: "\u2534",
1504
+ leftMid: "\u251C",
1505
+ rightMid: "\u2524",
1506
+ mid: "\u2500",
1507
+ verticalMid: "\u2502"
1508
+ },
1509
+ square: {
1510
+ topLeft: "\u250C",
1511
+ top: "\u2500",
1512
+ topRight: "\u2510",
1513
+ right: "\u2502",
1514
+ bottomRight: "\u2518",
1515
+ bottom: "\u2500",
1516
+ bottomLeft: "\u2514",
1517
+ left: "\u2502",
1518
+ topMid: "\u252C",
1519
+ midMid: "\u253C",
1520
+ bottomMid: "\u2534",
1521
+ leftMid: "\u251C",
1522
+ rightMid: "\u2524",
1523
+ mid: "\u2500",
1524
+ verticalMid: "\u2502"
1525
+ },
1526
+ // ASCII-safe
1527
+ ascii: {
1528
+ topLeft: "+",
1529
+ top: "-",
1530
+ topRight: "+",
1531
+ right: "|",
1532
+ bottomRight: "+",
1533
+ bottom: "-",
1534
+ bottomLeft: "+",
1535
+ left: "|",
1536
+ topMid: "+",
1537
+ midMid: "+",
1538
+ bottomMid: "+",
1539
+ leftMid: "+",
1540
+ rightMid: "+",
1541
+ mid: "-",
1542
+ verticalMid: "|"
1543
+ },
1544
+ // Minimal - no borders
1545
+ minimal: {
1546
+ topLeft: " ",
1547
+ top: " ",
1548
+ topRight: " ",
1549
+ right: " ",
1550
+ bottomRight: " ",
1551
+ bottom: " ",
1552
+ bottomLeft: " ",
1553
+ left: " ",
1554
+ topMid: " ",
1555
+ midMid: " ",
1556
+ bottomMid: " ",
1557
+ leftMid: " ",
1558
+ rightMid: " ",
1559
+ mid: "\u2500",
1560
+ verticalMid: " "
1561
+ },
1562
+ // Simple - just horizontal lines
1563
+ simple: {
1564
+ topLeft: " ",
1565
+ top: "\u2500",
1566
+ topRight: " ",
1567
+ right: " ",
1568
+ bottomRight: " ",
1569
+ bottom: "\u2500",
1570
+ bottomLeft: " ",
1571
+ left: " ",
1572
+ topMid: " ",
1573
+ midMid: "\u2500",
1574
+ bottomMid: " ",
1575
+ leftMid: " ",
1576
+ rightMid: " ",
1577
+ mid: "\u2500",
1578
+ verticalMid: " "
1579
+ },
1580
+ // Markdown style
1581
+ markdown: {
1582
+ topLeft: " ",
1583
+ top: " ",
1584
+ topRight: " ",
1585
+ right: "|",
1586
+ bottomRight: " ",
1587
+ bottom: " ",
1588
+ bottomLeft: " ",
1589
+ left: "|",
1590
+ topMid: " ",
1591
+ midMid: "|",
1592
+ bottomMid: " ",
1593
+ leftMid: "|",
1594
+ rightMid: "|",
1595
+ mid: "-",
1596
+ verticalMid: "|"
1597
+ }
1598
+ };
1599
+ function getBox(style) {
1600
+ if (style === "none") return null;
1601
+ if (style in CUSTOM_BOXES) {
1602
+ return CUSTOM_BOXES[style];
1603
+ }
1604
+ if (style === "bold") {
1605
+ return CUSTOM_BOXES.heavy;
1606
+ }
1607
+ const cliBox = boxes[style];
1608
+ if (cliBox) {
1609
+ return {
1610
+ ...cliBox,
1611
+ topMid: cliBox.topMid ?? "\u252C",
1612
+ midMid: cliBox.midMid ?? "\u253C",
1613
+ bottomMid: cliBox.bottomMid ?? "\u2534",
1614
+ leftMid: cliBox.leftMid ?? "\u251C",
1615
+ rightMid: cliBox.rightMid ?? "\u2524",
1616
+ mid: cliBox.mid ?? "\u2500",
1617
+ verticalMid: cliBox.verticalMid ?? "\u2502"
1618
+ };
1619
+ }
1620
+ return CUSTOM_BOXES.rounded;
1621
+ }
1622
+ function listBoxStyles() {
1623
+ const customStyles = Object.keys(CUSTOM_BOXES);
1624
+ const cliBoxStyles = Object.keys(boxes);
1625
+ return [.../* @__PURE__ */ new Set([...customStyles, ...cliBoxStyles])];
1626
+ }
1627
+ var Panel = class _Panel {
1628
+ constructor(renderable, options = {}) {
1629
+ this.renderable = renderable;
1630
+ this.options = options;
1631
+ }
1632
+ /**
1633
+ * Create a panel that fits its content (expand=false).
1634
+ */
1635
+ static fit(renderable, options = {}) {
1636
+ return new _Panel(renderable, { ...options, expand: false });
1637
+ }
1638
+ __rich_console__(console, consoleOptions) {
1639
+ const box = getBox(this.options.box ?? "rounded");
1640
+ const expand = this.options.expand ?? true;
1641
+ const maxWidth = this.options.width ?? consoleOptions.width ?? console.width;
1642
+ const borderStyle = typeof this.options.borderStyle === "string" ? Style.parse(this.options.borderStyle) : this.options.borderStyle ?? Style.parse("dim");
1643
+ const titleAlign = this.options.titleAlign ?? "center";
1644
+ const subtitleAlign = this.options.subtitleAlign ?? "center";
1645
+ const padding = this.normalizePadding(this.options.padding ?? 1);
1646
+ const segments = [];
1647
+ if (!box) {
1648
+ return { segments: [], width: 0 };
1649
+ }
1650
+ let contentSegments = [];
1651
+ if (typeof this.renderable === "string") {
1652
+ contentSegments = [new Segment(this.renderable)];
1653
+ } else if (isRenderable(this.renderable)) {
1654
+ const contentWidth = maxWidth - 2 - padding[1] - padding[3];
1655
+ const result = this.renderable.__rich_console__(console, {
1656
+ ...consoleOptions,
1657
+ width: contentWidth
1658
+ });
1659
+ if ("segments" in result) {
1660
+ contentSegments = Array.from(result.segments);
1661
+ }
1662
+ }
1663
+ const lines = splitLines(contentSegments);
1664
+ let maxContentWidth = 0;
1665
+ for (const line of lines) {
1666
+ const lineWidth = line.reduce((w, seg) => w + stringWidth3(seg.text), 0);
1667
+ if (lineWidth > maxContentWidth) maxContentWidth = lineWidth;
1668
+ }
1669
+ const titleWidth = this.options.title ? stringWidth3(this.options.title) + 4 : 0;
1670
+ const subtitleWidth = this.options.subtitle ? stringWidth3(this.options.subtitle) + 4 : 0;
1671
+ let panelWidth;
1672
+ if (expand) {
1673
+ panelWidth = maxWidth;
1674
+ } else {
1675
+ panelWidth = Math.min(
1676
+ maxWidth,
1677
+ Math.max(maxContentWidth + 2 + padding[1] + padding[3], titleWidth + 2, subtitleWidth + 2)
1678
+ );
1679
+ }
1680
+ const innerWidth = panelWidth - 2;
1681
+ segments.push(...this.renderTopBorder(box, innerWidth, borderStyle, titleAlign));
1682
+ segments.push(new Segment("\n", Style.null(), true));
1683
+ for (let i = 0; i < padding[0]; i++) {
1684
+ segments.push(new Segment(box.left, borderStyle));
1685
+ segments.push(new Segment(" ".repeat(innerWidth)));
1686
+ segments.push(new Segment(box.right, borderStyle));
1687
+ segments.push(new Segment("\n", Style.null(), true));
1688
+ }
1689
+ for (const line of lines) {
1690
+ segments.push(new Segment(box.left, borderStyle));
1691
+ segments.push(new Segment(" ".repeat(padding[3])));
1692
+ const contentPaddedWidth = innerWidth - padding[1] - padding[3];
1693
+ const paddedLine = padLine(line, contentPaddedWidth);
1694
+ segments.push(...paddedLine);
1695
+ segments.push(new Segment(" ".repeat(padding[1])));
1696
+ segments.push(new Segment(box.right, borderStyle));
1697
+ segments.push(new Segment("\n", Style.null(), true));
1698
+ }
1699
+ if (lines.length === 0) {
1700
+ segments.push(new Segment(box.left, borderStyle));
1701
+ segments.push(new Segment(" ".repeat(innerWidth)));
1702
+ segments.push(new Segment(box.right, borderStyle));
1703
+ segments.push(new Segment("\n", Style.null(), true));
1704
+ }
1705
+ for (let i = 0; i < padding[2]; i++) {
1706
+ segments.push(new Segment(box.left, borderStyle));
1707
+ segments.push(new Segment(" ".repeat(innerWidth)));
1708
+ segments.push(new Segment(box.right, borderStyle));
1709
+ segments.push(new Segment("\n", Style.null(), true));
1710
+ }
1711
+ segments.push(...this.renderBottomBorder(box, innerWidth, borderStyle, subtitleAlign));
1712
+ segments.push(new Segment("\n", Style.null(), true));
1713
+ return {
1714
+ segments,
1715
+ width: panelWidth
1716
+ };
1717
+ }
1718
+ /**
1719
+ * Normalize padding to [top, right, bottom, left] format.
1720
+ */
1721
+ normalizePadding(padding) {
1722
+ if (typeof padding === "number") {
1723
+ return [padding, padding, padding, padding];
1724
+ }
1725
+ if (padding.length === 2) {
1726
+ return [padding[0], padding[1], padding[0], padding[1]];
1727
+ }
1728
+ return padding;
1729
+ }
1730
+ /**
1731
+ * Render top border with optional title.
1732
+ */
1733
+ renderTopBorder(box, innerWidth, borderStyle, align) {
1734
+ const segments = [];
1735
+ if (this.options.title) {
1736
+ const title = ` ${this.options.title} `;
1737
+ const titleWidth = stringWidth3(title);
1738
+ const remainingWidth = Math.max(0, innerWidth - titleWidth);
1739
+ let leftLine;
1740
+ let rightLine;
1741
+ switch (align) {
1742
+ case "left":
1743
+ leftLine = "";
1744
+ rightLine = box.top.repeat(remainingWidth);
1745
+ break;
1746
+ case "right":
1747
+ leftLine = box.top.repeat(remainingWidth);
1748
+ rightLine = "";
1749
+ break;
1750
+ case "center":
1751
+ default: {
1752
+ const leftWidth = Math.floor(remainingWidth / 2);
1753
+ leftLine = box.top.repeat(leftWidth);
1754
+ rightLine = box.top.repeat(remainingWidth - leftWidth);
1755
+ break;
1756
+ }
1757
+ }
1758
+ segments.push(new Segment(box.topLeft, borderStyle));
1759
+ segments.push(new Segment(leftLine, borderStyle));
1760
+ segments.push(new Segment(title, Style.parse("bold")));
1761
+ segments.push(new Segment(rightLine, borderStyle));
1762
+ segments.push(new Segment(box.topRight, borderStyle));
1763
+ } else {
1764
+ segments.push(
1765
+ new Segment(box.topLeft + box.top.repeat(innerWidth) + box.topRight, borderStyle)
1766
+ );
1767
+ }
1768
+ return segments;
1769
+ }
1770
+ /**
1771
+ * Render bottom border with optional subtitle.
1772
+ */
1773
+ renderBottomBorder(box, innerWidth, borderStyle, align) {
1774
+ const segments = [];
1775
+ if (this.options.subtitle) {
1776
+ const subtitle = ` ${this.options.subtitle} `;
1777
+ const subtitleWidth = stringWidth3(subtitle);
1778
+ const remainingWidth = Math.max(0, innerWidth - subtitleWidth);
1779
+ let leftLine;
1780
+ let rightLine;
1781
+ switch (align) {
1782
+ case "left":
1783
+ leftLine = "";
1784
+ rightLine = box.bottom.repeat(remainingWidth);
1785
+ break;
1786
+ case "right":
1787
+ leftLine = box.bottom.repeat(remainingWidth);
1788
+ rightLine = "";
1789
+ break;
1790
+ case "center":
1791
+ default: {
1792
+ const leftWidth = Math.floor(remainingWidth / 2);
1793
+ leftLine = box.bottom.repeat(leftWidth);
1794
+ rightLine = box.bottom.repeat(remainingWidth - leftWidth);
1795
+ break;
1796
+ }
1797
+ }
1798
+ segments.push(new Segment(box.bottomLeft, borderStyle));
1799
+ segments.push(new Segment(leftLine, borderStyle));
1800
+ segments.push(new Segment(subtitle, Style.parse("dim italic")));
1801
+ segments.push(new Segment(rightLine, borderStyle));
1802
+ segments.push(new Segment(box.bottomRight, borderStyle));
1803
+ } else {
1804
+ segments.push(
1805
+ new Segment(box.bottomLeft + box.bottom.repeat(innerWidth) + box.bottomRight, borderStyle)
1806
+ );
1807
+ }
1808
+ return segments;
1809
+ }
1810
+ };
1811
+ var Rule = class {
1812
+ constructor(title = "", characters = "\u2500", style = Style.null()) {
1813
+ this.title = title;
1814
+ this.characters = characters;
1815
+ this.style = style;
1816
+ }
1817
+ __rich_console__(console, options) {
1818
+ const width = options.width ?? console.width;
1819
+ let line = "";
1820
+ if (this.title) {
1821
+ const titleText = ` ${this.title} `;
1822
+ const titleWidth = stringWidth3(titleText);
1823
+ const sideWidth = Math.floor((width - titleWidth) / 2);
1824
+ line = this.characters.repeat(sideWidth) + titleText + this.characters.repeat(width - titleWidth - sideWidth);
1825
+ } else {
1826
+ line = this.characters.repeat(width);
1827
+ }
1828
+ return {
1829
+ segments: [new Segment(line, this.style), new Segment("\n", Style.null(), true)],
1830
+ width
1831
+ };
1832
+ }
1833
+ };
1834
+ var Column = class {
1835
+ constructor(options) {
1836
+ this.options = options;
1837
+ }
1838
+ get header() {
1839
+ return this.options.header ?? "";
1840
+ }
1841
+ get footer() {
1842
+ return this.options.footer ?? "";
1843
+ }
1844
+ get justify() {
1845
+ return this.options.justify ?? "left";
1846
+ }
1847
+ get style() {
1848
+ return typeof this.options.style === "string" ? Style.parse(this.options.style) : this.options.style ?? Style.null();
1849
+ }
1850
+ get headerStyle() {
1851
+ return typeof this.options.headerStyle === "string" ? Style.parse(this.options.headerStyle) : this.options.headerStyle ?? Style.null();
1852
+ }
1853
+ };
1854
+ var Table = class {
1855
+ constructor(options = {}) {
1856
+ this.options = options;
1857
+ }
1858
+ columns = [];
1859
+ rows = [];
1860
+ footerRow = [];
1861
+ addColumn(header, options) {
1862
+ if (typeof header === "string") {
1863
+ this.columns.push(new Column({ header, ...options }));
1864
+ } else {
1865
+ this.columns.push(new Column(header));
1866
+ }
1867
+ return this;
1868
+ }
1869
+ addRow(...cells) {
1870
+ this.rows.push(cells);
1871
+ return this;
1872
+ }
1873
+ addFooter(...cells) {
1874
+ this.footerRow = cells;
1875
+ return this;
1876
+ }
1877
+ alignText(text, width, justify) {
1878
+ const textWidth = stringWidth3(text);
1879
+ const space = Math.max(0, width - textWidth);
1880
+ if (justify === "left") return text + " ".repeat(space);
1881
+ if (justify === "right") return " ".repeat(space) + text;
1882
+ const leftSpace = Math.floor(space / 2);
1883
+ const rightSpace = space - leftSpace;
1884
+ return " ".repeat(leftSpace) + text + " ".repeat(rightSpace);
1885
+ }
1886
+ __rich_console__(console, consoleOptions) {
1887
+ const width = consoleOptions.width ?? console.width;
1888
+ const box = getBox(this.options.box ?? "rounded");
1889
+ const segments = [];
1890
+ const borderStyle = typeof this.options.borderStyle === "string" ? Style.parse(this.options.borderStyle) : this.options.borderStyle ?? Style.parse("dim");
1891
+ const headerStyle = typeof this.options.headerStyle === "string" ? Style.parse(this.options.headerStyle) : this.options.headerStyle ?? Style.parse("bold cyan");
1892
+ const titleStyle = typeof this.options.titleStyle === "string" ? Style.parse(this.options.titleStyle) : this.options.titleStyle ?? Style.parse("bold");
1893
+ const showLines = this.options.showLines ?? false;
1894
+ const rowStyles = this.options.rowStyles ?? [];
1895
+ const padding = this.options.padding ?? 1;
1896
+ if (!box) return { segments: [], width: 0 };
1897
+ const totalBorderWidth = this.columns.length + 1;
1898
+ const paddingWidth = padding * 2 * this.columns.length;
1899
+ const availableWidth = width - totalBorderWidth - paddingWidth;
1900
+ const colWidth = Math.max(1, Math.floor(availableWidth / this.columns.length));
1901
+ const paddingStr = " ".repeat(padding);
1902
+ if (this.options.title) {
1903
+ const titleLine = this.alignText(this.options.title, width, "center");
1904
+ segments.push(new Segment(titleLine, titleStyle), new Segment("\n", Style.null(), true));
1905
+ }
1906
+ if (this.options.showHeader !== false) {
1907
+ segments.push(
1908
+ new Segment(
1909
+ box.topLeft + this.columns.map(() => (box.top || "\u2500").repeat(colWidth + padding * 2)).join(box.topMid || "\u252C") + box.topRight,
1910
+ borderStyle
1911
+ ),
1912
+ new Segment("\n", Style.null(), true)
1913
+ );
1914
+ segments.push(new Segment(box.left, borderStyle));
1915
+ this.columns.forEach((col, i) => {
1916
+ const text = this.alignText(col.header, colWidth, col.justify);
1917
+ const cellStyle = col.headerStyle.combine(headerStyle);
1918
+ segments.push(new Segment(paddingStr + text + paddingStr, cellStyle));
1919
+ segments.push(
1920
+ new Segment(
1921
+ i === this.columns.length - 1 ? box.right : box.verticalMid || "\u2502",
1922
+ borderStyle
1923
+ )
1924
+ );
1925
+ });
1926
+ segments.push(new Segment("\n", Style.null(), true));
1927
+ segments.push(
1928
+ new Segment(
1929
+ (box.leftMid || "\u251C") + this.columns.map(() => (box.mid || "\u2500").repeat(colWidth + padding * 2)).join(box.midMid || "\u253C") + (box.rightMid || "\u2524"),
1930
+ borderStyle
1931
+ ),
1932
+ new Segment("\n", Style.null(), true)
1933
+ );
1934
+ }
1935
+ this.rows.forEach((row, rowIndex) => {
1936
+ let rowStyle = Style.null();
1937
+ if (rowStyles.length > 0) {
1938
+ const styleStr = rowStyles[rowIndex % rowStyles.length];
1939
+ if (styleStr) {
1940
+ rowStyle = Style.parse(styleStr);
1941
+ }
1942
+ }
1943
+ segments.push(new Segment(box.left, borderStyle));
1944
+ this.columns.forEach((col, i) => {
1945
+ const cell = row[i];
1946
+ let cellSegments = [];
1947
+ if (typeof cell === "string") {
1948
+ const text = this.alignText(cell, colWidth, col.justify);
1949
+ const cellStyle = col.style.combine(rowStyle);
1950
+ cellSegments = [new Segment(paddingStr + text + paddingStr, cellStyle)];
1951
+ } else if (isRenderable(cell)) {
1952
+ const result = getRenderResult(cell, console, { ...consoleOptions, width: colWidth });
1953
+ segments.push(new Segment(paddingStr));
1954
+ cellSegments = result.segments.map((s) => {
1955
+ return new Segment(s.text, s.style.combine(rowStyle), s.isControl);
1956
+ });
1957
+ const contentWidth = result.width ?? 0;
1958
+ const space = Math.max(0, colWidth - contentWidth);
1959
+ if (space > 0) {
1960
+ cellSegments.push(new Segment(" ".repeat(space), rowStyle));
1961
+ }
1962
+ cellSegments.push(new Segment(paddingStr));
1963
+ }
1964
+ segments.push(...cellSegments);
1965
+ segments.push(
1966
+ new Segment(
1967
+ i === this.columns.length - 1 ? box.right : box.verticalMid || "\u2502",
1968
+ borderStyle
1969
+ )
1970
+ );
1971
+ });
1972
+ segments.push(new Segment("\n", Style.null(), true));
1973
+ if (showLines && rowIndex < this.rows.length - 1) {
1974
+ segments.push(
1975
+ new Segment(
1976
+ (box.leftMid || "\u251C") + this.columns.map(() => (box.mid || "\u2500").repeat(colWidth + padding * 2)).join(box.midMid || "\u253C") + (box.rightMid || "\u2524"),
1977
+ borderStyle
1978
+ ),
1979
+ new Segment("\n", Style.null(), true)
1980
+ );
1981
+ }
1982
+ });
1983
+ if (this.options.showFooter && this.footerRow.length > 0) {
1984
+ const footerStyle = typeof this.options.footerStyle === "string" ? Style.parse(this.options.footerStyle) : this.options.footerStyle ?? Style.parse("bold");
1985
+ segments.push(
1986
+ new Segment(
1987
+ (box.leftMid || "\u251C") + this.columns.map(() => (box.mid || "\u2500").repeat(colWidth + padding * 2)).join(box.midMid || "\u253C") + (box.rightMid || "\u2524"),
1988
+ borderStyle
1989
+ ),
1990
+ new Segment("\n", Style.null(), true)
1991
+ );
1992
+ segments.push(new Segment(box.left, borderStyle));
1993
+ this.columns.forEach((col, i) => {
1994
+ const cell = this.footerRow[i];
1995
+ const text = typeof cell === "string" ? cell : "";
1996
+ const alignedText = this.alignText(text, colWidth, col.justify);
1997
+ segments.push(new Segment(paddingStr + alignedText + paddingStr, footerStyle));
1998
+ segments.push(
1999
+ new Segment(
2000
+ i === this.columns.length - 1 ? box.right : box.verticalMid || "\u2502",
2001
+ borderStyle
2002
+ )
2003
+ );
2004
+ });
2005
+ segments.push(new Segment("\n", Style.null(), true));
2006
+ }
2007
+ segments.push(
2008
+ new Segment(
2009
+ box.bottomLeft + this.columns.map(() => (box.bottom || "\u2500").repeat(colWidth + padding * 2)).join(box.bottomMid || "\u2534") + box.bottomRight,
2010
+ borderStyle
2011
+ ),
2012
+ new Segment("\n", Style.null(), true)
2013
+ );
2014
+ if (this.options.caption) {
2015
+ const captionStyle = typeof this.options.captionStyle === "string" ? Style.parse(this.options.captionStyle) : this.options.captionStyle ?? Style.parse("dim italic");
2016
+ const captionLine = this.alignText(this.options.caption, width, "center");
2017
+ segments.push(new Segment(captionLine, captionStyle), new Segment("\n", Style.null(), true));
2018
+ }
2019
+ return { segments, width };
2020
+ }
2021
+ };
2022
+
2023
+ // src/renderables/tree.ts
2024
+ var TREE_GUIDES = {
2025
+ standard: {
2026
+ branch: "\u251C\u2500\u2500 ",
2027
+ last: "\u2514\u2500\u2500 ",
2028
+ vertical: "\u2502 ",
2029
+ space: " "
2030
+ },
2031
+ bold: {
2032
+ branch: "\u2523\u2501\u2501 ",
2033
+ last: "\u2517\u2501\u2501 ",
2034
+ vertical: "\u2503 ",
2035
+ space: " "
2036
+ },
2037
+ double: {
2038
+ branch: "\u2560\u2550\u2550 ",
2039
+ last: "\u255A\u2550\u2550 ",
2040
+ vertical: "\u2551 ",
2041
+ space: " "
2042
+ },
2043
+ ascii: {
2044
+ branch: "|-- ",
2045
+ last: "`-- ",
2046
+ vertical: "| ",
2047
+ space: " "
2048
+ }
2049
+ };
2050
+ var Tree = class _Tree {
2051
+ constructor(label, options = {}) {
2052
+ this.label = label;
2053
+ this.options = options;
2054
+ this.guideStyle = Style.parse(options.guideStyle ?? "#6e7681 dim");
2055
+ if (options.guideStyle === "bold") {
2056
+ this.guides = TREE_GUIDES.bold;
2057
+ } else if (options.guideStyle === "double") {
2058
+ this.guides = TREE_GUIDES.double;
2059
+ } else if (options.guideStyle === "ascii") {
2060
+ this.guides = TREE_GUIDES.ascii;
2061
+ } else {
2062
+ this.guides = TREE_GUIDES.standard;
2063
+ }
2064
+ }
2065
+ children = [];
2066
+ guideStyle;
2067
+ guides;
2068
+ /**
2069
+ * Add a child node to the tree.
2070
+ * Returns the added Tree node for method chaining.
2071
+ */
2072
+ add(label) {
2073
+ if (label instanceof _Tree) {
2074
+ this.children.push(label);
2075
+ return label;
2076
+ }
2077
+ const node = new _Tree(label, this.options);
2078
+ this.children.push(node);
2079
+ return node;
2080
+ }
2081
+ __rich_console__(console, options) {
2082
+ const segments = [];
2083
+ if (!this.options.hideRoot) {
2084
+ this.renderLabel(this.label, segments, console, options);
2085
+ segments.push(new Segment("\n", Style.null(), true));
2086
+ }
2087
+ this.renderChildren(this.children, "", segments, console, options);
2088
+ return { segments, width: 0 };
2089
+ }
2090
+ /**
2091
+ * Render a label (string or renderable) and add segments.
2092
+ */
2093
+ renderLabel(label, segments, console, options) {
2094
+ if (typeof label === "string") {
2095
+ segments.push(new Segment(label));
2096
+ } else if (isRenderable(label)) {
2097
+ const result = label.__rich_console__(console, options);
2098
+ if ("segments" in result) {
2099
+ const labelSegments = result.segments.filter((s) => !s.isControl || s.text !== "\n");
2100
+ segments.push(...labelSegments);
2101
+ }
2102
+ }
2103
+ }
2104
+ /**
2105
+ * Render child nodes with appropriate prefixes.
2106
+ */
2107
+ renderChildren(children, prefix, segments, console, options) {
2108
+ children.forEach((child, index) => {
2109
+ const isLast = index === children.length - 1;
2110
+ const connector = isLast ? this.guides.last : this.guides.branch;
2111
+ const continuation = isLast ? this.guides.space : this.guides.vertical;
2112
+ const labelSegments = [];
2113
+ if (typeof child.label === "string") {
2114
+ labelSegments.push(new Segment(child.label));
2115
+ } else if (isRenderable(child.label)) {
2116
+ const result = child.label.__rich_console__(console, options);
2117
+ if ("segments" in result) {
2118
+ labelSegments.push(...result.segments);
2119
+ }
2120
+ }
2121
+ const labelLines = splitLines(labelSegments);
2122
+ if (labelLines.length > 0) {
2123
+ segments.push(new Segment(prefix, this.guideStyle));
2124
+ segments.push(new Segment(connector, this.guideStyle));
2125
+ segments.push(...labelLines[0]);
2126
+ segments.push(new Segment("\n", Style.null(), true));
2127
+ }
2128
+ for (let i = 1; i < labelLines.length; i++) {
2129
+ segments.push(new Segment(prefix, this.guideStyle));
2130
+ segments.push(new Segment(continuation, this.guideStyle));
2131
+ segments.push(...labelLines[i]);
2132
+ segments.push(new Segment("\n", Style.null(), true));
2133
+ }
2134
+ const newPrefix = prefix + continuation;
2135
+ this.renderChildren(child.children, newPrefix, segments, console, options);
2136
+ });
2137
+ }
2138
+ };
2139
+
2140
+ // src/layout/grid.ts
2141
+ var Grid = class extends Layout {
2142
+ constructor() {
2143
+ super();
2144
+ }
2145
+ /**
2146
+ * Adds a row to the grid with optional constraints.
2147
+ */
2148
+ addRow(content, options = {}) {
2149
+ const layout = content instanceof Layout ? content : new Layout(content, options);
2150
+ if (!(content instanceof Layout)) {
2151
+ layout.size = options.size;
2152
+ layout.ratio = options.ratio ?? 1;
2153
+ layout.minimumSize = options.minimumSize ?? 0;
2154
+ }
2155
+ this.splitColumn(...this["_children"] || [], layout);
2156
+ }
2157
+ };
2158
+
2159
+ // src/renderables/padding.ts
2160
+ var Padding = class {
2161
+ constructor(renderable, padding) {
2162
+ this.renderable = renderable;
2163
+ if (typeof padding === "number") {
2164
+ this.top = this.right = this.bottom = this.left = padding;
2165
+ } else if (Array.isArray(padding)) {
2166
+ if (padding.length === 2) {
2167
+ this.top = this.bottom = padding[0];
2168
+ this.right = this.left = padding[1];
2169
+ } else {
2170
+ [this.top, this.right, this.bottom, this.left] = padding;
2171
+ }
2172
+ } else {
2173
+ this.top = this.right = this.bottom = this.left = 0;
2174
+ }
2175
+ }
2176
+ top;
2177
+ right;
2178
+ bottom;
2179
+ left;
2180
+ __rich_console__(console, options) {
2181
+ const width = options.width ?? console.width;
2182
+ const innerWidth = Math.max(0, width - this.left - this.right);
2183
+ let contentSegments = [];
2184
+ if (typeof this.renderable === "string") {
2185
+ contentSegments = [new Segment(this.renderable)];
2186
+ } else if (isRenderable(this.renderable)) {
2187
+ const result = this.renderable.__rich_console__(console, { ...options, width: innerWidth });
2188
+ if ("segments" in result) contentSegments = result.segments;
2189
+ }
2190
+ const lines = splitLines(contentSegments);
2191
+ const segments = [];
2192
+ for (let i = 0; i < this.top; i++) {
2193
+ segments.push(new Segment(" ".repeat(width) + "\n"));
2194
+ }
2195
+ const leftPad = " ".repeat(this.left);
2196
+ for (const line of lines) {
2197
+ segments.push(new Segment(leftPad));
2198
+ segments.push(...line);
2199
+ segments.push(new Segment("\n"));
2200
+ }
2201
+ for (let i = 0; i < this.bottom; i++) {
2202
+ segments.push(new Segment(" ".repeat(width) + "\n"));
2203
+ }
2204
+ return { segments, width };
2205
+ }
2206
+ };
2207
+
2208
+ // src/renderables/align.ts
2209
+ var Align = class _Align {
2210
+ constructor(renderable, align, style) {
2211
+ this.renderable = renderable;
2212
+ this.align = align;
2213
+ this.style = style;
2214
+ }
2215
+ static left(renderable) {
2216
+ return new _Align(renderable, "left");
2217
+ }
2218
+ static center(renderable) {
2219
+ return new _Align(renderable, "center");
2220
+ }
2221
+ static right(renderable) {
2222
+ return new _Align(renderable, "right");
2223
+ }
2224
+ __rich_console__(console, options) {
2225
+ const width = options.width ?? console.width;
2226
+ let contentSegments = [];
2227
+ if (typeof this.renderable === "string") {
2228
+ contentSegments = [new Segment(this.renderable)];
2229
+ } else if (isRenderable(this.renderable)) {
2230
+ const result = this.renderable.__rich_console__(console, options);
2231
+ if ("segments" in result) contentSegments = result.segments;
2232
+ }
2233
+ const lines = splitLines(contentSegments);
2234
+ const segments = [];
2235
+ for (const line of lines) {
2236
+ const lineWidth = line.reduce((acc, s) => acc + s.cellLength(), 0);
2237
+ const remaining = Math.max(0, width - lineWidth);
2238
+ if (remaining === 0) {
2239
+ segments.push(...line);
2240
+ } else {
2241
+ let leftSpace = 0;
2242
+ if (this.align === "center") leftSpace = Math.floor(remaining / 2);
2243
+ else if (this.align === "right") leftSpace = remaining;
2244
+ if (leftSpace > 0) segments.push(new Segment(" ".repeat(leftSpace)));
2245
+ segments.push(...line);
2246
+ }
2247
+ segments.push(new Segment("\n"));
2248
+ }
2249
+ return { segments, width };
2250
+ }
2251
+ };
2252
+ var Prompt = class {
2253
+ static async ask(message, options = {}) {
2254
+ const console = options.console ?? new Console();
2255
+ const rl = readline.createInterface({
2256
+ input: process.stdin,
2257
+ output: process.stdout,
2258
+ terminal: true
2259
+ });
2260
+ const defaultStr = options.default !== void 0 ? ` [default: ${options.default}]` : "";
2261
+ const choicesStr = options.choices ? ` [${options.choices.join("/")}]` : "";
2262
+ const query = `${message}${choicesStr}${defaultStr}: `;
2263
+ console.print(query);
2264
+ return new Promise((resolve) => {
2265
+ const askQuestion = () => {
2266
+ process.stdout.write("> ");
2267
+ rl.question("", (answer) => {
2268
+ let value = answer.trim();
2269
+ if (value === "" && options.default !== void 0) {
2270
+ value = String(options.default);
2271
+ }
2272
+ if (options.choices && !options.choices.includes(value)) {
2273
+ console.print(`[red]Please select one of: ${options.choices.join(", ")}[/]`);
2274
+ askQuestion();
2275
+ return;
2276
+ }
2277
+ if (options.validate) {
2278
+ const validation = options.validate(value);
2279
+ if (validation !== true) {
2280
+ const msg = typeof validation === "string" ? validation : "Invalid input";
2281
+ console.print(`[red]${msg}[/]`);
2282
+ askQuestion();
2283
+ return;
2284
+ }
2285
+ }
2286
+ rl.close();
2287
+ resolve(value);
2288
+ });
2289
+ };
2290
+ askQuestion();
2291
+ });
2292
+ }
2293
+ };
2294
+
2295
+ // src/prompt/confirm.ts
2296
+ var Confirm = class {
2297
+ static async ask(message, options = {}) {
2298
+ const defaultValue = options.default ?? true;
2299
+ const choices = defaultValue ? ["Y", "n"] : ["y", "N"];
2300
+ const answer = await Prompt.ask(message, {
2301
+ ...options,
2302
+ choices,
2303
+ default: defaultValue ? "y" : "n",
2304
+ validate: (input) => {
2305
+ const norm2 = input.toLowerCase();
2306
+ return norm2 === "y" || norm2 === "yes" || norm2 === "n" || norm2 === "no";
2307
+ }
2308
+ });
2309
+ const norm = answer.toLowerCase();
2310
+ return norm === "y" || norm === "yes";
2311
+ }
2312
+ };
2313
+
2314
+ // src/logging/handler.ts
2315
+ var RichHandler = class {
2316
+ console;
2317
+ constructor(console) {
2318
+ this.console = console ?? new Console();
2319
+ }
2320
+ handle(record) {
2321
+ const time = record.timestamp.toLocaleTimeString();
2322
+ const levelStyle = this.getLevelStyle(record.level);
2323
+ const parts = [
2324
+ `[dim]${time}[/dim]`,
2325
+ // Pad level to align messages
2326
+ new Segment(` ${record.level.toUpperCase()} `.padEnd(7), levelStyle),
2327
+ record.message
2328
+ ];
2329
+ if (record.context && Object.keys(record.context).length > 0) {
2330
+ parts.push(`[dim]${JSON.stringify(record.context)}[/dim]`);
2331
+ }
2332
+ this.console.print(...parts);
2333
+ }
2334
+ getLevelStyle(level) {
2335
+ switch (level) {
2336
+ case "debug":
2337
+ return Style.parse("dim cyan");
2338
+ case "info":
2339
+ return Style.parse("green");
2340
+ case "warn":
2341
+ return Style.parse("yellow");
2342
+ case "error":
2343
+ return Style.parse("bold red");
2344
+ default:
2345
+ return Style.null();
2346
+ }
2347
+ }
2348
+ };
2349
+
2350
+ // src/hooks/install.ts
2351
+ function install(consoleOptions = {}) {
2352
+ if (global.__rich_installed__) return;
2353
+ const richConsole = new Console(consoleOptions);
2354
+ const handler = new RichHandler(richConsole);
2355
+ const originalLog = global.console.log;
2356
+ const originalWarn = global.console.warn;
2357
+ const originalError = global.console.error;
2358
+ global.console.log = (...args) => {
2359
+ richConsole.print(...args);
2360
+ };
2361
+ global.console.warn = (...args) => {
2362
+ handler.handle({
2363
+ level: "warn",
2364
+ message: args.map(String).join(" "),
2365
+ timestamp: /* @__PURE__ */ new Date()
2366
+ });
2367
+ };
2368
+ global.console.error = (...args) => {
2369
+ handler.handle({
2370
+ level: "error",
2371
+ message: args.map(String).join(" "),
2372
+ timestamp: /* @__PURE__ */ new Date()
2373
+ });
2374
+ };
2375
+ global.__rich_installed__ = true;
2376
+ global.__rich_original_console__ = {
2377
+ log: originalLog,
2378
+ warn: originalWarn,
2379
+ error: originalError
2380
+ };
2381
+ }
2382
+ marked.setOptions({
2383
+ renderer: new TerminalRenderer()
2384
+ });
2385
+ var Markdown = class {
2386
+ constructor(markup) {
2387
+ this.markup = markup;
2388
+ }
2389
+ __rich_console__(_console, _options) {
2390
+ const rendered = marked.parse(this.markup);
2391
+ return {
2392
+ segments: [new Segment(rendered)],
2393
+ width: 0
2394
+ // Placeholder
2395
+ };
2396
+ }
2397
+ };
2398
+
2399
+ // src/progress/bar.ts
2400
+ var ProgressBar = class {
2401
+ constructor(total = 100, completed = 0, options = {}) {
2402
+ this.total = total;
2403
+ this.completed = completed;
2404
+ this.options = options;
2405
+ }
2406
+ pulseOffset = 0;
2407
+ lastPulseTime = 0;
2408
+ __rich_console__(console, consoleOptions) {
2409
+ const width = this.options.width ?? Math.min(40, (consoleOptions.width ?? console.width) - 20);
2410
+ const percentage = Math.min(1, Math.max(0, this.completed / this.total));
2411
+ const isComplete = percentage >= 1;
2412
+ const isPulse = this.options.pulse ?? false;
2413
+ const completeChar = this.options.completeChar ?? "\u2501";
2414
+ const remainingChar = this.options.remainingChar ?? "\u2501";
2415
+ const completeStyleStr = isComplete ? this.options.finishedStyle ?? "#50fa7b bold" : this.options.completeStyle ?? "#61afef";
2416
+ const remainingStyleStr = this.options.remainingStyle ?? "#3a3a3a dim";
2417
+ const pulseStyleStr = this.options.pulseStyle ?? "#98c379 bold";
2418
+ const completeStyle = Style.parse(completeStyleStr);
2419
+ const remainingStyle = Style.parse(remainingStyleStr);
2420
+ const pulseStyle = Style.parse(pulseStyleStr);
2421
+ const filledWidth = Math.floor(width * percentage);
2422
+ const segments = [];
2423
+ if (isPulse && !isComplete) {
2424
+ const now = Date.now();
2425
+ if (now - this.lastPulseTime > 100) {
2426
+ this.pulseOffset = (this.pulseOffset + 1) % width;
2427
+ this.lastPulseTime = now;
2428
+ }
2429
+ for (let i = 0; i < width; i++) {
2430
+ const isPulsePos = Math.abs(i - this.pulseOffset) < 3;
2431
+ const style = isPulsePos ? pulseStyle : remainingStyle;
2432
+ segments.push(new Segment(remainingChar, style));
2433
+ }
2434
+ } else {
2435
+ if (filledWidth > 0) {
2436
+ if (width >= 20 && !isComplete) {
2437
+ const gradientColors = ["#61afef", "#66d9ef", "#50fa7b"];
2438
+ for (let i = 0; i < filledWidth; i++) {
2439
+ const colorIndex = Math.floor(i / filledWidth * gradientColors.length);
2440
+ const color = gradientColors[Math.min(colorIndex, gradientColors.length - 1)];
2441
+ segments.push(new Segment(completeChar, Style.parse(color)));
2442
+ }
2443
+ } else {
2444
+ segments.push(new Segment(completeChar.repeat(filledWidth), completeStyle));
2445
+ }
2446
+ }
2447
+ const remainingWidth = width - filledWidth;
2448
+ if (remainingWidth > 0) {
2449
+ segments.push(new Segment(remainingChar.repeat(remainingWidth), remainingStyle));
2450
+ }
2451
+ }
2452
+ return {
2453
+ segments,
2454
+ width
2455
+ };
2456
+ }
2457
+ };
2458
+ var PercentageColumn = class {
2459
+ constructor(percentage, style) {
2460
+ this.percentage = percentage;
2461
+ this.style = style;
2462
+ }
2463
+ __rich_console__(_console, _options) {
2464
+ const pct = Math.floor(this.percentage * 100);
2465
+ const text = `${pct.toString().padStart(3)}%`;
2466
+ const style = Style.parse(this.style ?? (pct >= 100 ? "#50fa7b bold" : "#61afef"));
2467
+ return {
2468
+ segments: [new Segment(text, style)],
2469
+ width: 4
2470
+ };
2471
+ }
2472
+ };
2473
+ var TimeElapsedColumn = class {
2474
+ constructor(elapsedMs, style) {
2475
+ this.elapsedMs = elapsedMs;
2476
+ this.style = style;
2477
+ }
2478
+ __rich_console__(_console, _options) {
2479
+ const seconds = Math.floor(this.elapsedMs / 1e3);
2480
+ const minutes = Math.floor(seconds / 60);
2481
+ const hours = Math.floor(minutes / 60);
2482
+ let text;
2483
+ if (hours > 0) {
2484
+ text = `${hours}:${(minutes % 60).toString().padStart(2, "0")}:${(seconds % 60).toString().padStart(2, "0")}`;
2485
+ } else if (minutes > 0) {
2486
+ text = `${minutes}:${(seconds % 60).toString().padStart(2, "0")}`;
2487
+ } else {
2488
+ text = `0:${seconds.toString().padStart(2, "0")}`;
2489
+ }
2490
+ const style = Style.parse(this.style ?? "#e5c07b");
2491
+ return {
2492
+ segments: [new Segment(text, style)],
2493
+ width: text.length
2494
+ };
2495
+ }
2496
+ };
2497
+ var TimeRemainingColumn = class {
2498
+ constructor(percentage, elapsedMs, style) {
2499
+ this.percentage = percentage;
2500
+ this.elapsedMs = elapsedMs;
2501
+ this.style = style;
2502
+ }
2503
+ __rich_console__(_console, _options) {
2504
+ if (this.percentage <= 0 || this.percentage >= 1) {
2505
+ const text2 = "-:--";
2506
+ return {
2507
+ segments: [new Segment(text2, Style.parse(this.style ?? "dim"))],
2508
+ width: 4
2509
+ };
2510
+ }
2511
+ const estimatedTotal = this.elapsedMs / this.percentage;
2512
+ const remainingMs = estimatedTotal - this.elapsedMs;
2513
+ const seconds = Math.floor(remainingMs / 1e3);
2514
+ const minutes = Math.floor(seconds / 60);
2515
+ const hours = Math.floor(minutes / 60);
2516
+ let text;
2517
+ if (hours > 0) {
2518
+ text = `${hours}:${(minutes % 60).toString().padStart(2, "0")}:${(seconds % 60).toString().padStart(2, "0")}`;
2519
+ } else if (minutes > 0) {
2520
+ text = `${minutes}:${(seconds % 60).toString().padStart(2, "0")}`;
2521
+ } else {
2522
+ text = `0:${seconds.toString().padStart(2, "0")}`;
2523
+ }
2524
+ const style = Style.parse(this.style ?? "#c678dd");
2525
+ return {
2526
+ segments: [new Segment(text, style)],
2527
+ width: text.length
2528
+ };
2529
+ }
2530
+ };
2531
+
2532
+ // src/progress/progress.ts
2533
+ var Progress = class {
2534
+ tasks = [];
2535
+ live;
2536
+ console;
2537
+ taskIdCounter = 0;
2538
+ constructor(options = {}) {
2539
+ this.console = options.console ?? new Console();
2540
+ this.live = new Live(new Layout(), this.console);
2541
+ }
2542
+ addTask(description, options = {}) {
2543
+ const taskId = this.taskIdCounter++;
2544
+ this.tasks.push({
2545
+ id: taskId,
2546
+ description,
2547
+ total: options.total ?? 100,
2548
+ completed: options.completed ?? 0,
2549
+ visible: true,
2550
+ finished: false,
2551
+ startTime: Date.now(),
2552
+ endTime: null
2553
+ });
2554
+ this.refresh();
2555
+ return taskId;
2556
+ }
2557
+ update(taskId, options) {
2558
+ const task = this.tasks.find((t) => t.id === taskId);
2559
+ if (!task) return;
2560
+ if (options.completed !== void 0) task.completed = options.completed;
2561
+ if (options.description !== void 0) task.description = options.description;
2562
+ if (task.completed >= task.total) {
2563
+ task.finished = true;
2564
+ task.endTime = Date.now();
2565
+ }
2566
+ this.refresh();
2567
+ }
2568
+ start() {
2569
+ this.live.start();
2570
+ }
2571
+ stop() {
2572
+ this.live.stop();
2573
+ }
2574
+ refresh() {
2575
+ const layout = new Layout();
2576
+ const children = this.tasks.filter((t) => t.visible).map((task) => {
2577
+ const row = new Layout();
2578
+ row.splitRow(
2579
+ new Text(task.description, void 0, "right"),
2580
+ // Label
2581
+ new ProgressBar(task.total, task.completed),
2582
+ // Bar
2583
+ new Text(`${Math.floor(task.completed / task.total * 100)}%`)
2584
+ // Percent
2585
+ );
2586
+ return row;
2587
+ });
2588
+ layout.splitColumn(...children);
2589
+ this.live.update(layout);
2590
+ }
2591
+ };
2592
+
2593
+ // src/progress/track.ts
2594
+ function* track(sequence, description = "Working...") {
2595
+ const progress = new Progress();
2596
+ const arr = Array.isArray(sequence) ? sequence : Array.from(sequence);
2597
+ const total = arr.length;
2598
+ progress.start();
2599
+ const taskId = progress.addTask(description, { total });
2600
+ try {
2601
+ for (let i = 0; i < total; i++) {
2602
+ yield arr[i];
2603
+ progress.update(taskId, { completed: i + 1 });
2604
+ }
2605
+ } finally {
2606
+ progress.stop();
2607
+ }
2608
+ }
2609
+
2610
+ // src/logging/logger.ts
2611
+ var Logger = class {
2612
+ handler;
2613
+ constructor(console) {
2614
+ this.handler = new RichHandler(console);
2615
+ }
2616
+ debug(message, context) {
2617
+ this.log("debug", message, context);
2618
+ }
2619
+ info(message, context) {
2620
+ this.log("info", message, context);
2621
+ }
2622
+ warn(message, context) {
2623
+ this.log("warn", message, context);
2624
+ }
2625
+ error(message, context) {
2626
+ this.log("error", message, context);
2627
+ }
2628
+ log(level, message, context) {
2629
+ const record = {
2630
+ level,
2631
+ message,
2632
+ timestamp: /* @__PURE__ */ new Date(),
2633
+ context
2634
+ };
2635
+ this.handler.handle(record);
2636
+ }
2637
+ };
2638
+
2639
+ // src/utils/inspect.ts
2640
+ function inspect(obj, options = {}) {
2641
+ const console = new Console();
2642
+ const title = options.title ?? `Inspect: ${obj?.constructor?.name ?? typeof obj}`;
2643
+ const table = new Table({ box: "single", showHeader: true });
2644
+ table.addColumn("Property", { style: "cyan" });
2645
+ table.addColumn("Type", { style: "magenta" });
2646
+ table.addColumn("Value");
2647
+ const props = Object.getOwnPropertyNames(obj);
2648
+ props.sort();
2649
+ for (const prop of props) {
2650
+ const value = obj[prop];
2651
+ let type = typeof value;
2652
+ let valueStr = String(value);
2653
+ if (value === null) type = "null";
2654
+ else if (Array.isArray(value)) type = "Array";
2655
+ if (valueStr.length > 50) valueStr = valueStr.substring(0, 47) + "...";
2656
+ table.addRow(prop, type, valueStr);
2657
+ }
2658
+ let json = "";
2659
+ try {
2660
+ json = JSON.stringify(obj, null, 2);
2661
+ } catch {
2662
+ json = "[Circular]";
2663
+ }
2664
+ new Syntax(json, "json");
2665
+ console.print(new Panel(table, { title, box: "round", borderStyle: void 0 }));
2666
+ }
2667
+
2668
+ // src/index.ts
2669
+ var globalConsole = new Console();
2670
+ var print = globalConsole.print.bind(globalConsole);
2671
+
2672
+ export { Align, Color, Confirm, Console, DEFAULT_THEME, DRACULA, GITHUB_LIGHT, Grid, Layout, Logger, MONOKAI, MONOKAI_THEME, Markdown, MarkupParser, ONE_DARK, Padding, Palette, Panel, PercentageColumn, Progress, ProgressBar, Prompt, RichHandler, Rule, SYNTAX_THEMES, Segment, Spinner, Status, Style, Syntax, Table, Text, Theme, TimeElapsedColumn, TimeRemainingColumn, Traceback, Tree, getBox, getTheme, inspect, install, installTracebackHandler, isRenderable, listBoxStyles, print, track };
2673
+ //# sourceMappingURL=index.js.map
2674
+ //# sourceMappingURL=index.js.map