Node CLI 之 Commander.js (1)
官网地址: https://github.com/tj/commander.js/blob/f1ae2db8e2da01d6efcbfd59cbf82202f864b0c1/Readme_zh-CN.md
Commander.js是node.js命令行界面的完整解决方案
开始
- 新建一个node工程
- 执行 npm install commander
- package.json中新增代码
- 添加 #! /usr/bin/env node,用于识别是node命令文件
"bin": {
"cli": "./index.js"
}
声明 program 变量
/ CommonJS (.cjs)
const { program } = require('commander');
如果程序较为复杂,用户需要以多种方式来使用 Commander,如单元测试等。创建本地 Command 对象是一种更好的方式:
const { Command } = require('commander');
const program = new Command();
选项 option
使用 .option 实现,举个例子,然后再解释难点
program
.option('-d, --debug', 'output extra debugging')
.option('-s, --small', 'small pizza size')
.option('-p, --pizza-type <type>', 'flavour of pizza');
.option('-c, --cheese <type>', 'add the specified type of cheese', 'blue');
.option('-d, --drink [item]', 'output extra debugging', function deb (v) {
console.log('1---', arguments);
return '123'
})
- 第一个参数是选项名称,第二个参数选项描述, 第三个参数是默认值, 第四个为过滤函数,会改改变用户输入的值
- 每个选项可以定义一个短选项名称(-后面接单个字符)
- 一个长选项名称(–后面接一个或多个单词),驼峰命名法(camel-case)
- 短名称和长名称之间可以使用逗号,空格,|分割
- 有两种最常用的选项
- 一类是 boolean 型选项,选项无需配置参数,
- 另一类选项则可以设置参数(使用尖括号声明在该选项后,如–expect )。如果在命令行中不指定具体的选项及参数,则会被定义为undefine
调用方式
serve -p 80
serve -p80
serve --port 80
serve --port=80
项及其选项参数可以用空格分隔,也可以组合成同一个参数。选项参数可以直接跟在短选项之后,也可以在长选项后面加上 = 。
完整例子
program
.option('-d, --debug', 'output extra debugging')
.option('-s, --small', 'small pizza size')
.option('-p, --pizza-type <type>', 'flavour of pizza');
.option('-d, --drink [item]', 'output extra debugging', function deb (v) {
console.log('1---', arguments);
return '123'
})
program.parse(process.argv);
const options = program.opts();
if (options.debug) console.log(options);
console.log('pizza details:');
if (options.small) console.log('- small pizza size');
if (options.pizzaType) console.log(`- ${options.pizzaType}`);
必填选项
通过 .requiredOption 方法可以设置选项为必填。必填选项要么设有默认值,要么必须在命令行中输入,对应的属性字段在解析时必定会有赋值。该方法其余参数与 .option一致
program
.requiredOption('-c, --cheese <type>', 'pizza must have cheese');
program.parse();
终端中部署入参数,会报错
error: required option '-c, --cheese <type>' not specified
变长参数选项
通过使用 … 来设置参数为可变长参数
program
.option('-n, --number <numbers...>', 'specify numbers')
.option('-l, --letter [letters...]', 'specify letters');
program.parse();
console.log('Options: ', program.opts());
console.log('Remaining arguments: ', program.args);
$ collect -n 1 2 3 --letter a b c
Options: { number: [ '1', '2', '3' ], letter: [ 'a', 'b', 'c' ] }
Remaining arguments: []
$ collect --letter=A -n80 operand
Options: { number: [ '80' ], letter: [ 'A' ] }
Remaining arguments: [ 'operand' ]
$ collect --letter -n 1 -n 2 3 -- operand
Options: { number: [ '1', '2', '3' ], letter: true }
Remaining arguments: [ 'operand' ]
其他选项配置
大多数情况下,选项均可通过.option()方法添加。但对某些不常见的用例,也可以直接构造Option对象,对选项进行更详尽的配置
program
.addOption(new Option('-s, --secret').hideHelp())
.addOption(new Option('-t, --timeout <delay>', 'timeout in seconds').default(60, 'one minute'))
.addOption(new Option('-d, --drink <size>', 'drink size').choices(['small', 'medium', 'large']))
.addOption(new Option('-p, --port <number>', 'port number').env('PORT'))
.addOption(new Option('--donate [amount]', 'optional donation in dollars').preset('20').argParser(parseFloat))
.addOption(new Option('--disable-server', 'disables the server').conflicts('port'))
.addOption(new Option('--free-drink', 'small drink included free ').implies({ drink: 'small' }));
版本选项
.version 方法可以设置版本,其默认选项为-V和–version,设置了版本后,命令行会输出当前的版本号
program.version('0.0.1');
命令
通过 .command 或 .addCommand 可以配置命令, 有两种实现方式
- 为命令绑定处理函数
- 将命令单独写成一个可执行文件
先看例子
// 通过绑定处理函数实现命令(这里的指令描述为放在`.command`中)
// 返回新生成的命令(即该子命令)以供继续配置
program
.command('clone <source> [destination]')
.description('clone a repository into a newly created directory')
.option('-t, --typeName <typeName>', '基于哪个项目')
.action((source, destination) => {
console.log('clone command called');
});
// 通过独立的的可执行文件实现命令 (注意这里指令描述是作为`.command`的第二个参数)
// 返回最顶层的命令以供继续添加子命令
program
.command('start <service>', 'start named service')
.command('stop [service]', 'stop named service, or all if no name supplied');
// 分别装配命令
// 返回最顶层的命令以供继续添加子命令
program
.addCommand(build.makeBuildCommand());
- .command 的第一个参数为命令名称, 命令参数可以跟在名称后面,也可以用.argument 单独指定, 参数可为必选的(尖括号表示)、可选的(方括号表示)或变长参数(点号表示,如果使用,只能是最后一个参数)
- option 为命令中的选项 比如 vue create my-project -t vue-template
- .description 为命令描述
- .action 为命令触发之后,执行的函数
举个例子:
program
.command('rmdir <soure>')
.description('remove some directory')
.option('-f, --force', '强制删除')
.action((source, destination) => {
console.log('remove some directory');
});
// 调用方式
// Try the following:
// rmdir ./project
// rmdir ./project -f
// rmdir ./project --force
program
.command('add')
.argument('<first>', 'integer argument', myParseInt)
.argument('[second]', 'integer argument', myParseInt, 1000)
.action((first, second) => {
console.log(`${first} + ${second} = ${first + second}`);
});
// 调用方式
// Try the following:
// add 1
// add 1 2
program
.argument("<name>")
.option("-t, --title <honorific>", "title to use before name")
.option("-d, --debug", "display some debugging")
.action((name, options, command) => {
if (options.debug) {
console.error("Called %s with options %o", command.name(), options);
}
const title = options.title ? `${options.title} ` : "";
console.log(`Thank-you ${title}${name}`);
});
// 调用方式
// Try the following:
// node thank.js John
// node thank.js Doe --title Mr
// node thank.js --debug Doe --title Mr