bktide 1.0.1755266193 → 1.0.1755547716

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.
Files changed (75) hide show
  1. package/README.md +107 -1
  2. package/WORKFLOW_README.md +1 -1
  3. package/completions/bktide-dynamic.fish +171 -0
  4. package/completions/bktide.bash +124 -0
  5. package/completions/bktide.fish +107 -0
  6. package/completions/bktide.zsh +139 -0
  7. package/dist/commands/BaseCommand.js +7 -7
  8. package/dist/commands/BaseCommand.js.map +1 -1
  9. package/dist/commands/GenerateCompletions.js +238 -0
  10. package/dist/commands/GenerateCompletions.js.map +1 -0
  11. package/dist/commands/ListAnnotations.js +7 -0
  12. package/dist/commands/ListAnnotations.js.map +1 -1
  13. package/dist/commands/ListBuilds.js +67 -3
  14. package/dist/commands/ListBuilds.js.map +1 -1
  15. package/dist/commands/ListOrganizations.js +6 -0
  16. package/dist/commands/ListOrganizations.js.map +1 -1
  17. package/dist/commands/ListPipelines.js +87 -12
  18. package/dist/commands/ListPipelines.js.map +1 -1
  19. package/dist/commands/ManageToken.js +32 -9
  20. package/dist/commands/ManageToken.js.map +1 -1
  21. package/dist/commands/ShowViewer.js +7 -1
  22. package/dist/commands/ShowViewer.js.map +1 -1
  23. package/dist/commands/index.js +1 -0
  24. package/dist/commands/index.js.map +1 -1
  25. package/dist/formatters/annotations/PlainTextFormatter.js +37 -9
  26. package/dist/formatters/annotations/PlainTextFormatter.js.map +1 -1
  27. package/dist/formatters/builds/PlainTextFormatter.js +82 -60
  28. package/dist/formatters/builds/PlainTextFormatter.js.map +1 -1
  29. package/dist/formatters/errors/AlfredFormatter.js +20 -0
  30. package/dist/formatters/errors/AlfredFormatter.js.map +1 -1
  31. package/dist/formatters/errors/PlainTextFormatter.js +121 -23
  32. package/dist/formatters/errors/PlainTextFormatter.js.map +1 -1
  33. package/dist/formatters/organizations/PlainTextFormatter.js +37 -6
  34. package/dist/formatters/organizations/PlainTextFormatter.js.map +1 -1
  35. package/dist/formatters/pipelines/AlfredFormatter.js.map +1 -1
  36. package/dist/formatters/pipelines/Formatter.js.map +1 -1
  37. package/dist/formatters/pipelines/JsonFormatter.js.map +1 -1
  38. package/dist/formatters/pipelines/PlainTextFormatter.js +165 -19
  39. package/dist/formatters/pipelines/PlainTextFormatter.js.map +1 -1
  40. package/dist/formatters/token/AlfredFormatter.js +15 -2
  41. package/dist/formatters/token/AlfredFormatter.js.map +1 -1
  42. package/dist/formatters/token/PlainTextFormatter.js +56 -18
  43. package/dist/formatters/token/PlainTextFormatter.js.map +1 -1
  44. package/dist/formatters/viewer/PlainTextFormatter.js +8 -7
  45. package/dist/formatters/viewer/PlainTextFormatter.js.map +1 -1
  46. package/dist/index.js +47 -6
  47. package/dist/index.js.map +1 -1
  48. package/dist/services/CredentialManager.js +80 -10
  49. package/dist/services/CredentialManager.js.map +1 -1
  50. package/dist/ui/help.js +69 -0
  51. package/dist/ui/help.js.map +1 -0
  52. package/dist/ui/progress.js +356 -0
  53. package/dist/ui/progress.js.map +1 -0
  54. package/dist/ui/reporter.js +111 -0
  55. package/dist/ui/reporter.js.map +1 -0
  56. package/dist/ui/responsive-table.js +183 -0
  57. package/dist/ui/responsive-table.js.map +1 -0
  58. package/dist/ui/spinner.js +20 -0
  59. package/dist/ui/spinner.js.map +1 -0
  60. package/dist/ui/symbols.js +46 -0
  61. package/dist/ui/symbols.js.map +1 -0
  62. package/dist/ui/table.js +32 -0
  63. package/dist/ui/table.js.map +1 -0
  64. package/dist/ui/theme.js +280 -0
  65. package/dist/ui/theme.js.map +1 -0
  66. package/dist/ui/width.js +111 -0
  67. package/dist/ui/width.js.map +1 -0
  68. package/dist/utils/alfred.js +6 -0
  69. package/dist/utils/alfred.js.map +1 -0
  70. package/dist/utils/cli-error-handler.js +35 -20
  71. package/dist/utils/cli-error-handler.js.map +1 -1
  72. package/dist/utils/pagination.js +92 -0
  73. package/dist/utils/pagination.js.map +1 -0
  74. package/info.plist +51 -218
  75. package/package.json +23 -5
