UNPKG

bktide

Version:

Command-line interface for Buildkite CI/CD workflows with rich shell completions (Fish, Bash, Zsh) and Alfred workflow integration for macOS power users

115 lines 4.42 kB
import { COLORS, SYMBOLS, shouldDecorate, formatTips, TipStyle } from './theme.js'; import { termWidth, calculateColumnWidths, formatTableRow } from './width.js'; function isMachine(format) { const f = (format || '').toLowerCase(); return f === 'json' || f === 'alfred'; } function isInteractive() { // Check for forced interactive mode first (for testing) if (process.env.BKTIDE_FORCE_INTERACTIVE === '1') { return true; } // Only show decorative messages when stdout is a TTY (not piped/redirected) return Boolean(process.stdout.isTTY); } export class Reporter { format; quiet; showTips; constructor(format = 'plain', quiet = false, tips) { this.format = format; this.quiet = quiet; // Tips logic: // - If tips is explicitly set (true or false), use that // - Otherwise, tips are off if quiet mode is enabled // - Default to true (show tips) if not quiet and not explicitly set this.showTips = tips !== undefined ? tips : !quiet; } info(message) { if (this.shouldSuppress()) return; this.writeStdout(this.decorate(COLORS.info, `${SYMBOLS.info} ${message}`)); } success(message) { if (this.shouldSuppress()) return; this.writeStdout(this.decorate(COLORS.success, `${SYMBOLS.success} ${message}`)); } tip(message) { // Tips have their own suppression logic if (!this.shouldShowTips()) return; // Use individual style for single tips from reporter const formatted = formatTips([message], TipStyle.INDIVIDUAL); this.writeStdout(formatted); } /** * Display multiple tips in a grouped format */ tips(messages, style) { if (!this.shouldShowTips()) return; const formatted = formatTips(messages, style || TipStyle.GROUPED); this.writeStdout(formatted); } warn(message) { // Warnings go to stderr, check stderr TTY status if (isMachine(this.format) || !process.stderr.isTTY) return; this.writeStderr(this.decorate(COLORS.warn, `${SYMBOLS.warn} ${message}`)); } error(message) { // Errors go to stderr, check stderr TTY status if (isMachine(this.format) || !process.stderr.isTTY) return; this.writeStderr(this.decorate(COLORS.error, `${SYMBOLS.error} ${message}`)); } table(rows, options) { // Tables are data output, not decorative - always show them if (!rows.length || isMachine(this.format)) return; // Get terminal width for responsive tables const width = termWidth(); const numColumns = rows[0].length; if (options?.preserveWidths) { // Legacy behavior: preserve exact widths (may overflow) const widths = rows[0].map((_, i) => Math.max(...rows.map(r => (r[i] ?? '').length))); const lines = rows.map(r => r.map((c, i) => (c ?? '').padEnd(widths[i])).join(' ')).join('\n'); this.writeStdout(lines); } else { // New behavior: responsive width-aware tables const columnWidths = calculateColumnWidths(numColumns, width); const lines = rows.map(row => formatTableRow(row, columnWidths)); this.writeStdout(lines.join('\n')); } } shouldSuppress() { // Suppress decorative messages when: // - quiet mode is enabled // - machine format (json/alfred) // - stdout is not a TTY (piped/redirected) return this.quiet || isMachine(this.format) || !isInteractive(); } shouldShowTips() { // Tips are shown when: // - Not in machine format (json/alfred) // - stdout is a TTY (interactive) // - showTips flag is true (controlled by --tips/--no-tips/--quiet) return !isMachine(this.format) && isInteractive() && this.showTips; } decorate(fn, s) { return shouldDecorate(this.format) ? fn(s) : s; } writeStdout(s) { if (isMachine(this.format)) return; // keep machine outputs pristine process.stdout.write(s + '\n'); } writeStderr(s) { if (isMachine(this.format)) return; // keep machine outputs pristine process.stderr.write(s + '\n'); } } //# sourceMappingURL=reporter.js.map