claude-switcher
Version: 
Cross-platform CLI tool for switching between different Claude AI model configurations. Supports automatic backup, rollback, and multi-platform configuration management for Claude API integrations.
253 lines (252 loc) • 10.5 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.OutputFormatter = void 0;
const chalk_1 = __importDefault(require("chalk"));
const BOX_CHARS = {
    simple: {
        topLeft: '┌',
        topRight: '┐',
        bottomLeft: '└',
        bottomRight: '┘',
        horizontal: '─',
        vertical: '│',
        cross: '┼',
        topTee: '┬',
        bottomTee: '┴',
        leftTee: '├',
        rightTee: '┤'
    },
    double: {
        topLeft: '╔',
        topRight: '╗',
        bottomLeft: '╚',
        bottomRight: '╝',
        horizontal: '═',
        vertical: '║',
        cross: '╬',
        topTee: '╦',
        bottomTee: '╩',
        leftTee: '╠',
        rightTee: '╣'
    },
    rounded: {
        topLeft: '╭',
        topRight: '╮',
        bottomLeft: '╰',
        bottomRight: '╯',
        horizontal: '─',
        vertical: '│',
        cross: '┼',
        topTee: '┬',
        bottomTee: '┴',
        leftTee: '├',
        rightTee: '┤'
    }
};
class OutputFormatter {
    static createTable(data, columns, options) {
        if (data.length === 0) {
            return chalk_1.default.gray('(无数据)');
        }
        const style = options?.style ?? 'simple';
        const showHeader = options?.showHeader ?? true;
        const padding = options?.padding ?? 1;
        const chars = BOX_CHARS[style];
        const columnWidths = columns.map(col => {
            const headerWidth = col.header.length;
            const dataWidth = Math.max(...data.map(row => String(row[col.key] || '').length));
            return Math.max(headerWidth, dataWidth, col.width || 0);
        });
        if (options?.maxWidth) {
            const totalWidth = columnWidths.reduce((sum, width) => sum + width, 0) +
                (columns.length - 1) * 3 + 4;
            if (totalWidth > options.maxWidth) {
                const availableWidth = options.maxWidth - (columns.length - 1) * 3 - 4;
                const avgWidth = Math.floor(availableWidth / columns.length);
                columnWidths.forEach((_, index) => {
                    columnWidths[index] = Math.min(columnWidths[index], avgWidth);
                });
            }
        }
        const lines = [];
        const topBorder = chars.topLeft +
            columnWidths.map(width => chars.horizontal.repeat(width + padding * 2))
                .join(chars.topTee) +
            chars.topRight;
        lines.push(topBorder);
        if (showHeader) {
            const headerRow = chars.vertical +
                columns.map((col, index) => {
                    const content = OutputFormatter.alignText(col.header, columnWidths[index], col.align || 'left');
                    return ' '.repeat(padding) + chalk_1.default.bold(content) + ' '.repeat(padding);
                }).join(chars.vertical) +
                chars.vertical;
            lines.push(headerRow);
            const headerSeparator = chars.leftTee +
                columnWidths.map(width => chars.horizontal.repeat(width + padding * 2))
                    .join(chars.cross) +
                chars.rightTee;
            lines.push(headerSeparator);
        }
        data.forEach(row => {
            const dataRow = chars.vertical +
                columns.map((col, index) => {
                    let content = String(row[col.key] || '');
                    if (content.length > columnWidths[index]) {
                        content = content.substring(0, columnWidths[index] - 3) + '...';
                    }
                    content = OutputFormatter.alignText(content, columnWidths[index], col.align || 'left');
                    if (col.color) {
                        content = col.color(content);
                    }
                    return ' '.repeat(padding) + content + ' '.repeat(padding);
                }).join(chars.vertical) +
                chars.vertical;
            lines.push(dataRow);
        });
        const bottomBorder = chars.bottomLeft +
            columnWidths.map(width => chars.horizontal.repeat(width + padding * 2))
                .join(chars.bottomTee) +
            chars.bottomRight;
        lines.push(bottomBorder);
        return lines.join('\n');
    }
    static createList(items, options) {
        if (items.length === 0) {
            return chalk_1.default.gray('(无项目)');
        }
        const bullet = options?.bullet ?? '•';
        const indent = ' '.repeat(options?.indent ?? 2);
        const color = options?.color ?? ((text) => text);
        return items.map((item, index) => {
            const marker = options?.numbered ? `${index + 1}.` : bullet;
            return `${indent}${color(marker)} ${item}`;
        }).join('\n');
    }
    static createKeyValue(data, options) {
        const keyColor = options?.keyColor ?? chalk_1.default.cyan;
        const valueColor = options?.valueColor ?? ((text) => text);
        const separator = options?.separator ?? ':';
        const indent = ' '.repeat(options?.indent ?? 2);
        const keyWidth = options?.keyWidth ?? Math.max(...Object.keys(data).map(k => k.length));
        return Object.entries(data).map(([key, value]) => {
            const paddedKey = key.padEnd(keyWidth);
            const formattedValue = value === null || value === undefined ?
                chalk_1.default.gray('(未设置)') :
                String(value);
            return `${indent}${keyColor(paddedKey)}${separator} ${valueColor(formattedValue)}`;
        }).join('\n');
    }
    static createStatus(items, options) {
        const indent = ' '.repeat(options?.indent ?? 2);
        const showDetails = options?.showDetails ?? false;
        const statusIcons = {
            success: { icon: '✅', color: chalk_1.default.green },
            error: { icon: '❌', color: chalk_1.default.red },
            warning: { icon: '⚠️', color: chalk_1.default.yellow },
            info: { icon: 'ℹ️', color: chalk_1.default.blue },
            pending: { icon: '⏳', color: chalk_1.default.gray }
        };
        return items.map(item => {
            const { icon, color } = statusIcons[item.status];
            let line = `${indent}${icon} ${color(item.label)}`;
            if (showDetails && item.details) {
                line += `\n${indent}   ${chalk_1.default.gray(item.details)}`;
            }
            return line;
        }).join('\n');
    }
    static createProgress(label, current, total, options) {
        const width = options?.width ?? 30;
        const showPercentage = options?.showPercentage ?? true;
        const showNumbers = options?.showNumbers ?? false;
        const color = options?.color ?? chalk_1.default.cyan;
        const percentage = Math.min(100, Math.max(0, (current / total) * 100));
        const filled = Math.floor((percentage / 100) * width);
        const empty = width - filled;
        const bar = color('█'.repeat(filled)) + chalk_1.default.gray('░'.repeat(empty));
        let result = `${label}: [${bar}]`;
        if (showPercentage) {
            result += ` ${Math.round(percentage)}%`;
        }
        if (showNumbers) {
            result += ` (${current}/${total})`;
        }
        return result;
    }
    static createBox(message, options) {
        const style = options?.style ?? 'simple';
        const color = options?.color ?? ((text) => text);
        const padding = options?.padding ?? 1;
        const chars = BOX_CHARS[style];
        const lines = Array.isArray(message) ? message : [message];
        const maxContentWidth = Math.max(...lines.map(line => line.length));
        const titleWidth = options?.title ? options.title.length : 0;
        const contentWidth = Math.max(maxContentWidth, titleWidth);
        const boxWidth = options?.width ?? contentWidth + padding * 2;
        const result = [];
        if (options?.title) {
            const titlePadding = Math.max(0, boxWidth - options.title.length - 2);
            const leftPadding = Math.floor(titlePadding / 2);
            const rightPadding = titlePadding - leftPadding;
            result.push(color(chars.topLeft +
                chars.horizontal.repeat(leftPadding) +
                ` ${options.title} ` +
                chars.horizontal.repeat(rightPadding) +
                chars.topRight));
        }
        else {
            result.push(color(chars.topLeft +
                chars.horizontal.repeat(boxWidth) +
                chars.topRight));
        }
        lines.forEach(line => {
            const paddedLine = line.padEnd(boxWidth - padding * 2);
            result.push(color(chars.vertical +
                ' '.repeat(padding) +
                paddedLine +
                ' '.repeat(padding) +
                chars.vertical));
        });
        result.push(color(chars.bottomLeft +
            chars.horizontal.repeat(boxWidth) +
            chars.bottomRight));
        return result.join('\n');
    }
    static alignText(text, width, align) {
        if (text.length >= width) {
            return text.substring(0, width);
        }
        switch (align) {
            case 'center':
                const totalPadding = width - text.length;
                const leftPadding = Math.floor(totalPadding / 2);
                const rightPadding = totalPadding - leftPadding;
                return ' '.repeat(leftPadding) + text + ' '.repeat(rightPadding);
            case 'right':
                return text.padStart(width);
            default:
                return text.padEnd(width);
        }
    }
    static createSeparator(width = 50, char = '─', color) {
        const line = char.repeat(width);
        return color ? color(line) : chalk_1.default.gray(line);
    }
    static createHeader(title, options) {
        const level = options?.level ?? 1;
        const color = options?.color ?? chalk_1.default.blue.bold;
        const separator = options?.separator ?? true;
        const width = options?.width ?? Math.max(50, title.length + 10);
        let result = color(title);
        if (separator) {
            const separatorChar = level === 1 ? '═' : level === 2 ? '─' : '·';
            result += '\n' + chalk_1.default.gray(separatorChar.repeat(width));
        }
        return result;
    }
}
exports.OutputFormatter = OutputFormatter;