Initial commit
This commit is contained in:
201
skills/argparse-patterns/templates/argparse-to-commander.ts
Normal file
201
skills/argparse-patterns/templates/argparse-to-commander.ts
Normal file
@@ -0,0 +1,201 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* argparse patterns translated to commander.js
|
||||
*
|
||||
* Shows equivalent patterns between Python argparse and Node.js commander
|
||||
*
|
||||
* Usage:
|
||||
* npm install commander
|
||||
* node argparse-to-commander.ts deploy production --force
|
||||
*/
|
||||
|
||||
import { Command, Option } from 'commander';
|
||||
|
||||
const program = new Command();
|
||||
|
||||
// ===== Basic Configuration (like ArgumentParser) =====
|
||||
program
|
||||
.name('mycli')
|
||||
.description('A powerful CLI tool')
|
||||
.version('1.0.0');
|
||||
|
||||
// ===== Subcommands (like add_subparsers) =====
|
||||
|
||||
// Init command (like subparsers.add_parser('init'))
|
||||
program
|
||||
.command('init')
|
||||
.description('Initialize a new project')
|
||||
.option('-t, --template <type>', 'project template', 'basic')
|
||||
.option('-p, --path <path>', 'project path', '.')
|
||||
.action((options) => {
|
||||
console.log(`Initializing project with ${options.template} template...`);
|
||||
console.log(`Path: ${options.path}`);
|
||||
});
|
||||
|
||||
// Deploy command with choices (like choices=[...])
|
||||
program
|
||||
.command('deploy <environment>')
|
||||
.description('Deploy to specified environment')
|
||||
.addOption(
|
||||
new Option('-m, --mode <mode>', 'deployment mode')
|
||||
.choices(['fast', 'safe', 'rollback'])
|
||||
.default('safe')
|
||||
)
|
||||
.option('-f, --force', 'force deployment', false)
|
||||
.action((environment, options) => {
|
||||
console.log(`Deploying to ${environment} in ${options.mode} mode`);
|
||||
if (options.force) {
|
||||
console.log('Warning: Force mode enabled');
|
||||
}
|
||||
});
|
||||
|
||||
// ===== Nested Subcommands (like nested add_subparsers) =====
|
||||
const config = program
|
||||
.command('config')
|
||||
.description('Manage configuration');
|
||||
|
||||
config
|
||||
.command('get <key>')
|
||||
.description('Get configuration value')
|
||||
.action((key) => {
|
||||
console.log(`Getting config: ${key}`);
|
||||
});
|
||||
|
||||
config
|
||||
.command('set <key> <value>')
|
||||
.description('Set configuration value')
|
||||
.option('-f, --force', 'overwrite existing value')
|
||||
.action((key, value, options) => {
|
||||
console.log(`Setting ${key} = ${value}`);
|
||||
if (options.force) {
|
||||
console.log('(Overwriting existing value)');
|
||||
}
|
||||
});
|
||||
|
||||
config
|
||||
.command('list')
|
||||
.description('List all configuration values')
|
||||
.option('--format <format>', 'output format', 'text')
|
||||
.action((options) => {
|
||||
console.log(`Listing configuration (format: ${options.format})`);
|
||||
});
|
||||
|
||||
// ===== Boolean Flags (like action='store_true') =====
|
||||
program
|
||||
.command('build')
|
||||
.description('Build the project')
|
||||
.option('--verbose', 'enable verbose output')
|
||||
.option('--debug', 'enable debug mode')
|
||||
.option('--no-cache', 'disable cache (enabled by default)')
|
||||
.action((options) => {
|
||||
console.log('Building project...');
|
||||
console.log(`Verbose: ${options.verbose || false}`);
|
||||
console.log(`Debug: ${options.debug || false}`);
|
||||
console.log(`Cache: ${options.cache}`);
|
||||
});
|
||||
|
||||
// ===== Type Coercion (like type=int, type=float) =====
|
||||
program
|
||||
.command('server')
|
||||
.description('Start server')
|
||||
.option('-p, --port <number>', 'server port', parseInt, 8080)
|
||||
.option('-t, --timeout <seconds>', 'timeout in seconds', parseFloat, 30.0)
|
||||
.option('-w, --workers <number>', 'number of workers', parseInt, 4)
|
||||
.action((options) => {
|
||||
console.log(`Starting server on port ${options.port}`);
|
||||
console.log(`Timeout: ${options.timeout}s`);
|
||||
console.log(`Workers: ${options.workers}`);
|
||||
});
|
||||
|
||||
// ===== Variadic Arguments (like nargs='+') =====
|
||||
program
|
||||
.command('process <files...>')
|
||||
.description('Process multiple files')
|
||||
.option('--format <format>', 'output format', 'json')
|
||||
.action((files, options) => {
|
||||
console.log(`Processing ${files.length} file(s):`);
|
||||
files.forEach((file) => console.log(` - ${file}`));
|
||||
console.log(`Output format: ${options.format}`);
|
||||
});
|
||||
|
||||
// ===== Mutually Exclusive Options =====
|
||||
// Note: Commander doesn't have built-in mutually exclusive groups
|
||||
// You need to validate manually
|
||||
program
|
||||
.command('export')
|
||||
.description('Export data')
|
||||
.option('--json <file>', 'export as JSON')
|
||||
.option('--yaml <file>', 'export as YAML')
|
||||
.option('--xml <file>', 'export as XML')
|
||||
.action((options) => {
|
||||
const formats = [options.json, options.yaml, options.xml].filter(Boolean);
|
||||
if (formats.length > 1) {
|
||||
console.error('Error: --json, --yaml, and --xml are mutually exclusive');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (options.json) {
|
||||
console.log(`Exporting as JSON to ${options.json}`);
|
||||
} else if (options.yaml) {
|
||||
console.log(`Exporting as YAML to ${options.yaml}`);
|
||||
} else if (options.xml) {
|
||||
console.log(`Exporting as XML to ${options.xml}`);
|
||||
}
|
||||
});
|
||||
|
||||
// ===== Required Options (like required=True) =====
|
||||
program
|
||||
.command('login')
|
||||
.description('Login to service')
|
||||
.requiredOption('--username <username>', 'username for authentication')
|
||||
.requiredOption('--password <password>', 'password for authentication')
|
||||
.option('--token <token>', 'authentication token (alternative to password)')
|
||||
.action((options) => {
|
||||
console.log(`Logging in as ${options.username}`);
|
||||
});
|
||||
|
||||
// ===== Custom Validation =====
|
||||
function validatePort(value: string): number {
|
||||
const port = parseInt(value, 10);
|
||||
if (isNaN(port) || port < 1 || port > 65535) {
|
||||
throw new Error(`Invalid port: ${value} (must be 1-65535)`);
|
||||
}
|
||||
return port;
|
||||
}
|
||||
|
||||
program
|
||||
.command('connect')
|
||||
.description('Connect to server')
|
||||
.option('-p, --port <number>', 'server port', validatePort, 8080)
|
||||
.action((options) => {
|
||||
console.log(`Connecting to port ${options.port}`);
|
||||
});
|
||||
|
||||
// ===== Argument Groups (display organization) =====
|
||||
// Note: Commander doesn't have argument groups for help display
|
||||
// You can organize with comments or separate commands
|
||||
|
||||
// ===== Parse Arguments =====
|
||||
program.parse();
|
||||
|
||||
/**
|
||||
* COMPARISON SUMMARY:
|
||||
*
|
||||
* argparse Pattern | commander.js Equivalent
|
||||
* ---------------------------------|--------------------------------
|
||||
* ArgumentParser() | new Command()
|
||||
* add_argument() | .option() or .argument()
|
||||
* add_subparsers() | .command()
|
||||
* choices=[...] | .choices([...])
|
||||
* action='store_true' | .option('--flag')
|
||||
* action='store_false' | .option('--no-flag')
|
||||
* type=int | parseInt
|
||||
* type=float | parseFloat
|
||||
* nargs='+' | <arg...>
|
||||
* nargs='*' | [arg...]
|
||||
* required=True | .requiredOption()
|
||||
* default=value | option(..., default)
|
||||
* help='...' | .description('...')
|
||||
* mutually_exclusive_group() | Manual validation
|
||||
* add_argument_group() | Organize with subcommands
|
||||
*/
|
||||
Reference in New Issue
Block a user