UNPKG

unqommented

Version:

A Node.js utility that quickly identifies files with uncommented code in your codebase. Designed for developers who want to efficiently tell LLMs exactly which files need comments added.

113 lines (102 loc) 5.08 kB
#!/usr/bin/env node /** * @file Command-line interface for the unqommented code analysis tool * @description This script provides a user-friendly CLI for scanning directories to find files * with uncommented code. It's specifically designed for LLM-assisted workflows where developers * need to quickly identify which files need commenting before feeding them to AI assistants. * @rationale The CLI uses yargs for robust argument parsing and structured output formatting * that makes it easy to integrate into development workflows and automation scripts. * @architectural_decision We chose yargs over minimist for better help generation and validation, * and implemented batch output formatting to make results easier to process in chunks. * * @example * // Scan the current directory * npx unqommented * * @example * // Scan a specific directory * npx unqommented ./src */ const { findUncommentedFiles } = require('../lib/utils.js'); const localVars = require('../config/localVars'); const { qerrors } = require('qerrors'); // For structured error logging const yargs =require('yargs/yargs'); const { hideBin } = require('yargs/helpers'); /** * @function main * @description The main execution block implementing the CLI workflow * @rationale Uses an Immediately Invoked Function Expression (IIFE) to enable async/await * at the top level in Node.js versions before 14.8. This pattern ensures compatibility * while providing clean async error handling. The function orchestrates argument parsing, * file scanning, and result formatting in a single execution flow. * @error_handling All errors are caught and logged with structured error information via * qerrors for better debugging and user experience. */ (async () => { let argv; try { // Use yargs to parse command-line arguments. This provides a robust and flexible // way to define and handle CLI options, including the 'directory' argument. // The .command() method defines the primary command, and .positional() specifies // the 'directory' argument, its type, and a default value. argv = yargs(hideBin(process.argv)) .usage('Usage: $0 [directory] [options]') .command('$0 [directory]', 'Scan a directory for uncommented files', (yargs) => { yargs.positional('directory', { describe: 'The directory to scan for uncommented code', type: 'string', default: '.', // Default to the current directory if not specified }); }) .help() // Automatically generate a help message .argv; // Execute the scan and await the results. The findUncommentedFiles function // returns both the list of uncommented files and any errors that occurred. const { uncommentedFiles, errors } = await findUncommentedFiles(argv.directory); // Process and display the results. If no uncommented files are found, a // success message is shown. Otherwise, the paths of the uncommented files are printed. if (uncommentedFiles.length === 0) { console.log(localVars.CLI_MESSAGES.NO_UNCOMMENTED_FILES); } else { // Split files into three evenly distributed batches const totalFiles = uncommentedFiles.length; const baseSize = Math.floor(totalFiles / 3); const remainder = totalFiles % 3; // Calculate batch sizes - distribute remainder evenly among first batches const batchSizes = [ baseSize + (remainder > 0 ? 1 : 0), // First batch gets extra if remainder > 0 baseSize + (remainder > 1 ? 1 : 0), // Second batch gets extra if remainder > 1 baseSize // Third batch gets base size ]; // Create batches using calculated sizes let startIndex = 0; const batches = batchSizes.map(size => { const batch = uncommentedFiles.slice(startIndex, startIndex + size); startIndex += size; return batch; }); // Print each batch with a separator batches.forEach((batch, index) => { if (batch.length > 0) { console.log(`\n--- Batch ${index + 1} ---`); batch.forEach(f => console.log(f)); } }); // Print total files found at the bottom console.log(`\nTotal files found: ${uncommentedFiles.length}`); } // Display any errors that were collected during the scan. This ensures that // file-specific issues are reported without halting the entire process. errors.forEach(err => { const fileInfo = err.file ? `${err.file}: ` : ''; console.error(`${localVars.CLI_MESSAGES.ERROR_PREFIX} ${fileInfo}${err.error}`); }); } catch (error) { // The catch block handles critical errors that prevent the CLI from running, // such as an invalid directory. It logs the error using qerrors for structured // logging and exits with a non-zero status code to indicate failure. qerrors(error, 'cli', { directory: argv?.directory || 'unknown' }); console.error(`${localVars.CLI_MESSAGES.ERROR_PREFIX} ${error.message}`); process.exit(1); } })();