diff --git a/index.js b/index.js index 470be8c..e182bc2 100755 --- a/index.js +++ b/index.js @@ -8,55 +8,10 @@ const path = require('path'); const { execSync } = require('child_process'); const packageJson = require('./package.json'); -// Get the current directory name for default output file -const getCurrentDirectoryName = () => { - const currentPath = process.cwd(); - return path.basename(currentPath) + '.md'; -}; - -// Package information -program - .name('code2prompt-manager') - .description('A CLI tool to manage code2prompt file size limits') - .version(packageJson.version); - -// Command line options -program - .option('-l, --limit ', 'Size limit for the generated MD file in KB', (value) => parseInt(value, 10), 400) - .option('-d, --directory ', 'Directory to scan', '.') - .option('-e, --extra-exclude ', 'Additional exclude patterns (comma-separated)') - .option('-i, --include ', 'Include patterns (comma-separated)') - .option('-O, --output-file ', 'Output file name', getCurrentDirectoryName()) - .option('-F, --output-format ', 'Output format: markdown, json, or xml', 'markdown') - .option('--include-priority', 'Include files in case of conflict between include and exclude patterns') - .option('--full-directory-tree', 'List the full directory tree') - .option('-c, --encoding ', 'Optional tokenizer to use for token count (cl100k, p50k, etc.)') - .option('--line-numbers', 'Add line numbers to the source code') - .option('-n, --no-execute', 'Only show the command, don\'t execute it') - .option('--auto-exclude', 'Automatically exclude files to stay under size limit', false); - -program.parse(process.argv); -const options = program.opts(); - -// Utility function to format file sizes -function formatSize(bytes) { - const units = ['B', 'KB', 'MB', 'GB']; - let size = bytes; - let unitIndex = 0; - - while (size >= 1024 && unitIndex < units.length - 1) { - size /= 1024; - unitIndex++; - } - - return `${size.toFixed(2)} ${units[unitIndex]}`; -} - -// Get files and directories recursively -function scanDirectory(rootDir) { - const items = []; - // Default directories to skip during scanning - const skipDirs = [ +// Configuration constants +const CONFIG = { + // Default directories to exclude + COMMON_EXCLUDE_DIRS: [ 'node_modules', '.git', 'vendor', @@ -72,7 +27,137 @@ function scanDirectory(rootDir) { 'src/assets/images', 'assets/icons', 'languages', - ]; + ], + // Default file patterns to exclude + COMMON_EXCLUDE_FILES: [ + 'package-lock.json', + 'composer.lock', + 'yarn.lock', + '*.min.js', + '*.min.css' + ] +}; + +// Utility functions +const utils = { + // Get current directory name for default output file + getCurrentDirectoryName() { + const currentPath = process.cwd(); + return path.basename(currentPath) + '.md'; + }, + + // Format file sizes for display + formatSize(bytes) { + const units = ['B', 'KB', 'MB', 'GB']; + let size = bytes; + let unitIndex = 0; + + while (size >= 1024 && unitIndex < units.length - 1) { + size /= 1024; + unitIndex++; + } + + return `${size.toFixed(2)} ${units[unitIndex]}`; + }, + + // Calculate directory size recursively + getDirSize(dirPath) { + let totalSize = 0; + + try { + const entries = fs.readdirSync(dirPath); + + for (const entry of entries) { + const entryPath = path.join(dirPath, entry); + + try { + const stats = fs.statSync(entryPath); + + if (stats.isDirectory()) { + totalSize += this.getDirSize(entryPath); + } else { + totalSize += stats.size; + } + } catch (err) { + // Skip files/directories we can't access + } + } + } catch (err) { + // Skip directories we can't read + } + + return totalSize; + }, + + // Pattern matching for file and directory paths + isPathExcluded(itemPath, pattern, isDirectory = false) { + // For directory patterns with '/**' + if (pattern.endsWith('/**')) { + const dirName = pattern.slice(0, -3); + + // For top-level directories + if (!dirName.includes('/')) { + return itemPath === dirName || itemPath.startsWith(dirName + '/'); + } + // For path-specified directories + else { + return itemPath === dirName || itemPath.startsWith(dirName + '/'); + } + } + // For exact file matches (no wildcards) + else if (!pattern.includes('*')) { + return itemPath === pattern; + } + // For other wildcard patterns + else { + const regex = new RegExp('^' + pattern.replace(/\*\*/g, '.*').replace(/\*/g, '[^/]*') + '$'); + return regex.test(itemPath); + } + }, + + // Check if item is excluded by any pattern in the list + isExcluded(itemPath, excludePatterns, isDirectory = false) { + return excludePatterns.some(pattern => + this.isPathExcluded(itemPath, pattern, isDirectory)); + }, + + // Log with color + log: { + info: (msg) => console.log(chalk.blue(msg)), + success: (msg) => console.log(chalk.green(msg)), + warning: (msg) => console.log(chalk.yellow(msg)), + error: (msg) => console.error(chalk.red(msg)) + } +}; + +// Set up command line options +function setupCommandLine() { + program + .name('code2prompt-manager') + .description('A CLI tool to manage code2prompt file size limits') + .version(packageJson.version) + .option('-l, --limit ', 'Size limit for the generated MD file in KB', + (value) => parseInt(value, 10), 400) + .option('-d, --directory ', 'Directory to scan', '.') + .option('-e, --extra-exclude ', 'Additional exclude patterns (comma-separated)') + .option('-i, --include ', 'Include patterns (comma-separated)') + .option('-O, --output-file ', 'Output file name', utils.getCurrentDirectoryName()) + .option('-F, --output-format ', 'Output format: markdown, json, or xml', 'markdown') + .option('--include-priority', 'Include files in case of conflict between include and exclude patterns') + .option('--full-directory-tree', 'List the full directory tree') + .option('-c, --encoding ', 'Optional tokenizer to use for token count (cl100k, p50k, etc.)') + .option('--line-numbers', 'Add line numbers to the source code') + .option('-n, --no-execute', 'Only show the command, don\'t execute it') + .option('--auto-exclude', 'Automatically exclude files to stay under size limit', false); + + program.parse(process.argv); + return program.opts(); +} + +// Prepare exclude directories list +function getExcludeDirs(options) { + // Default directories to skip during scanning + const skipDirs = [...CONFIG.COMMON_EXCLUDE_DIRS]; // Add extra exclude directories from command line if (options.extraExclude) { @@ -94,6 +179,13 @@ function scanDirectory(rootDir) { }); } + return skipDirs; +} + +// Get files and directories recursively +function scanDirectory(rootDir, skipDirs) { + const items = []; + function scan(dir, baseDir = '') { try { const entries = fs.readdirSync(dir); @@ -123,17 +215,18 @@ function scanDirectory(rootDir) { path: relativePath, isDirectory: true, size: 0, - prettySize: formatSize(0) + prettySize: utils.formatSize(0) }); continue; } // Add the directory + const dirSize = utils.getDirSize(fullPath); items.push({ path: relativePath, isDirectory: true, - size: getDirSize(fullPath), - prettySize: formatSize(getDirSize(fullPath)) + size: dirSize, + prettySize: utils.formatSize(dirSize) }); // Scan subdirectory @@ -144,45 +237,16 @@ function scanDirectory(rootDir) { path: relativePath, isDirectory: false, size: stats.size, - prettySize: formatSize(stats.size) + prettySize: utils.formatSize(stats.size) }); } } catch (err) { - console.warn(chalk.yellow(`Warning: Could not access ${fullPath}: ${err.message}`)); - } - } - } catch (err) { - console.warn(chalk.yellow(`Warning: Could not read directory ${dir}: ${err.message}`)); - } - } - - // Calculate directory size - function getDirSize(dirPath) { - let totalSize = 0; - - try { - const entries = fs.readdirSync(dirPath); - - for (const entry of entries) { - const entryPath = path.join(dirPath, entry); - - try { - const stats = fs.statSync(entryPath); - - if (stats.isDirectory()) { - totalSize += getDirSize(entryPath); - } else { - totalSize += stats.size; - } - } catch (err) { - // Skip files/directories we can't access + utils.log.warning(`Warning: Could not access ${fullPath}: ${err.message}`); } } } catch (err) { - // Skip directories we can't read + utils.log.warning(`Warning: Could not read directory ${dir}: ${err.message}`); } - - return totalSize; } // Start scanning from the root directory @@ -192,43 +256,44 @@ function scanDirectory(rootDir) { return items.sort((a, b) => b.size - a.size); } -// Estimate the final size after excluding files -function estimateFinalSize(items, excludePatterns) { - let totalSize = 0; - - // Helper function to check if a file/directory is excluded - function isExcluded(itemPath, isDirectory) { - const itemPathWithWildcard = isDirectory ? `${itemPath}/**` : itemPath; - - return excludePatterns.some(pattern => { - // For directory patterns with '/**' - match pattern exactly - if (pattern.endsWith('/**')) { - const dirName = pattern.slice(0, -3); +// Prepare exclude patterns +function prepareExcludePatterns(options) { + // Default excludes + const defaultExcludes = [ + // Add directory patterns with /** + ...CONFIG.COMMON_EXCLUDE_DIRS.map(dir => `${dir}/**`), + // Add file patterns + ...CONFIG.COMMON_EXCLUDE_FILES + ]; - // For top-level directories - if (!dirName.includes('/')) { - return itemPath === dirName || itemPath.startsWith(dirName + '/'); - } - // For path-specified directories - else { - return itemPath === dirName || itemPath.startsWith(dirName + '/'); + // Add extra exclude patterns from command line + const extraExcludes = []; + if (options.extraExclude) { + options.extraExclude.split(',').forEach(pattern => { + pattern = pattern.trim(); + if (pattern) { + // Add '/**' suffix for directory patterns that don't have wildcards + if (!pattern.includes('*') && + fs.existsSync(path.join(options.directory, pattern)) && + fs.statSync(path.join(options.directory, pattern)).isDirectory()) { + extraExcludes.push(pattern + '/**'); + } else { + extraExcludes.push(pattern); } } - // For exact file matches (no wildcards) - else if (!pattern.includes('*')) { - return itemPath === pattern; - } - // For other wildcard patterns - else { - const regex = new RegExp('^' + pattern.replace(/\*\*/g, '.*').replace(/\*/g, '[^/]*') + '$'); - return regex.test(itemPath); - } }); } + return { defaultExcludes, extraExcludes, allExcludes: [...defaultExcludes, ...extraExcludes] }; +} + +// Estimate the final size after excluding files +function estimateFinalSize(items, excludePatterns) { + let totalSize = 0; + // Sum sizes of all files that are not excluded items.forEach(item => { - if (!item.isDirectory && !isExcluded(item.path, item.isDirectory)) { + if (!item.isDirectory && !utils.isExcluded(item.path, excludePatterns)) { totalSize += item.size; } }); @@ -239,173 +304,212 @@ function estimateFinalSize(items, excludePatterns) { return totalSize + markdownOverhead; } +// Create choices for selection UI +function createSelectionChoices(items, allExcludes) { + // Create file choices + const fileChoices = items + .filter(item => !item.isDirectory) // Only include files in the choices + .sort((a, b) => b.size - a.size) + .map(item => { + const sizeStr = item.prettySize.padStart(10); + const pathStr = item.path; + + return { + name: `${sizeStr} │ ${pathStr}`, + value: item.path, + short: item.path, + size: item.size, // Store size for auto-exclude feature + checked: utils.isExcluded(item.path, allExcludes) + }; + }); + + // Create directory choices + const directoryChoices = items + .filter(item => item.isDirectory) + .sort((a, b) => b.size - a.size) + .map(item => { + const sizeStr = item.prettySize.padStart(10); + const pathStr = item.path + '/'; + + return { + name: `${sizeStr} │ ${pathStr}`, + value: `${item.path}/**`, + short: item.path, + checked: utils.isExcluded(item.path, allExcludes, true) + }; + }); + + return { + fileChoices, + directoryChoices, + allChoices: [ + new inquirer.Separator(' === Files (sorted by size) === '), + ...fileChoices, + new inquirer.Separator(' === Directories === '), + ...directoryChoices + ] + }; +} + +// Auto-exclude large files to stay under the size limit +function autoExcludeFiles(choices, initialSize, sizeLimit, autoExclude) { + const autoExcluded = []; + + if (autoExclude && initialSize > sizeLimit) { + let remainingSize = initialSize; + const targetSize = sizeLimit * 0.95; // Target 95% of limit to allow some margin + + // Sort files by size (largest first) that aren't already excluded + const filesToConsider = [...choices] + .filter(choice => !choice.checked) + .sort((a, b) => b.size - a.size); + + for (const file of filesToConsider) { + if (remainingSize > targetSize) { + file.checked = true; + autoExcluded.push(file.value); + remainingSize -= file.size; + } else { + break; + } + } + + if (autoExcluded.length > 0) { + utils.log.warning(`\nAuto-excluded ${autoExcluded.length} files to meet size limit:`); + autoExcluded.forEach(file => { + utils.log.warning(` - ${file}`); + }); + utils.log.success(`New estimated size: ${utils.formatSize(remainingSize)}`); + } + } + + return autoExcluded; +} + +// Build the code2prompt command +function buildCommand(options, allExcludes) { + let cmd = `code2prompt`; + + // Add options that match code2prompt's format + if (options.outputFile) { + cmd += ` -O "${options.outputFile}"`; + } + + if (options.outputFormat && options.outputFormat !== 'markdown') { + cmd += ` -F ${options.outputFormat}`; + } + + // Add boolean flags + const booleanFlags = { + includePriority: '--include-priority', + fullDirectoryTree: '--full-directory-tree', + lineNumbers: '--line-numbers' + }; + + // Add each enabled boolean flag + Object.entries(booleanFlags).forEach(([option, flag]) => { + if (options[option]) cmd += ` ${flag}`; + }); + + // Add encoding option if present + if (options.encoding) { + cmd += ` -c ${options.encoding}`; + } + + // Add exclude options - use a single -e flag with comma-separated patterns + if (allExcludes.length > 0) { + cmd += ` -e "${allExcludes.join(',')}"`; + } + + // Add include options - use a single -i flag with comma-separated patterns + if (options.include) { + const includePatterns = options.include.split(',') + .map(pattern => pattern.trim()) + .filter(pattern => pattern); + + if (includePatterns.length > 0) { + cmd += ` -i "${includePatterns.join(',')}"`; + } + } + + // Add the directory path at the end + cmd += ` "${options.directory}"`; + + return cmd; +} + +// Execute the generated command +function executeCommand(cmd, execute) { + if (execute) { + utils.log.info('\nExecuting command...'); + try { + execSync(cmd, { stdio: 'inherit' }); + utils.log.success('\nCommand executed successfully!'); + } catch (error) { + utils.log.error('\nError executing command: ' + error.message); + } + } +} + +// Process any unselected auto-excluded files +function processUnselectedAutoExcludes(autoExcluded, selectedExcludes) { + const unselectedAutoExcludes = autoExcluded.filter(item => !selectedExcludes.includes(item)); + + if (unselectedAutoExcludes.length > 0) { + utils.log.warning(`You un-selected ${unselectedAutoExcludes.length} auto-excluded files that will be INCLUDED in the output:`); + unselectedAutoExcludes.forEach(file => { + utils.log.warning(` + ${file}`); + }); + } +} + +// Display size information +function displaySizeInfo(size, limit, message) { + const formattedSize = utils.formatSize(size); + + if (size > limit) { + const exceedMessage = `(exceeds limit by ${utils.formatSize(size - limit)})`; + utils.log.info(`\n${message}: ${formattedSize} ${chalk.red(exceedMessage)}`); + } else { + utils.log.info(`\n${message}: ${formattedSize} ${chalk.green('(within limit)')}`); + } +} + // Main function async function main() { try { - console.log(chalk.blue(`Scanning directory "${options.directory}" for files...`)); - console.log(chalk.yellow('This may take a while for large codebases...')); + // Set up command line options + const options = setupCommandLine(); + + utils.log.info(`Scanning directory "${options.directory}" for files...`); + utils.log.warning('This may take a while for large codebases...'); + + // Prepare exclude directories + const skipDirs = getExcludeDirs(options); // Scan the directory - const items = scanDirectory(options.directory); - - console.log(chalk.green(`Found ${items.length} files and directories.`)); - - // Default excludes - const defaultExcludes = [ - 'node_modules/**', - 'vendor/**', - '.git/**', - '.next/**', - '.husky/**', - 'dist/**', - 'build/**', - 'public/**', - 'docs/**', - 'assets/fonts/**', - 'assets/images/**', - 'assets/svg/**', - 'src/assets/images/**', - 'assets/icons/**', - 'languages/**', - 'package-lock.json', - 'composer.lock', - 'yarn.lock', - '*.min.js', - '*.min.css' - ]; - - // Add extra exclude patterns from command line to defaultExcludes - const extraExcludes = []; - if (options.extraExclude) { - options.extraExclude.split(',').forEach(pattern => { - pattern = pattern.trim(); - if (pattern) { - // Add '/**' suffix for directory patterns that don't have wildcards - if (!pattern.includes('*') && fs.existsSync(path.join(options.directory, pattern)) && - fs.statSync(path.join(options.directory, pattern)).isDirectory()) { - extraExcludes.push(pattern + '/**'); - } else { - extraExcludes.push(pattern); - } - } - }); - } + const items = scanDirectory(options.directory, skipDirs); + utils.log.success(`Found ${items.length} files and directories.`); - // Combine defaults with extras - const allDefaultExcludes = [...defaultExcludes, ...extraExcludes]; + // Prepare exclude patterns + const { defaultExcludes, extraExcludes, allExcludes } = prepareExcludePatterns(options); // Calculate initial size with just default excludes - const initialSize = estimateFinalSize(items, allDefaultExcludes); + const initialSize = estimateFinalSize(items, allExcludes); const sizeLimit = options.limit * 1024; // Convert KB to bytes - console.log(chalk.blue(`\nSize limit: ${formatSize(sizeLimit)} (${options.limit} KB)`)); - console.log(chalk.blue(`Estimated size with default excludes: ${formatSize(initialSize)}`)); + utils.log.info(`\nSize limit: ${utils.formatSize(sizeLimit)} (${options.limit} KB)`); + utils.log.info(`Estimated size with default excludes: ${utils.formatSize(initialSize)}`); if (initialSize > sizeLimit) { - console.log(chalk.yellow(`\nWARNING: Current selection exceeds size limit by ${formatSize(initialSize - sizeLimit)}`)); + utils.log.warning(`\nWARNING: Current selection exceeds size limit by ${utils.formatSize(initialSize - sizeLimit)}`); } - // Create choices for selection and sort by size (largest first) - const choices = items - .filter(item => !item.isDirectory) // Only include files in the choices - .sort((a, b) => b.size - a.size) - .map(item => { - const sizeStr = item.prettySize.padStart(10); - const pathStr = item.path; - - return { - name: `${sizeStr} │ ${pathStr}`, - value: item.path, - short: item.path, - size: item.size, // Store size for auto-exclude feature - checked: allDefaultExcludes.some(pattern => { - // For exact file matches (no wildcards) - if (!pattern.includes('*')) { - return item.path === pattern; - } - // For wildcard patterns - else { - const regex = new RegExp('^' + pattern.replace(/\*\*/g, '.*').replace(/\*/g, '[^/]*') + '$'); - return regex.test(item.path); - } - }) - }; - }); - - // Add directories as separate section - const directoryChoices = items - .filter(item => item.isDirectory) - .sort((a, b) => b.size - a.size) - .map(item => { - const sizeStr = item.prettySize.padStart(10); - const pathStr = item.path + '/'; - - return { - name: `${sizeStr} │ ${pathStr}`, - value: `${item.path}/**`, - short: item.path, - checked: allDefaultExcludes.some(pattern => { - // For directory patterns with '/**' - match pattern exactly - if (pattern.endsWith('/**')) { - const dirName = pattern.slice(0, -3); - - // For top-level directories (e.g., "styles/**") - if (!dirName.includes('/')) { - return item.path === dirName || - (item.path.startsWith(dirName + '/') && !item.path.substring(dirName.length + 1).includes('/')); - } - // For path-specified directories - else { - return item.path === dirName || - item.path.startsWith(dirName + '/'); - } - } - // For other patterns - else { - const regex = new RegExp('^' + pattern.replace(/\*\*/g, '.*').replace(/\*/g, '[^/]*') + '$'); - return regex.test(item.path); - } - }) - }; - }); + // Create choices for selection UI + const { fileChoices, directoryChoices, allChoices } = createSelectionChoices(items, allExcludes); // Auto-exclude large files if needed and requested - let autoExcluded = []; - if (options.autoExclude && initialSize > sizeLimit) { - let remainingSize = initialSize; - const targetSize = sizeLimit * 0.95; // Target 95% of limit to allow some margin - - // Sort files by size (largest first) that aren't already excluded - const filesToConsider = [...choices] - .filter(choice => !choice.checked) - .sort((a, b) => b.size - a.size); - - for (const file of filesToConsider) { - if (remainingSize > targetSize) { - file.checked = true; - autoExcluded.push(file.value); - remainingSize -= file.size; - } else { - break; - } - } - - if (autoExcluded.length > 0) { - console.log(chalk.yellow(`\nAuto-excluded ${autoExcluded.length} files to meet size limit:`)); - autoExcluded.forEach(file => { - console.log(chalk.yellow(` - ${file}`)); - }); - console.log(chalk.green(`New estimated size: ${formatSize(remainingSize)}`)); - } - } - - // Combine file and directory choices for the selection UI - const allChoices = [ - new inquirer.Separator(' === Files (sorted by size) === '), - ...choices, - new inquirer.Separator(' === Directories === '), - ...directoryChoices - ]; + const autoExcluded = autoExcludeFiles(fileChoices, initialSize, sizeLimit, options.autoExclude); // Show selection UI const { selectedExcludes } = await inquirer.prompt([ @@ -418,98 +522,38 @@ async function main() { } ]); - // For auto-excluded files, we should ONLY consider them if they are still in the selectedExcludes - // This is the correct approach - the user's final selection is the source of truth + utils.log.info(`\nFinal user selection: ${selectedExcludes.length} items`); - console.log(chalk.blue(`\nFinal user selection: ${selectedExcludes.length} items`)); + // Process any unselected auto-excluded files + processUnselectedAutoExcludes(autoExcluded, selectedExcludes); - // Log any auto-excluded files that were unselected by the user - const unselectedAutoExcludes = autoExcluded.filter(item => !selectedExcludes.includes(item)); - if (unselectedAutoExcludes.length > 0) { - console.log(chalk.yellow(`You un-selected ${unselectedAutoExcludes.length} auto-excluded files that will be INCLUDED in the output:`)); - unselectedAutoExcludes.forEach(file => { - console.log(chalk.yellow(` + ${file}`)); - }); - } - - // The final list should ONLY contain what's in the user's selection plus default excludes + // The final list should contain default excludes plus user's selection const finalExcludes = [...defaultExcludes, ...extraExcludes, ...selectedExcludes]; const finalSize = estimateFinalSize(items, finalExcludes); - console.log(chalk.blue(`\nFinal estimated size: ${formatSize(finalSize)} ${finalSize > sizeLimit ? chalk.red(`(exceeds limit by ${formatSize(finalSize - sizeLimit)})`) : chalk.green('(within limit)')}`)); + // Display final size information + displaySizeInfo(finalSize, sizeLimit, "Final estimated size"); // Combine default and selected excludes, removing duplicates - const allExcludes = Array.from(new Set(finalExcludes)); + const dedupedExcludes = Array.from(new Set(finalExcludes)); // Create the code2prompt command - let cmd = `code2prompt`; - - // Add options that match code2prompt's format - if (options.outputFile) { - cmd += ` -O "${options.outputFile}"`; - } - - if (options.outputFormat && options.outputFormat !== 'markdown') { - cmd += ` -F ${options.outputFormat}`; - } - - if (options.includePriority) { - cmd += ` --include-priority`; - } - - if (options.fullDirectoryTree) { - cmd += ` --full-directory-tree`; - } - - if (options.encoding) { - cmd += ` -c ${options.encoding}`; - } - - if (options.lineNumbers) { - cmd += ` --line-numbers`; - } - - // Add exclude options - use a single -e flag with comma-separated patterns - if (allExcludes.length > 0) { - cmd += ` -e "${allExcludes.join(',')}"`; - } - - // Add include options - use a single -i flag with comma-separated patterns - if (options.include) { - const includePatterns = options.include.split(',') - .map(pattern => pattern.trim()) - .filter(pattern => pattern); - - if (includePatterns.length > 0) { - cmd += ` -i "${includePatterns.join(',')}"`; - } - } - - // Add the directory path at the end - cmd += ` "${options.directory}"`; + const cmd = buildCommand(options, dedupedExcludes); console.log('\n' + chalk.green('Generated code2prompt command:')); console.log(chalk.yellow(cmd)); // Execute the command if requested - if (options.execute) { - console.log(chalk.blue('\nExecuting command...')); - try { - execSync(cmd, { stdio: 'inherit' }); - console.log(chalk.green('\nCommand executed successfully!')); - } catch (error) { - console.error(chalk.red('\nError executing command:'), error.message); - } - } + executeCommand(cmd, options.execute); } catch (error) { - console.error(chalk.red('Error:'), error.message); + utils.log.error('Error: ' + error.message); process.exit(1); } } // Run the main function main().catch(err => { - console.error(chalk.red('Error:'), err.message); + utils.log.error('Error: ' + err.message); process.exit(1); }); \ No newline at end of file diff --git a/package.json b/package.json index d06fda5..e052749 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "description": "A CLI tool to manage code2prompt file size limits", "main": "index.js", "bin": { - "code2prompt-manager": "./index.js" + "code2prompt-manager": "index.js" }, "scripts": { "test": "echo \"Error: no test specified\" && exit 1"