python2ib
Version:
Convert Python code to IB Pseudocode format
248 lines (245 loc) • 8.12 kB
JavaScript
/**
* CLI tool for Python to IB Pseudocode converter
*/
import { readFileSync, writeFileSync, existsSync } from 'fs';
import { resolve } from 'path';
import { PythonToIBConverter } from './index.js';
/** Parse command line arguments */
function parseArgs(args) {
const options = {};
for (let i = 0; i < args.length; i++) {
const arg = args[i];
switch (arg) {
case '-h':
case '--help':
options.help = true;
break;
case '-v':
case '--version':
options.version = true;
break;
case '-i':
case '--input':
options.input = args[++i];
break;
case '-o':
case '--output':
options.output = args[++i];
break;
case '-c':
case '--config':
options.config = args[++i];
break;
case '--validate':
options.validate = true;
break;
case '--info':
options.info = true;
break;
case '--indent':
const indentType = args[++i];
if (indentType === 'spaces' || indentType === 'tabs') {
options.indent = indentType;
}
else {
console.error(`Invalid indent type: ${indentType}. Use 'spaces' or 'tabs'.`);
process.exit(1);
}
break;
case '--indent-size':
const size = parseInt(args[++i], 10);
if (isNaN(size) || size < 1 || size > 8) {
console.error(`Invalid indent size: ${args[i]}. Use a number between 1 and 8.`);
process.exit(1);
}
options.indentSize = size;
break;
case '--strict':
options.strict = true;
break;
case '-q':
case '--quiet':
options.quiet = true;
break;
case '--verbose':
options.verbose = true;
break;
default:
if (arg.startsWith('-')) {
console.error(`Unknown option: ${arg}`);
process.exit(1);
}
else if (!options.input) {
options.input = arg;
}
break;
}
}
return options;
}
/** Load configuration from file */
function loadConfig(configPath) {
try {
if (!existsSync(configPath)) {
console.error(`Configuration file not found: ${configPath}`);
process.exit(1);
}
const configContent = readFileSync(configPath, 'utf-8');
return JSON.parse(configContent);
}
catch (error) {
console.error(`Failed to load configuration: ${error instanceof Error ? error.message : String(error)}`);
process.exit(1);
}
}
/** Show help message */
function showHelp() {
console.log(`
Python to IB Pseudocode Converter
Usage:
python2ib [options] <input-file>
python2ib [options] -i <input-file> -o <output-file>
Options:
-h, --help Show this help message
-v, --version Show version information
-i, --input <file> Input Python file
-o, --output <file> Output file (default: stdout)
-c, --config <file> Configuration file (JSON)
--validate Validate Python syntax only
--info Show supported/unsupported constructs
--indent <type> Indentation type: 'spaces' or 'tabs' (default: spaces)
--indent-size <size> Indentation size: 1-8 (default: 4)
--strict Enable strict mode
-q, --quiet Suppress non-error output
--verbose Enable verbose output
Examples:
python2ib script.py
python2ib -i script.py -o pseudocode.txt
python2ib --validate script.py
python2ib --info
python2ib --indent tabs --indent-size 2 script.py
`);
}
/** Show version information */
function showVersion() {
// In a real implementation, this would read from package.json
console.log('Python to IB Pseudocode Converter v1.0.0');
}
/** Show construct information */
function showConstructInfo() {
const converter = new PythonToIBConverter();
const supported = converter.getSupportedConstructs();
const unsupported = converter.getUnsupportedConstructs();
console.log('\nSupported Python Constructs:');
supported.forEach(construct => console.log(` ✓ ${construct}`));
console.log('\nUnsupported Python Constructs:');
unsupported.forEach(construct => console.log(` ✗ ${construct}`));
console.log('');
}
/** Validate Python file */
function validatePython(filePath, verbose) {
try {
const pythonCode = readFileSync(filePath, 'utf-8');
const converter = new PythonToIBConverter();
const result = converter.validateSyntax(pythonCode);
if (result.isValid) {
if (verbose) {
console.log(`✓ ${filePath}: Valid Python syntax`);
}
process.exit(0);
}
else {
console.error(`✗ ${filePath}: Invalid Python syntax`);
result.errors.forEach(error => console.error(` ${error}`));
process.exit(1);
}
}
catch (error) {
console.error(`Failed to validate ${filePath}: ${error instanceof Error ? error.message : String(error)}`);
process.exit(1);
}
}
/** Main CLI function */
function main() {
const args = process.argv.slice(2);
const options = parseArgs(args);
// Handle special commands
if (options.help) {
showHelp();
return;
}
if (options.version) {
showVersion();
return;
}
if (options.info) {
showConstructInfo();
return;
}
// Validate input
if (!options.input) {
console.error('Error: No input file specified. Use --help for usage information.');
process.exit(1);
}
const inputPath = resolve(options.input);
if (!existsSync(inputPath)) {
console.error(`Error: Input file not found: ${inputPath}`);
process.exit(1);
}
// Handle validation mode
if (options.validate) {
validatePython(inputPath, options.verbose || false);
return;
}
try {
// Load configuration
let config = {};
if (options.config) {
config = loadConfig(options.config);
}
// Override with CLI options
if (options.indent) {
config.indentStyle = options.indent;
}
if (options.indentSize) {
config.indentSize = options.indentSize;
}
if (options.strict) {
config.strictMode = true;
}
// Read input file
const pythonCode = readFileSync(inputPath, 'utf-8');
if (options.verbose) {
console.error(`Reading from: ${inputPath}`);
}
// Convert
const converter = new PythonToIBConverter(config);
const pseudocode = converter.convertSync(pythonCode);
// Output
if (options.output) {
const outputPath = resolve(options.output);
writeFileSync(outputPath, pseudocode, 'utf-8');
if (!options.quiet) {
console.error(`Output written to: ${outputPath}`);
}
}
else {
// Output to stdout
console.log(pseudocode);
}
if (options.verbose) {
console.error('Conversion completed successfully.');
}
}
catch (error) {
console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
process.exit(1);
}
}
// Run CLI if this file is executed directly
if (import.meta.url === `file://${process.argv[1]}`) {
main();
}
export { main as runCLI, parseArgs, loadConfig };
//# sourceMappingURL=cli.js.map