git-aiflow
Version:
🚀 An AI-powered workflow automation tool for effortless Git-based development, combining smart GitLab/GitHub merge & pull request creation with Conan package management.
259 lines • 8.76 kB
JavaScript
import chalk from 'chalk';
/**
* Color utility for console output
*/
export class ColorUtil {
/**
* Get color for file status
*/
static getFileStatusColor(status) {
switch (status.toLowerCase()) {
case 'm':
case 'modified':
return this.FILE_STATUS_COLORS.modified;
case 'a':
case 'added':
return this.FILE_STATUS_COLORS.added;
case 'd':
case 'deleted':
return this.FILE_STATUS_COLORS.deleted;
case 'r':
case 'renamed':
return this.FILE_STATUS_COLORS.renamed;
case 'c':
case 'copied':
return this.FILE_STATUS_COLORS.copied;
case 'u':
case 'unmerged':
return this.FILE_STATUS_COLORS.unmerged;
case '?':
case 'untracked':
return this.FILE_STATUS_COLORS.untracked;
case '!':
case 'ignored':
return this.FILE_STATUS_COLORS.ignored;
default:
return chalk.white;
}
}
/**
* Format file status with appropriate color
*/
static formatFileStatus(filePath, status, index) {
const color = this.getFileStatusColor(status);
const prefix = index !== undefined ? `${index + 1}. ` : '';
return `${prefix}${color(filePath)}`;
}
/**
* Format file status with description
*/
static formatFileStatusWithDescription(filePath, status, description, index) {
const color = this.getFileStatusColor(status);
const prefix = index !== undefined ? `${index + 1}. ` : '';
return `${prefix}${color(filePath)} ${chalk.gray(`(${description})`)}`;
}
/**
* Format git status line with colors
*/
static formatGitStatusLine(line) {
if (!line || line.length < 3)
return line;
const status = line.substring(0, 2);
const filePath = line.substring(3);
// Parse git status format (XY filename)
const workTreeStatus = status[1];
let color = chalk.white;
let statusText = '';
if (workTreeStatus === 'M') {
color = this.FILE_STATUS_COLORS.modified;
statusText = 'modified';
}
else if (workTreeStatus === 'A') {
color = this.FILE_STATUS_COLORS.added;
statusText = 'added';
}
else if (workTreeStatus === 'D') {
color = this.FILE_STATUS_COLORS.deleted;
statusText = 'deleted';
}
else if (workTreeStatus === 'R') {
color = this.FILE_STATUS_COLORS.renamed;
statusText = 'renamed';
}
else if (workTreeStatus === 'C') {
color = this.FILE_STATUS_COLORS.copied;
statusText = 'copied';
}
else if (workTreeStatus === 'U') {
color = this.FILE_STATUS_COLORS.unmerged;
statusText = 'unmerged';
}
else if (status === '??') {
color = this.FILE_STATUS_COLORS.untracked;
statusText = 'untracked';
}
else if (status === '!!') {
color = this.FILE_STATUS_COLORS.ignored;
statusText = 'ignored';
}
return `${color(status)} ${color(filePath)} ${chalk.gray(`(${statusText})`)}`;
}
/**
* Format success message
*/
static success(message) {
return `${this.UI_COLORS.emoji('✅')} ${this.LOG_COLORS.success(message)}`;
}
/**
* Format error message
*/
static error(message) {
return `${this.UI_COLORS.emoji('❌')} ${this.LOG_COLORS.error(message)}`;
}
/**
* Format warning message
*/
static warning(message) {
return `${this.UI_COLORS.emoji('⚠️')} ${this.LOG_COLORS.warning(message)}`;
}
/**
* Format info message
*/
static info(message) {
return `${this.UI_COLORS.emoji('ℹ️')} ${this.LOG_COLORS.info(message)}`;
}
/**
* Format header
*/
static header(message) {
return this.UI_COLORS.header(message);
}
/**
* Format separator line
*/
static separator(char = '─', length = 50) {
return this.UI_COLORS.separator(char.repeat(length));
}
/**
* Format prompt
*/
static prompt(message) {
return this.UI_COLORS.prompt(message);
}
/**
* Format selected item
*/
static selected(message) {
return this.UI_COLORS.selected(message);
}
/**
* Format link
*/
static link(url) {
return this.UI_COLORS.link(url);
}
/**
* Format MR/PR information
*/
static formatMrInfo(title, url, branch, target) {
return `${this.UI_COLORS.emoji('🎉')} ${this.UI_COLORS.header(title)}
${this.UI_COLORS.emoji('📋')} ${this.LOG_COLORS.info('MR/PR 链接')}: ${this.link(url)}
${this.UI_COLORS.emoji('🌿')} ${this.LOG_COLORS.info('分支信息')}: ${this.LOG_COLORS.highlight(branch)} → ${this.LOG_COLORS.highlight(target)}`;
}
/**
* Format file list with colors
*/
static formatFileList(files, maxDisplay = 10) {
if (files.length === 0)
return '';
const displayFiles = files.slice(0, maxDisplay);
const remaining = files.length - maxDisplay;
let result = displayFiles.map(file => ` ${this.UI_COLORS.emoji('•')} ${this.LOG_COLORS.info(file)}`).join('\n');
if (remaining > 0) {
result += `\n ${this.UI_COLORS.emoji('...')} ${this.LOG_COLORS.debug(`${remaining}个文件`)}`;
}
return result;
}
/**
* Dynamic countdown display
*/
static async countdown(seconds, message, finalMessage) {
for (let i = seconds; i > 0; i--) {
process.stdout.write(`\r${this.UI_COLORS.emoji('⏰')} ${this.LOG_COLORS.info(`${message} ${this.UI_COLORS.highlight(i)} seconds...`)}`);
await new Promise(resolve => setTimeout(resolve, 1000));
}
// Clear the line and show final message
const final = finalMessage || message.replace(/\d+ seconds/, 'now');
process.stdout.write(`\r${' '.repeat(process.stdout.columns - 1)}`);
process.stdout.write(`\r${this.UI_COLORS.emoji('✅')} ${this.LOG_COLORS.success(final)}\n`);
}
/**
* Dynamic progress display
*/
static async progressBar(total, message, updateCallback) {
for (let i = 0; i <= total; i++) {
const percentage = Math.round((i / total) * 100);
const progress = '█'.repeat(Math.round(percentage / 2));
const empty = '░'.repeat(50 - Math.round(percentage / 2));
process.stdout.write(`\r${this.UI_COLORS.emoji('📊')} ${this.LOG_COLORS.info(message)} [${progress}${empty}] ${percentage}%`);
if (i < total) {
await updateCallback(i);
await new Promise(resolve => setTimeout(resolve, 100));
}
}
process.stdout.write(`\r${' '.repeat(process.stdout.columns - 1)}`);
process.stdout.write(`\n${this.UI_COLORS.emoji('✅')} ${this.LOG_COLORS.success('Progress completed!')}\n`);
}
/**
* Dynamic spinner display
*/
static async spinner(message, duration = 3000) {
const spinnerChars = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
let i = 0;
const interval = setInterval(() => {
process.stdout.write(`\r${spinnerChars[i % spinnerChars.length]} ${this.LOG_COLORS.info(message)}`);
i++;
}, 100);
await new Promise(resolve => setTimeout(resolve, duration));
clearInterval(interval);
process.stdout.write(`\r${this.UI_COLORS.emoji('✅')} ${this.LOG_COLORS.success(message.replace('ing', 'ed'))}\n`);
}
}
/**
* Color for different file statuses
*/
ColorUtil.FILE_STATUS_COLORS = {
modified: chalk.yellow,
untracked: chalk.blue,
added: chalk.green,
deleted: chalk.red,
renamed: chalk.cyan,
copied: chalk.magenta,
unmerged: chalk.red.bold,
ignored: chalk.gray
};
/**
* Color for different log levels
*/
ColorUtil.LOG_COLORS = {
info: chalk.blue,
success: chalk.green,
warning: chalk.yellow,
error: chalk.red,
debug: chalk.gray,
highlight: chalk.cyan.bold
};
/**
* Color for different UI elements
*/
ColorUtil.UI_COLORS = {
header: chalk.cyan.bold,
separator: chalk.gray,
prompt: chalk.yellow,
selected: chalk.green.bold,
cancelled: chalk.red,
link: chalk.blue.underline,
emoji: chalk.white,
highlight: chalk.cyan.bold
};
//# sourceMappingURL=color-util.js.map