@@ -0,0 +1 @@
1
+ {"version":3,"file":"progress.js","sourceRoot":"/","sources":["ui/progress.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Unified progress indicator system\n * Provides both determinate (bar) and indeterminate (spinner) progress indicators\n */\n\nimport { COLORS, SYMBOLS } from './theme.js';\nimport { termWidth, truncate } from './width.js';\n\n/**\n * Check if output format is machine-readable\n */\nfunction isMachineFormat(format?: string): boolean {\n const f = (format || '').toLowerCase();\n return f === 'json' || f === 'alfred';\n}\n\n/**\n * Check if we should show progress indicators\n */\nfunction shouldShowProgress(format?: string): boolean {\n // Don't show in non-TTY environments\n if (!process.stderr.isTTY) return false;\n \n // Don't show for machine formats\n if (format && isMachineFormat(format)) return false;\n \n // Don't show in CI environments\n if (process.env.CI) return false;\n \n // Don't show if NO_COLOR is set (indicates non-interactive)\n if (process.env.NO_COLOR) return false;\n \n return true;\n}\n\n/**\n * Base interface for all progress indicators\n */\nexport interface IProgress {\n /** Update the progress indicator */\n update(value: number | string, label?: string): void;\n \n /** Stop the progress indicator */\n stop(): void;\n \n /** Complete with a success message */\n complete(message?: string): void;\n \n /** Fail with an error message */\n fail(message?: string): void;\n}\n\n/**\n * Spinner for indeterminate progress\n * Shows animated spinner with updating label\n */\nclass Spinner implements IProgress {\n private interval?: NodeJS.Timeout;\n private frame = 0;\n private frames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];\n private label: string = '';\n private lastLineLength = 0;\n private isActive = false;\n private stream: NodeJS.WriteStream = process.stderr;\n \n constructor(\n label?: string,\n private format?: string\n ) {\n if (label) this.label = label;\n }\n\n private shouldShow(): boolean {\n return shouldShowProgress(this.format);\n }\n\n start(): void {\n if (!this.shouldShow() || this.isActive) return;\n \n this.isActive = true;\n this.interval = setInterval(() => {\n this.render();\n this.frame = (this.frame + 1) % this.frames.length;\n }, 80);\n }\n\n update(_value: number | string, label?: string): void {\n // For spinner, we only care about label updates\n if (label !== undefined) {\n this.label = label;\n }\n if (!this.isActive) {\n this.start();\n }\n }\n\n stop(): void {\n if (!this.isActive) return;\n \n if (this.interval) {\n clearInterval(this.interval);\n this.interval = undefined;\n }\n this.clear();\n this.isActive = false;\n }\n\n complete(message?: string): void {\n this.stop();\n if (message && this.shouldShow()) {\n this.stream.write(COLORS.success(`${SYMBOLS.success} ${message}\\n`));\n }\n }\n\n fail(message?: string): void {\n this.stop();\n if (message && this.shouldShow()) {\n this.stream.write(COLORS.error(`${SYMBOLS.error} ${message}\\n`));\n }\n }\n\n private clear(): void {\n if (!this.stream.isTTY) return;\n this.stream.write('\\r' + ' '.repeat(this.lastLineLength) + '\\r');\n }\n\n private render(): void {\n if (!this.shouldShow() || !this.isActive) return;\n \n const spinner = COLORS.info(this.frames[this.frame]);\n const line = this.label ? `${spinner} ${this.label}` : spinner;\n \n this.clear();\n this.stream.write(line);\n this.lastLineLength = line.length;\n }\n}\n\n/**\n * Progress bar for determinate progress\n * Shows percentage and optional counts\n */\nclass Bar implements IProgress {\n private current = 0;\n private total: number;\n private barWidth = 30;\n private label?: string;\n private lastLineLength = 0;\n private isActive = false;\n private stream: NodeJS.WriteStream = process.stderr;\n private format?: string;\n \n constructor(\n options: {\n total: number;\n label?: string;\n barWidth?: number;\n format?: string;\n }\n ) {\n this.total = options.total || 100;\n this.label = options.label;\n this.barWidth = options.barWidth || 30;\n this.format = options.format;\n }\n\n private shouldShow(): boolean {\n return shouldShowProgress(this.format);\n }\n\n start(): void {\n if (!this.shouldShow() || this.isActive) return;\n this.isActive = true;\n this.render();\n }\n\n update(value: number | string, label?: string): void {\n if (!this.isActive) {\n this.start();\n }\n \n // For bar, value should be a number\n if (typeof value === 'number') {\n this.current = Math.min(value, this.total);\n }\n \n if (label !== undefined) {\n this.label = label;\n }\n \n if (this.shouldShow() && this.isActive) {\n this.render();\n }\n }\n\n stop(): void {\n if (!this.isActive) return;\n this.clear();\n this.isActive = false;\n }\n\n complete(message?: string): void {\n if (!this.shouldShow()) return;\n \n this.current = this.total;\n this.render();\n this.clear();\n \n if (message) {\n this.stream.write(COLORS.success(`${SYMBOLS.success} ${message}\\n`));\n }\n \n this.isActive = false;\n }\n\n fail(message?: string): void {\n this.stop();\n if (message && this.shouldShow()) {\n this.stream.write(COLORS.error(`${SYMBOLS.error} ${message}\\n`));\n }\n }\n\n private clear(): void {\n if (!this.stream.isTTY) return;\n this.stream.write('\\r' + ' '.repeat(this.lastLineLength) + '\\r');\n }\n\n private render(): void {\n if (!this.shouldShow() || !this.isActive) return;\n \n const percentage = Math.round((this.current / this.total) * 100);\n const filledLength = Math.round((this.current / this.total) * this.barWidth);\n const emptyLength = this.barWidth - filledLength;\n \n const filled = '█'.repeat(filledLength);\n const empty = '░'.repeat(emptyLength);\n const bar = `[${filled}${empty}]`;\n \n const parts: string[] = [];\n \n if (this.label) {\n const maxLabelWidth = Math.max(20, termWidth() - this.barWidth - 20);\n parts.push(truncate(this.label, maxLabelWidth));\n }\n \n parts.push(bar);\n parts.push(`${percentage}%`);\n parts.push(`(${this.current}/${this.total})`);\n \n const line = parts.join(' ');\n \n this.clear();\n this.stream.write(line);\n this.lastLineLength = line.length;\n }\n}\n\n/**\n * No-op progress for non-interactive environments\n */\nclass NoOpProgress implements IProgress {\n update(): void {}\n stop(): void {}\n complete(): void {}\n fail(): void {}\n}\n\n/**\n * Main Progress API - factory methods for creating progress indicators\n */\nexport class Progress {\n /**\n * Create a spinner (indeterminate progress)\n * Use for operations of unknown duration\n */\n static spinner(label?: string, options?: { format?: string }): IProgress {\n if (!shouldShowProgress(options?.format)) {\n return new NoOpProgress();\n }\n \n const spinner = new Spinner(label, options?.format);\n if (label) {\n spinner.start();\n }\n return spinner;\n }\n\n /**\n * Create a progress bar (determinate progress)\n * Use when you know the total number of items\n */\n static bar(options: {\n total: number;\n label?: string;\n format?: string;\n }): IProgress {\n if (!shouldShowProgress(options.format)) {\n return new NoOpProgress();\n }\n \n const bar = new Bar(options);\n bar.start();\n return bar;\n }\n\n /**\n * Smart factory that creates appropriate progress type\n * Creates bar if total is provided, spinner otherwise\n */\n static create(options?: {\n total?: number;\n label?: string;\n format?: string;\n }): IProgress {\n if (!options) {\n return Progress.spinner();\n }\n \n if (options.total !== undefined && options.total > 0) {\n return Progress.bar(options as { total: number; label?: string; format?: string });\n }\n \n return Progress.spinner(options.label, options);\n }\n}\n\n/**\n * Helper for async operations with progress tracking\n */\nexport async function withProgress<T>(\n operation: (progress: IProgress) => Promise<T>,\n options?: {\n total?: number;\n label?: string;\n format?: string;\n successMessage?: string;\n }\n): Promise<T> {\n const progress = Progress.create(options);\n \n try {\n const result = await operation(progress);\n progress.complete(options?.successMessage);\n return result;\n } catch (error) {\n progress.fail(error instanceof Error ? error.message : 'Operation failed');\n throw error;\n }\n}\n\n// ============================================================================\n// Legacy API - for backward compatibility during migration\n// ============================================================================\n\n/**\n * @deprecated Use Progress.bar() instead\n */\nexport class ProgressBar {\n private progress: IProgress;\n \n constructor(options: any) {\n this.progress = Progress.bar({\n total: options.total,\n label: options.label,\n format: options.format\n });\n }\n \n start(): void {\n // Already started in constructor\n }\n \n update(value: number, label?: string): void {\n this.progress.update(value, label);\n }\n \n stop(): void {\n this.progress.stop();\n }\n \n complete(message?: string): void {\n this.progress.complete(message);\n }\n}\n\n/**\n * @deprecated Use Progress.spinner() instead\n */\nexport class IndeterminateProgress {\n private progress: IProgress;\n \n constructor(label?: string, format?: string) {\n this.progress = Progress.spinner(label, { format });\n }\n \n start(): void {\n // Already started if label provided\n }\n \n updateLabel(label: string): void {\n this.progress.update(label, label);\n }\n \n stop(): void {\n this.progress.stop();\n }\n \n complete(message?: string): void {\n this.progress.complete(message);\n }\n}\n\n/**\n * @deprecated Use withProgress() instead\n */\nexport async function withCountedProgress<T>(\n items: T[],\n operation: (item: T, index: number) => Promise<void>,\n options: {\n label?: string;\n format?: string;\n itemLabel?: (item: T, index: number) => string;\n showPercentage?: boolean;\n showCounts?: boolean;\n onComplete?: (count: number) => string;\n } = {}\n): Promise<void> {\n if (!items || items.length === 0) {\n return;\n }\n \n const progress = Progress.bar({\n total: items.length,\n label: options.label || 'Processing',\n format: options.format\n });\n \n try {\n for (let i = 0; i < items.length; i++) {\n const label = options.itemLabel ? \n options.itemLabel(items[i], i) : \n `Processing item ${i + 1}/${items.length}`;\n \n progress.update(i, label);\n await operation(items[i], i);\n }\n \n progress.update(items.length, 'Complete');\n \n const completeMessage = options.onComplete ?\n options.onComplete(items.length) :\n `Processed ${items.length} items`;\n \n progress.complete(completeMessage);\n } catch (error) {\n progress.stop();\n throw error;\n }\n}\n\n/**\n * @deprecated Use withProgress() instead\n */\nexport async function withIndeterminateProgress<T>(\n operation: () => Promise<T>,\n label?: string,\n format?: string,\n successMessage?: string\n): Promise<T> {\n return withProgress(\n operation,\n { label, format, successMessage }\n );\n}"]}
@@ -0,0 +1,111 @@
1
+ import { COLORS, SYMBOLS, shouldDecorate, formatTips, TipStyle } from './theme.js';
2
+ import { termWidth, calculateColumnWidths, formatTableRow } from './width.js';
3
+ function isMachine(format) {
4
+ const f = (format || '').toLowerCase();
5
+ return f === 'json' || f === 'alfred';
6
+ }
7
+ function isInteractive() {
8
+ // Only show decorative messages when stdout is a TTY (not piped/redirected)
9
+ return Boolean(process.stdout.isTTY);
10
+ }
11
+ export class Reporter {
12
+ format;
13
+ quiet;
14
+ showTips;
15
+ constructor(format = 'plain', quiet = false, tips) {
16
+ this.format = format;
17
+ this.quiet = quiet;
18
+ // Tips logic:
19
+ // - If tips is explicitly set (true or false), use that
20
+ // - Otherwise, tips are off if quiet mode is enabled
21
+ // - Default to true (show tips) if not quiet and not explicitly set
22
+ this.showTips = tips !== undefined ? tips : !quiet;
23
+ }
24
+ info(message) {
25
+ if (this.shouldSuppress())
26
+ return;
27
+ this.writeStdout(this.decorate(COLORS.info, `${SYMBOLS.info} ${message}`));
28
+ }
29
+ success(message) {
30
+ if (this.shouldSuppress())
31
+ return;
32
+ this.writeStdout(this.decorate(COLORS.success, `${SYMBOLS.success} ${message}`));
33
+ }
34
+ tip(message) {
35
+ // Tips have their own suppression logic
36
+ if (!this.shouldShowTips())
37
+ return;
38
+ // Use individual style for single tips from reporter
39
+ const formatted = formatTips([message], TipStyle.INDIVIDUAL);
40
+ this.writeStdout(formatted);
41
+ }
42
+ /**
43
+ * Display multiple tips in a grouped format
44
+ */
45
+ tips(messages, style) {
46
+ if (!this.shouldShowTips())
47
+ return;
48
+ const formatted = formatTips(messages, style || TipStyle.GROUPED);
49
+ this.writeStdout(formatted);
50
+ }
51
+ warn(message) {
52
+ // Warnings go to stderr, check stderr TTY status
53
+ if (isMachine(this.format) || !process.stderr.isTTY)
54
+ return;
55
+ this.writeStderr(this.decorate(COLORS.warn, `${SYMBOLS.warn} ${message}`));
56
+ }
57
+ error(message) {
58
+ // Errors go to stderr, check stderr TTY status
59
+ if (isMachine(this.format) || !process.stderr.isTTY)
60
+ return;
61
+ this.writeStderr(this.decorate(COLORS.error, `${SYMBOLS.error} ${message}`));
62
+ }
63
+ table(rows, options) {
64
+ // Tables are data output, not decorative - always show them
65
+ if (!rows.length || isMachine(this.format))
66
+ return;
67
+ // Get terminal width for responsive tables
68
+ const width = termWidth();
69
+ const numColumns = rows[0].length;
70
+ if (options?.preserveWidths) {
71
+ // Legacy behavior: preserve exact widths (may overflow)
72
+ const widths = rows[0].map((_, i) => Math.max(...rows.map(r => (r[i] ?? '').length)));
73
+ const lines = rows.map(r => r.map((c, i) => (c ?? '').padEnd(widths[i])).join(' ')).join('\n');
74
+ this.writeStdout(lines);
75
+ }
76
+ else {
77
+ // New behavior: responsive width-aware tables
78
+ const columnWidths = calculateColumnWidths(numColumns, width);
79
+ const lines = rows.map(row => formatTableRow(row, columnWidths));
80
+ this.writeStdout(lines.join('\n'));
81
+ }
82
+ }
83
+ shouldSuppress() {
84
+ // Suppress decorative messages when:
85
+ // - quiet mode is enabled
86
+ // - machine format (json/alfred)
87
+ // - stdout is not a TTY (piped/redirected)
88
+ return this.quiet || isMachine(this.format) || !isInteractive();
89
+ }
90
+ shouldShowTips() {
91
+ // Tips are shown when:
92
+ // - Not in machine format (json/alfred)
93
+ // - stdout is a TTY (interactive)
94
+ // - showTips flag is true (controlled by --tips/--no-tips/--quiet)
95
+ return !isMachine(this.format) && isInteractive() && this.showTips;
96
+ }
97
+ decorate(fn, s) {
98
+ return shouldDecorate(this.format) ? fn(s) : s;
99
+ }
100
+ writeStdout(s) {
101
+ if (isMachine(this.format))
102
+ return; // keep machine outputs pristine
103
+ process.stdout.write(s + '\n');
104
+ }
105
+ writeStderr(s) {
106
+ if (isMachine(this.format))
107
+ return; // keep machine outputs pristine
108
+ process.stderr.write(s + '\n');
109
+ }
110
+ }
111
+ //# sourceMappingURL=reporter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reporter.js","sourceRoot":"/","sources":["ui/reporter.ts"],"names":[],"mappings":"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","sourcesContent":["import { COLORS, SYMBOLS, shouldDecorate, formatTips, TipStyle } from './theme.js';\nimport { termWidth, calculateColumnWidths, formatTableRow } from './width.js';\n\nfunction isMachine(format?: string): boolean {\n const f = (format || '').toLowerCase();\n return f === 'json' || f === 'alfred';\n}\n\nfunction isInteractive(): boolean {\n // Only show decorative messages when stdout is a TTY (not piped/redirected)\n return Boolean(process.stdout.isTTY);\n}\n\nexport class Reporter {\n private readonly format: string;\n private readonly quiet: boolean;\n private readonly showTips: boolean;\n\n constructor(format: string = 'plain', quiet = false, tips?: boolean) {\n this.format = format;\n this.quiet = quiet;\n \n // Tips logic:\n // - If tips is explicitly set (true or false), use that\n // - Otherwise, tips are off if quiet mode is enabled\n // - Default to true (show tips) if not quiet and not explicitly set\n this.showTips = tips !== undefined ? tips : !quiet;\n }\n\n info(message: string): void {\n if (this.shouldSuppress()) return;\n this.writeStdout(this.decorate(COLORS.info, `${SYMBOLS.info} ${message}`));\n }\n\n success(message: string): void {\n if (this.shouldSuppress()) return;\n this.writeStdout(this.decorate(COLORS.success, `${SYMBOLS.success} ${message}`));\n }\n \n tip(message: string): void {\n // Tips have their own suppression logic\n if (!this.shouldShowTips()) return;\n // Use individual style for single tips from reporter\n const formatted = formatTips([message], TipStyle.INDIVIDUAL);\n this.writeStdout(formatted);\n }\n \n /**\n * Display multiple tips in a grouped format\n */\n tips(messages: string[], style?: TipStyle): void {\n if (!this.shouldShowTips()) return;\n const formatted = formatTips(messages, style || TipStyle.GROUPED);\n this.writeStdout(formatted);\n }\n\n warn(message: string): void {\n // Warnings go to stderr, check stderr TTY status\n if (isMachine(this.format) || !process.stderr.isTTY) return;\n this.writeStderr(this.decorate(COLORS.warn, `${SYMBOLS.warn} ${message}`));\n }\n\n error(message: string): void {\n // Errors go to stderr, check stderr TTY status \n if (isMachine(this.format) || !process.stderr.isTTY) return;\n this.writeStderr(this.decorate(COLORS.error, `${SYMBOLS.error} ${message}`));\n }\n\n table(rows: string[][], options?: { preserveWidths?: boolean }): void {\n // Tables are data output, not decorative - always show them\n if (!rows.length || isMachine(this.format)) return;\n \n // Get terminal width for responsive tables\n const width = termWidth();\n const numColumns = rows[0].length;\n \n if (options?.preserveWidths) {\n // Legacy behavior: preserve exact widths (may overflow)\n const widths = rows[0].map((_, i) => Math.max(...rows.map(r => (r[i] ?? '').length)));\n const lines = rows.map(r => r.map((c, i) => (c ?? '').padEnd(widths[i])).join(' ')).join('\\n');\n this.writeStdout(lines);\n } else {\n // New behavior: responsive width-aware tables\n const columnWidths = calculateColumnWidths(numColumns, width);\n const lines = rows.map(row => formatTableRow(row, columnWidths));\n this.writeStdout(lines.join('\\n'));\n }\n }\n\n private shouldSuppress(): boolean {\n // Suppress decorative messages when:\n // - quiet mode is enabled\n // - machine format (json/alfred)\n // - stdout is not a TTY (piped/redirected)\n return this.quiet || isMachine(this.format) || !isInteractive();\n }\n \n private shouldShowTips(): boolean {\n // Tips are shown when:\n // - Not in machine format (json/alfred)\n // - stdout is a TTY (interactive)\n // - showTips flag is true (controlled by --tips/--no-tips/--quiet)\n return !isMachine(this.format) && isInteractive() && this.showTips;\n }\n\n private decorate(fn: (s: string) => string, s: string): string {\n return shouldDecorate(this.format) ? fn(s) : s;\n }\n\n private writeStdout(s: string): void {\n if (isMachine(this.format)) return; // keep machine outputs pristine\n process.stdout.write(s + '\\n');\n }\n\n private writeStderr(s: string): void {\n if (isMachine(this.format)) return; // keep machine outputs pristine\n process.stderr.write(s + '\\n');\n }\n}\n\n\n"]}
@@ -0,0 +1,183 @@
1
+ /**
2
+ * Responsive table rendering with smart column handling
3
+ */
4
+ import { termWidth, stripAnsi, truncate } from './width.js';
5
+ /**
6
+ * Calculate optimal column widths based on content and terminal width
7
+ */
8
+ function calculateOptimalWidths(rows, columns, availableWidth) {
9
+ const numColumns = columns.length;
10
+ const visibleColumns = new Array(numColumns).fill(true);
11
+ // Calculate content widths (max width needed for each column)
12
+ const contentWidths = columns.map((col, i) => {
13
+ const maxContentWidth = Math.max(stripAnsi(col.header).length, ...rows.map(row => stripAnsi(row[i] ?? '').length));
14
+ return {
15
+ min: col.minWidth ?? 3,
16
+ max: col.maxWidth ?? maxContentWidth,
17
+ content: maxContentWidth,
18
+ priority: col.priority ?? 0
19
+ };
20
+ });
21
+ // Start with ideal widths (content width capped by max)
22
+ let widths = contentWidths.map(cw => Math.min(cw.content, cw.max));
23
+ let totalWidth = widths.reduce((a, b) => a + b, 0);
24
+ // If we fit, return as-is
25
+ if (totalWidth <= availableWidth) {
26
+ return { widths, visibleColumns };
27
+ }
28
+ // Try to shrink columns proportionally
29
+ const shrinkable = contentWidths.map((cw, i) => widths[i] - cw.min);
30
+ const totalShrinkable = shrinkable.reduce((a, b) => a + b, 0);
31
+ if (totalShrinkable > 0) {
32
+ const needToShrink = totalWidth - availableWidth;
33
+ if (needToShrink <= totalShrinkable) {
34
+ // We can fit by shrinking
35
+ const shrinkRatio = needToShrink / totalShrinkable;
36
+ widths = widths.map((w, i) => {
37
+ const shrinkAmount = Math.floor(shrinkable[i] * shrinkRatio);
38
+ return w - shrinkAmount;
39
+ });
40
+ return { widths, visibleColumns };
41
+ }
42
+ }
43
+ // Still doesn't fit - hide low priority columns
44
+ const sortedByPriority = columns
45
+ .map((col, i) => ({ col, index: i, priority: col.priority ?? 0 }))
46
+ .sort((a, b) => a.priority - b.priority);
47
+ // Start with minimum widths
48
+ widths = contentWidths.map(cw => cw.min);
49
+ totalWidth = widths.reduce((a, b) => a + b, 0);
50
+ // Hide columns starting with lowest priority until we fit
51
+ for (const { index } of sortedByPriority) {
52
+ if (totalWidth <= availableWidth)
53
+ break;
54
+ visibleColumns[index] = false;
55
+ totalWidth -= widths[index];
56
+ widths[index] = 0;
57
+ }
58
+ // Expand remaining columns if we have extra space
59
+ const visibleIndices = visibleColumns
60
+ .map((v, i) => v ? i : -1)
61
+ .filter(i => i >= 0);
62
+ if (visibleIndices.length > 0 && totalWidth < availableWidth) {
63
+ const extraSpace = availableWidth - totalWidth;
64
+ const spacePerColumn = Math.floor(extraSpace / visibleIndices.length);
65
+ for (const i of visibleIndices) {
66
+ widths[i] = Math.min(widths[i] + spacePerColumn, contentWidths[i].max);
67
+ }
68
+ }
69
+ return { widths, visibleColumns };
70
+ }
71
+ /**
72
+ * Align text within a given width
73
+ */
74
+ function alignText(text, width, align = 'left') {
75
+ const visibleLength = stripAnsi(text).length;
76
+ if (visibleLength >= width) {
77
+ return text; // No room for alignment
78
+ }
79
+ const padding = width - visibleLength;
80
+ switch (align) {
81
+ case 'right':
82
+ return ' '.repeat(padding) + text;
83
+ case 'center':
84
+ const leftPad = Math.floor(padding / 2);
85
+ const rightPad = padding - leftPad;
86
+ return ' '.repeat(leftPad) + text + ' '.repeat(rightPad);
87
+ default: // left
88
+ return text + ' '.repeat(padding);
89
+ }
90
+ }
91
+ /**
92
+ * Format a single cell with proper width and alignment
93
+ */
94
+ function formatCell(content, width, config) {
95
+ if (width === 0)
96
+ return ''; // Hidden column
97
+ const visibleLength = stripAnsi(content).length;
98
+ // Truncate or pad as needed
99
+ let formatted;
100
+ if (visibleLength > width) {
101
+ if (config.truncate !== false) { // Default to truncate
102
+ formatted = truncate(content, width);
103
+ }
104
+ else {
105
+ // For wrapping, just take first line for now
106
+ formatted = content.substring(0, width);
107
+ }
108
+ }
109
+ else {
110
+ formatted = content;
111
+ }
112
+ // Apply alignment
113
+ return alignText(formatted, width, config.align);
114
+ }
115
+ /**
116
+ * Render a responsive table that adapts to terminal width
117
+ */
118
+ export function renderResponsiveTable(headers, rows, options) {
119
+ const separator = options?.separator ?? ' ';
120
+ const width = options?.width ?? termWidth();
121
+ // Create default column configs if not provided
122
+ const columns = options?.columns ?? headers.map(h => ({
123
+ header: h,
124
+ priority: 0,
125
+ minWidth: 3,
126
+ truncate: true
127
+ }));
128
+ // Combine headers with data for width calculation
129
+ const allRows = [headers, ...rows];
130
+ // Account for separators
131
+ const numSeparators = columns.length - 1;
132
+ const availableWidth = Math.max(columns.length * 3, width - (separator.length * numSeparators));
133
+ // Calculate optimal widths
134
+ const { widths, visibleColumns } = options?.forceAllColumns
135
+ ? { widths: columns.map((_, i) => Math.max(...allRows.map(r => stripAnsi(r[i] ?? '').length))), visibleColumns: new Array(columns.length).fill(true) }
136
+ : calculateOptimalWidths(rows, columns, availableWidth);
137
+ // Filter to visible columns
138
+ const visibleIndices = visibleColumns
139
+ .map((v, i) => v ? i : -1)
140
+ .filter(i => i >= 0);
141
+ if (visibleIndices.length === 0) {
142
+ // Emergency: show at least one column
143
+ visibleIndices.push(0);
144
+ visibleColumns[0] = true;
145
+ widths[0] = availableWidth;
146
+ }
147
+ // Format output
148
+ const lines = [];
149
+ // Format all rows
150
+ for (const row of allRows) {
151
+ const formattedCells = visibleIndices.map(i => formatCell(row[i] ?? '', widths[i], columns[i]));
152
+ lines.push(formattedCells.join(separator).trimEnd());
153
+ }
154
+ return lines.join('\n');
155
+ }
156
+ /**
157
+ * Responsive list rendering for narrow terminals
158
+ */
159
+ export function renderResponsiveList(items, options) {
160
+ const width = options?.width ?? termWidth();
161
+ const labelWidth = options?.labelWidth ?? Math.min(20, Math.floor(width * 0.3));
162
+ const lines = [];
163
+ for (const item of items) {
164
+ const label = truncate(item.label, labelWidth).padEnd(labelWidth);
165
+ const valueWidth = Math.max(10, width - labelWidth - 2);
166
+ const value = truncate(item.value, valueWidth);
167
+ lines.push(`${label} ${value}`);
168
+ }
169
+ return lines.join('\n');
170
+ }
171
+ /**
172
+ * Detect if terminal is narrow
173
+ */
174
+ export function isNarrowTerminal(threshold = 80) {
175
+ return termWidth() < threshold;
176
+ }
177
+ /**
178
+ * Detect if terminal is very narrow (mobile-like)
179
+ */
180
+ export function isMobileTerminal(threshold = 50) {
181
+ return termWidth() < threshold;
182
+ }
183
+ //# sourceMappingURL=responsive-table.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"responsive-table.js","sourceRoot":"/","sources":["ui/responsive-table.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AA4B5D;;GAEG;AACH,SAAS,sBAAsB,CAC7B,IAAgB,EAChB,OAAuB,EACvB,cAAsB;IAEtB,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC;IAClC,MAAM,cAAc,GAAG,IAAI,KAAK,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAExD,8DAA8D;IAC9D,MAAM,aAAa,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE;QAC3C,MAAM,eAAe,GAAG,IAAI,CAAC,GAAG,CAC9B,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,MAAM,EAC5B,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CACnD,CAAC;QACF,OAAO;YACL,GAAG,EAAE,GAAG,CAAC,QAAQ,IAAI,CAAC;YACtB,GAAG,EAAE,GAAG,CAAC,QAAQ,IAAI,eAAe;YACpC,OAAO,EAAE,eAAe;YACxB,QAAQ,EAAE,GAAG,CAAC,QAAQ,IAAI,CAAC;SAC5B,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,wDAAwD;IACxD,IAAI,MAAM,GAAG,aAAa,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACnE,IAAI,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;IAEnD,0BAA0B;IAC1B,IAAI,UAAU,IAAI,cAAc,EAAE,CAAC;QACjC,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,CAAC;IACpC,CAAC;IAED,uCAAuC;IACvC,MAAM,UAAU,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC;IACpE,MAAM,eAAe,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;IAE9D,IAAI,eAAe,GAAG,CAAC,EAAE,CAAC;QACxB,MAAM,YAAY,GAAG,UAAU,GAAG,cAAc,CAAC;QAEjD,IAAI,YAAY,IAAI,eAAe,EAAE,CAAC;YACpC,0BAA0B;YAC1B,MAAM,WAAW,GAAG,YAAY,GAAG,eAAe,CAAC;YACnD,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;gBAC3B,MAAM,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,WAAW,CAAC,CAAC;gBAC7D,OAAO,CAAC,GAAG,YAAY,CAAC;YAC1B,CAAC,CAAC,CAAC;YACH,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,CAAC;QACpC,CAAC;IACH,CAAC;IAED,gDAAgD;IAChD,MAAM,gBAAgB,GAAG,OAAO;SAC7B,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,GAAG,CAAC,QAAQ,IAAI,CAAC,EAAE,CAAC,CAAC;SACjE,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC;IAE3C,4BAA4B;IAC5B,MAAM,GAAG,aAAa,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC;IACzC,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;IAE/C,0DAA0D;IAC1D,KAAK,MAAM,EAAE,KAAK,EAAE,IAAI,gBAAgB,EAAE,CAAC;QACzC,IAAI,UAAU,IAAI,cAAc;YAAE,MAAM;QAExC,cAAc,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC;QAC9B,UAAU,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC;QAC5B,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACpB,CAAC;IAED,kDAAkD;IAClD,MAAM,cAAc,GAAG,cAAc;SAClC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;SACzB,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IAEvB,IAAI,cAAc,CAAC,MAAM,GAAG,CAAC,IAAI,UAAU,GAAG,cAAc,EAAE,CAAC;QAC7D,MAAM,UAAU,GAAG,cAAc,GAAG,UAAU,CAAC;QAC/C,MAAM,cAAc,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;QAEtE,KAAK,MAAM,CAAC,IAAI,cAAc,EAAE,CAAC;YAC/B,MAAM,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,cAAc,EAAE,aAAa,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;QACzE,CAAC;IACH,CAAC;IAED,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,CAAC;AACpC,CAAC;AAED;;GAEG;AACH,SAAS,SAAS,CAAC,IAAY,EAAE,KAAa,EAAE,QAAqC,MAAM;IACzF,MAAM,aAAa,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC;IAE7C,IAAI,aAAa,IAAI,KAAK,EAAE,CAAC;QAC3B,OAAO,IAAI,CAAC,CAAC,wBAAwB;IACvC,CAAC;IAED,MAAM,OAAO,GAAG,KAAK,GAAG,aAAa,CAAC;IAEtC,QAAQ,KAAK,EAAE,CAAC;QACd,KAAK,OAAO;YACV,OAAO,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC;QACpC,KAAK,QAAQ;YACX,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC;YACxC,MAAM,QAAQ,GAAG,OAAO,GAAG,OAAO,CAAC;YACnC,OAAO,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC3D,SAAS,OAAO;YACd,OAAO,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IACtC,CAAC;AACH,CAAC;AAED;;GAEG;AACH,SAAS,UAAU,CACjB,OAAe,EACf,KAAa,EACb,MAAoB;IAEpB,IAAI,KAAK,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC,CAAC,gBAAgB;IAE5C,MAAM,aAAa,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC;IAEhD,4BAA4B;IAC5B,IAAI,SAAiB,CAAC;IACtB,IAAI,aAAa,GAAG,KAAK,EAAE,CAAC;QAC1B,IAAI,MAAM,CAAC,QAAQ,KAAK,KAAK,EAAE,CAAC,CAAC,sBAAsB;YACrD,SAAS,GAAG,QAAQ,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;QACvC,CAAC;aAAM,CAAC;YACN,6CAA6C;YAC7C,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;QAC1C,CAAC;IACH,CAAC;SAAM,CAAC;QACN,SAAS,GAAG,OAAO,CAAC;IACtB,CAAC;IAED,kBAAkB;IAClB,OAAO,SAAS,CAAC,SAAS,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;AACnD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,qBAAqB,CACnC,OAAiB,EACjB,IAAgB,EAChB,OAAgC;IAEhC,MAAM,SAAS,GAAG,OAAO,EAAE,SAAS,IAAI,IAAI,CAAC;IAC7C,MAAM,KAAK,GAAG,OAAO,EAAE,KAAK,IAAI,SAAS,EAAE,CAAC;IAE5C,gDAAgD;IAChD,MAAM,OAAO,GAAmB,OAAO,EAAE,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QACpE,MAAM,EAAE,CAAC;QACT,QAAQ,EAAE,CAAC;QACX,QAAQ,EAAE,CAAC;QACX,QAAQ,EAAE,IAAI;KACf,CAAC,CAAC,CAAC;IAEJ,kDAAkD;IAClD,MAAM,OAAO,GAAG,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,CAAC;IAEnC,yBAAyB;IACzB,MAAM,aAAa,GAAG,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC;IACzC,MAAM,cAAc,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,KAAK,GAAG,CAAC,SAAS,CAAC,MAAM,GAAG,aAAa,CAAC,CAAC,CAAC;IAEhG,2BAA2B;IAC3B,MAAM,EAAE,MAAM,EAAE,cAAc,EAAE,GAAG,OAAO,EAAE,eAAe;QACzD,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;QACtJ,CAAC,CAAC,sBAAsB,CAAC,IAAI,EAAE,OAAO,EAAE,cAAc,CAAC,CAAC;IAE1D,4BAA4B;IAC5B,MAAM,cAAc,GAAG,cAAc;SAClC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;SACzB,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IAEvB,IAAI,cAAc,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAChC,sCAAsC;QACtC,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACvB,cAAc,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;QACzB,MAAM,CAAC,CAAC,CAAC,GAAG,cAAc,CAAC;IAC7B,CAAC;IAED,gBAAgB;IAChB,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,kBAAkB;IAClB,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;QAC1B,MAAM,cAAc,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAC5C,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAChD,CAAC;QACF,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;IACvD,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,oBAAoB,CAClC,KAA8C,EAC9C,OAAiD;IAEjD,MAAM,KAAK,GAAG,OAAO,EAAE,KAAK,IAAI,SAAS,EAAE,CAAC;IAC5C,MAAM,UAAU,GAAG,OAAO,EAAE,UAAU,IAAI,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,GAAG,CAAC,CAAC,CAAC;IAEhF,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;QAClE,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,KAAK,GAAG,UAAU,GAAG,CAAC,CAAC,CAAC;QACxD,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;QAE/C,KAAK,CAAC,IAAI,CAAC,GAAG,KAAK,KAAK,KAAK,EAAE,CAAC,CAAC;IACnC,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,SAAS,GAAG,EAAE;IAC7C,OAAO,SAAS,EAAE,GAAG,SAAS,CAAC;AACjC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,SAAS,GAAG,EAAE;IAC7C,OAAO,SAAS,EAAE,GAAG,SAAS,CAAC;AACjC,CAAC","sourcesContent":["/**\n * Responsive table rendering with smart column handling\n */\n\nimport { termWidth, stripAnsi, truncate } from './width.js';\n\nexport interface ColumnConfig {\n /** Column header text */\n header: string;\n /** Priority for column visibility (higher = more important) */\n priority?: number;\n /** Minimum width in characters */\n minWidth?: number;\n /** Maximum width in characters */\n maxWidth?: number;\n /** Alignment: left, right, or center */\n align?: 'left' | 'right' | 'center';\n /** Whether to truncate with ellipsis or wrap */\n truncate?: boolean;\n}\n\nexport interface ResponsiveTableOptions {\n /** Column configurations */\n columns?: ColumnConfig[];\n /** Separator between columns */\n separator?: string;\n /** Terminal width override (for testing) */\n width?: number;\n /** Force all columns visible regardless of width */\n forceAllColumns?: boolean;\n}\n\n/**\n * Calculate optimal column widths based on content and terminal width\n */\nfunction calculateOptimalWidths(\n rows: string[][],\n columns: ColumnConfig[],\n availableWidth: number\n): { widths: number[]; visibleColumns: boolean[] } {\n const numColumns = columns.length;\n const visibleColumns = new Array(numColumns).fill(true);\n \n // Calculate content widths (max width needed for each column)\n const contentWidths = columns.map((col, i) => {\n const maxContentWidth = Math.max(\n stripAnsi(col.header).length,\n ...rows.map(row => stripAnsi(row[i] ?? '').length)\n );\n return {\n min: col.minWidth ?? 3,\n max: col.maxWidth ?? maxContentWidth,\n content: maxContentWidth,\n priority: col.priority ?? 0\n };\n });\n \n // Start with ideal widths (content width capped by max)\n let widths = contentWidths.map(cw => Math.min(cw.content, cw.max));\n let totalWidth = widths.reduce((a, b) => a + b, 0);\n \n // If we fit, return as-is\n if (totalWidth <= availableWidth) {\n return { widths, visibleColumns };\n }\n \n // Try to shrink columns proportionally\n const shrinkable = contentWidths.map((cw, i) => widths[i] - cw.min);\n const totalShrinkable = shrinkable.reduce((a, b) => a + b, 0);\n \n if (totalShrinkable > 0) {\n const needToShrink = totalWidth - availableWidth;\n \n if (needToShrink <= totalShrinkable) {\n // We can fit by shrinking\n const shrinkRatio = needToShrink / totalShrinkable;\n widths = widths.map((w, i) => {\n const shrinkAmount = Math.floor(shrinkable[i] * shrinkRatio);\n return w - shrinkAmount;\n });\n return { widths, visibleColumns };\n }\n }\n \n // Still doesn't fit - hide low priority columns\n const sortedByPriority = columns\n .map((col, i) => ({ col, index: i, priority: col.priority ?? 0 }))\n .sort((a, b) => a.priority - b.priority);\n \n // Start with minimum widths\n widths = contentWidths.map(cw => cw.min);\n totalWidth = widths.reduce((a, b) => a + b, 0);\n \n // Hide columns starting with lowest priority until we fit\n for (const { index } of sortedByPriority) {\n if (totalWidth <= availableWidth) break;\n \n visibleColumns[index] = false;\n totalWidth -= widths[index];\n widths[index] = 0;\n }\n \n // Expand remaining columns if we have extra space\n const visibleIndices = visibleColumns\n .map((v, i) => v ? i : -1)\n .filter(i => i >= 0);\n \n if (visibleIndices.length > 0 && totalWidth < availableWidth) {\n const extraSpace = availableWidth - totalWidth;\n const spacePerColumn = Math.floor(extraSpace / visibleIndices.length);\n \n for (const i of visibleIndices) {\n widths[i] = Math.min(widths[i] + spacePerColumn, contentWidths[i].max);\n }\n }\n \n return { widths, visibleColumns };\n}\n\n/**\n * Align text within a given width\n */\nfunction alignText(text: string, width: number, align: 'left' | 'right' | 'center' = 'left'): string {\n const visibleLength = stripAnsi(text).length;\n \n if (visibleLength >= width) {\n return text; // No room for alignment\n }\n \n const padding = width - visibleLength;\n \n switch (align) {\n case 'right':\n return ' '.repeat(padding) + text;\n case 'center':\n const leftPad = Math.floor(padding / 2);\n const rightPad = padding - leftPad;\n return ' '.repeat(leftPad) + text + ' '.repeat(rightPad);\n default: // left\n return text + ' '.repeat(padding);\n }\n}\n\n/**\n * Format a single cell with proper width and alignment\n */\nfunction formatCell(\n content: string,\n width: number,\n config: ColumnConfig\n): string {\n if (width === 0) return ''; // Hidden column\n \n const visibleLength = stripAnsi(content).length;\n \n // Truncate or pad as needed\n let formatted: string;\n if (visibleLength > width) {\n if (config.truncate !== false) { // Default to truncate\n formatted = truncate(content, width);\n } else {\n // For wrapping, just take first line for now\n formatted = content.substring(0, width);\n }\n } else {\n formatted = content;\n }\n \n // Apply alignment\n return alignText(formatted, width, config.align);\n}\n\n/**\n * Render a responsive table that adapts to terminal width\n */\nexport function renderResponsiveTable(\n headers: string[],\n rows: string[][],\n options?: ResponsiveTableOptions\n): string {\n const separator = options?.separator ?? ' ';\n const width = options?.width ?? termWidth();\n \n // Create default column configs if not provided\n const columns: ColumnConfig[] = options?.columns ?? headers.map(h => ({\n header: h,\n priority: 0,\n minWidth: 3,\n truncate: true\n }));\n \n // Combine headers with data for width calculation\n const allRows = [headers, ...rows];\n \n // Account for separators\n const numSeparators = columns.length - 1;\n const availableWidth = Math.max(columns.length * 3, width - (separator.length * numSeparators));\n \n // Calculate optimal widths\n const { widths, visibleColumns } = options?.forceAllColumns \n ? { widths: columns.map((_, i) => Math.max(...allRows.map(r => stripAnsi(r[i] ?? '').length))), visibleColumns: new Array(columns.length).fill(true) }\n : calculateOptimalWidths(rows, columns, availableWidth);\n \n // Filter to visible columns\n const visibleIndices = visibleColumns\n .map((v, i) => v ? i : -1)\n .filter(i => i >= 0);\n \n if (visibleIndices.length === 0) {\n // Emergency: show at least one column\n visibleIndices.push(0);\n visibleColumns[0] = true;\n widths[0] = availableWidth;\n }\n \n // Format output\n const lines: string[] = [];\n \n // Format all rows\n for (const row of allRows) {\n const formattedCells = visibleIndices.map(i => \n formatCell(row[i] ?? '', widths[i], columns[i])\n );\n lines.push(formattedCells.join(separator).trimEnd());\n }\n \n return lines.join('\\n');\n}\n\n/**\n * Responsive list rendering for narrow terminals\n */\nexport function renderResponsiveList(\n items: Array<{ label: string; value: string }>,\n options?: { width?: number; labelWidth?: number }\n): string {\n const width = options?.width ?? termWidth();\n const labelWidth = options?.labelWidth ?? Math.min(20, Math.floor(width * 0.3));\n \n const lines: string[] = [];\n \n for (const item of items) {\n const label = truncate(item.label, labelWidth).padEnd(labelWidth);\n const valueWidth = Math.max(10, width - labelWidth - 2);\n const value = truncate(item.value, valueWidth);\n \n lines.push(`${label} ${value}`);\n }\n \n return lines.join('\\n');\n}\n\n/**\n * Detect if terminal is narrow\n */\nexport function isNarrowTerminal(threshold = 80): boolean {\n return termWidth() < threshold;\n}\n\n/**\n * Detect if terminal is very narrow (mobile-like)\n */\nexport function isMobileTerminal(threshold = 50): boolean {\n return termWidth() < threshold;\n}\n"]}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Spinner compatibility layer
3
+ * Uses the new unified Progress API internally
4
+ */
5
+ import { Progress } from './progress.js';
6
+ /**
7
+ * Create a spinner using the new Progress API
8
+ * This maintains backward compatibility while using the unified implementation
9
+ */
10
+ export function createSpinner(format) {
11
+ const progress = Progress.spinner(undefined, { format });
12
+ return {
13
+ start: (text) => progress.update(text, text),
14
+ setText: (text) => progress.update(text, text),
15
+ stop: () => progress.stop(),
16
+ succeed: (text) => progress.complete(text),
17
+ fail: (text) => progress.fail(text)
18
+ };
19
+ }
20
+ //# sourceMappingURL=spinner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spinner.js","sourceRoot":"/","sources":["ui/spinner.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAUzC;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,MAAe;IAC3C,MAAM,QAAQ,GAAG,QAAQ,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;IAEzD,OAAO;QACL,KAAK,EAAE,CAAC,IAAY,EAAE,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC;QACpD,OAAO,EAAE,CAAC,IAAY,EAAE,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC;QACtD,IAAI,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,IAAI,EAAE;QAC3B,OAAO,EAAE,CAAC,IAAa,EAAE,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC;QACnD,IAAI,EAAE,CAAC,IAAa,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC;KAC7C,CAAC;AACJ,CAAC","sourcesContent":["/**\n * Spinner compatibility layer\n * Uses the new unified Progress API internally\n */\n\nimport { Progress } from './progress.js';\n\nexport interface Spinner {\n start(text: string): void;\n setText(text: string): void;\n stop(): void;\n succeed(text?: string): void;\n fail(text?: string): void;\n}\n\n/**\n * Create a spinner using the new Progress API\n * This maintains backward compatibility while using the unified implementation\n */\nexport function createSpinner(format?: string): Spinner {\n const progress = Progress.spinner(undefined, { format });\n \n return {\n start: (text: string) => progress.update(text, text),\n setText: (text: string) => progress.update(text, text),\n stop: () => progress.stop(),\n succeed: (text?: string) => progress.complete(text),\n fail: (text?: string) => progress.fail(text)\n };\n}\n\n\n"]}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Symbol management with ASCII fallback support
3
+ */
4
+ /**
5
+ * Check if ASCII symbols should be used
6
+ * Based on environment variable or command line flag
7
+ */
8
+ export function useAscii() {
9
+ return process.env.BKTIDE_ASCII === '1' ||
10
+ process.argv.includes('--ascii');
11
+ }
12
+ /**
13
+ * Symbol sets for different display modes
14
+ */
15
+ const UNICODE_SYMBOLS = {
16
+ success: '✓',
17
+ warn: '⚠︎',
18
+ error: '✖',
19
+ info: 'ℹ︎',
20
+ bullet: '•',
21
+ arrow: '→',
22
+ check: '✓',
23
+ cross: '✗'
24
+ };
25
+ const ASCII_SYMBOLS = {
26
+ success: '[OK]',
27
+ warn: '[!]',
28
+ error: '[X]',
29
+ info: '[i]',
30
+ bullet: '*',
31
+ arrow: '->',
32
+ check: '[v]',
33
+ cross: '[x]'
34
+ };
35
+ /**
36
+ * Get the appropriate symbol set based on current settings
37
+ */
38
+ export function getSymbols() {
39
+ return useAscii() ? ASCII_SYMBOLS : UNICODE_SYMBOLS;
40
+ }
41
+ /**
42
+ * Export the symbols for use throughout the application
43
+ * This dynamically returns the appropriate set based on settings
44
+ */
45
+ export const SYMBOLS = getSymbols();
46
+ //# sourceMappingURL=symbols.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"symbols.js","sourceRoot":"/","sources":["ui/symbols.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;GAGG;AACH,MAAM,UAAU,QAAQ;IACtB,OAAO,OAAO,CAAC,GAAG,CAAC,YAAY,KAAK,GAAG;QAChC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;AAC1C,CAAC;AAED;;GAEG;AACH,MAAM,eAAe,GAAG;IACtB,OAAO,EAAE,GAAG;IACZ,IAAI,EAAE,IAAI;IACV,KAAK,EAAE,GAAG;IACV,IAAI,EAAE,IAAI;IACV,MAAM,EAAE,GAAG;IACX,KAAK,EAAE,GAAG;IACV,KAAK,EAAE,GAAG;IACV,KAAK,EAAE,GAAG;CACX,CAAC;AAEF,MAAM,aAAa,GAAG;IACpB,OAAO,EAAE,MAAM;IACf,IAAI,EAAE,KAAK;IACX,KAAK,EAAE,KAAK;IACZ,IAAI,EAAE,KAAK;IACX,MAAM,EAAE,GAAG;IACX,KAAK,EAAE,IAAI;IACX,KAAK,EAAE,KAAK;IACZ,KAAK,EAAE,KAAK;CACb,CAAC;AAEF;;GAEG;AACH,MAAM,UAAU,UAAU;IACxB,OAAO,QAAQ,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,eAAe,CAAC;AACtD,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC","sourcesContent":["/**\n * Symbol management with ASCII fallback support\n */\n\n/**\n * Check if ASCII symbols should be used\n * Based on environment variable or command line flag\n */\nexport function useAscii(): boolean {\n return process.env.BKTIDE_ASCII === '1' || \n process.argv.includes('--ascii');\n}\n\n/**\n * Symbol sets for different display modes\n */\nconst UNICODE_SYMBOLS = {\n success: '✓',\n warn: '⚠︎',\n error: '✖',\n info: 'ℹ︎',\n bullet: '•',\n arrow: '→',\n check: '✓',\n cross: '✗'\n};\n\nconst ASCII_SYMBOLS = {\n success: '[OK]',\n warn: '[!]',\n error: '[X]',\n info: '[i]',\n bullet: '*',\n arrow: '->',\n check: '[v]',\n cross: '[x]'\n};\n\n/**\n * Get the appropriate symbol set based on current settings\n */\nexport function getSymbols(): typeof UNICODE_SYMBOLS {\n return useAscii() ? ASCII_SYMBOLS : UNICODE_SYMBOLS;\n}\n\n/**\n * Export the symbols for use throughout the application\n * This dynamically returns the appropriate set based on settings\n */\nexport const SYMBOLS = getSymbols();\n"]}
@@ -0,0 +1,32 @@
1
+ import { termWidth, calculateColumnWidths, formatTableRow, stripAnsi } from './width.js';
2
+ /**
3
+ * Render a table with proper width awareness
4
+ * @param rows - Array of rows, each row is an array of cells
5
+ * @param options - Optional configuration
6
+ * @returns Formatted table string
7
+ */
8
+ export function renderTable(rows, options) {
9
+ if (!rows || rows.length === 0)
10
+ return '';
11
+ const numColumns = rows[0].length;
12
+ const separator = options?.separator ?? ' ';
13
+ if (options?.preserveWidths) {
14
+ // Calculate widths based on visible text (excluding ANSI codes)
15
+ const widths = rows[0].map((_, i) => Math.max(...rows.map(r => stripAnsi(r[i] ?? '').length)));
16
+ // Format each row with proper padding based on visible length
17
+ return rows
18
+ .map(r => r.map((c, i) => {
19
+ const visibleLength = stripAnsi(c ?? '').length;
20
+ const padding = ' '.repeat(Math.max(0, widths[i] - visibleLength));
21
+ return (c ?? '') + padding;
22
+ }).join(separator))
23
+ .join('\n');
24
+ }
25
+ // Width-aware behavior: responsive tables that fit terminal width
26
+ const width = termWidth();
27
+ const columnWidths = calculateColumnWidths(numColumns, width, separator.length);
28
+ return rows
29
+ .map(row => formatTableRow(row, columnWidths, separator))
30
+ .join('\n');
31
+ }
32
+ //# sourceMappingURL=table.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"table.js","sourceRoot":"/","sources":["ui/table.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,qBAAqB,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEzF;;;;;GAKG;AACH,MAAM,UAAU,WAAW,CACzB,IAAgB,EAChB,OAGC;IAED,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAE1C,MAAM,UAAU,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;IAClC,MAAM,SAAS,GAAG,OAAO,EAAE,SAAS,IAAI,IAAI,CAAC;IAE7C,IAAI,OAAO,EAAE,cAAc,EAAE,CAAC;QAC5B,gEAAgE;QAChE,MAAM,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAClC,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CACzD,CAAC;QAEF,8DAA8D;QAC9D,OAAO,IAAI;aACR,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;YACvB,MAAM,aAAa,GAAG,SAAS,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC;YAChD,MAAM,OAAO,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,GAAG,aAAa,CAAC,CAAC,CAAC;YACnE,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC,GAAG,OAAO,CAAC;QAC7B,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;aAClB,IAAI,CAAC,IAAI,CAAC,CAAC;IAChB,CAAC;IAED,kEAAkE;IAClE,MAAM,KAAK,GAAG,SAAS,EAAE,CAAC;IAC1B,MAAM,YAAY,GAAG,qBAAqB,CAAC,UAAU,EAAE,KAAK,EAAE,SAAS,CAAC,MAAM,CAAC,CAAC;IAEhF,OAAO,IAAI;SACR,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,cAAc,CAAC,GAAG,EAAE,YAAY,EAAE,SAAS,CAAC,CAAC;SACxD,IAAI,CAAC,IAAI,CAAC,CAAC;AAChB,CAAC","sourcesContent":["import { termWidth, calculateColumnWidths, formatTableRow, stripAnsi } from './width.js';\n\n/**\n * Render a table with proper width awareness\n * @param rows - Array of rows, each row is an array of cells\n * @param options - Optional configuration\n * @returns Formatted table string\n */\nexport function renderTable(\n rows: string[][], \n options?: { \n preserveWidths?: boolean;\n separator?: string;\n }\n): string {\n if (!rows || rows.length === 0) return '';\n \n const numColumns = rows[0].length;\n const separator = options?.separator ?? ' ';\n \n if (options?.preserveWidths) {\n // Calculate widths based on visible text (excluding ANSI codes)\n const widths = rows[0].map((_, i) => \n Math.max(...rows.map(r => stripAnsi(r[i] ?? '').length))\n );\n \n // Format each row with proper padding based on visible length\n return rows\n .map(r => r.map((c, i) => {\n const visibleLength = stripAnsi(c ?? '').length;\n const padding = ' '.repeat(Math.max(0, widths[i] - visibleLength));\n return (c ?? '') + padding;\n }).join(separator))\n .join('\\n');\n }\n \n // Width-aware behavior: responsive tables that fit terminal width\n const width = termWidth();\n const columnWidths = calculateColumnWidths(numColumns, width, separator.length);\n \n return rows\n .map(row => formatTableRow(row, columnWidths, separator))\n .join('\\n');\n}\n\n\n"]}