Commander.js简介及使用教程
简介
事实上,在Nodejs或ruby等语言环境里,只要在文件头部添加一行所谓的shebang(提供一个执行环境),就可以将代码转为命令行执行。比如在Node中文件头这样写:
#!/usr/bin/env node
但是命令行选项处理和流程控制很不方便,所以才有了命令行框架的出现。Commander 是一款重量轻,表现力和强大的命令行框架。提供了用户命令行输入和参数解析强大功能。Commander 源自一个同名的Ruby项目。它 是 TJ 写的一个帮助快速开发Nodejs命令行工具的package。
安装
在项目根目录执行:
npm install commander --save
选项
指令带的选项由.option()
定义,也会作为选项的文档。下面的例子从process.argv
解析了选项和参数,没有被选项占用的参数会作为program.args
数组。所有的属性带[]
就是可选的,带<>
的是必需参数。
option()
接收四个参数
- 第一个参数是属性,可以使用逗号分隔开
- 第二个为 option 描述, 会在 help 信息里展示出来
- 第三个参数为回调函数
- 第四个参数为默认值
#!/usr/bin/env node
/**
* Module dependencies.
*/
var program = require('commander');
program
.version('0.1.0')
.option('-p, --peppers', 'Add peppers')
.option('-P, --pineapple', 'Add pineapple')
.option('-b, --bbq-sauce', 'Add bbq sauce')
.option('-c, --cheese [type]', 'Add the specified type of cheese [marble]', 'marble')
.parse(process.argv);
console.log('you ordered a pizza with:');
if (program.peppers) console.log(' - peppers');
if (program.pineapple) console.log(' - pineapple');
if (program.bbqSauce) console.log(' - bbq');
console.log(' - %s cheese', program.cheese);
短属性会被解析成单独的一个参数。例如-abc
会被解析成-a -b -c
,多单词的选项比如--template-engine
会被解析成驼峰式templateEngine
。
如果多单词的选项是以--no
为前缀的,则代表是否定的,如:--no-sauce
则代表program.sauce
的值为false
。
在option的第一个参数里, 除了short
,long option
,还可以指定option类型,分隔符也是|
和,
其中
<...flag>
required参数,使用时后边必须跟参数值, 否则程序会报错[flag]
optional参数,后面可以选择是否跟参数值- 如果以
--no
则表示默认为false
(没有使用--no
默认值为true
)
function range(val) {
return val.split('..').map(Number);
}
function list(val) {
return val.split(',');
}
function collect(val, memo) {
memo.push(val);
return memo;
}
function increaseVerbosity(v, total) {
return total + 1;
}
program
.version('0.1.0')
.usage('[options] <file ...>')
.option('-i, --integer <n>', 'An integer argument', parseInt)
.option('-f, --float <n>', 'A float argument', parseFloat)
.option('-r, --range <a>..<b>', 'A range', range)
.option('-l, --list <items>', 'A list', list)
.option('-o, --optional [value]', 'An optional value')
.option('-c, --collect [value]', 'A repeatable value', collect, [])
.option('-v, --verbose', 'A value that can be increased', increaseVerbosity, 0)
.option('-d, --no-date', 'don‘t display current date')
.parse(process.argv);
console.log(' int: %j', program.integer);
console.log(' float: %j', program.float);
console.log(' optional: %j', program.optional);
program.range = program.range || [];
console.log(' range: %j..%j', program.range[0], program.range[1]);
console.log(' list: %j', program.list);
console.log(' collect: %j', program.collect);
console.log(' verbosity: %j', program.verbose);
console.log(' args: %j', program.args);
option
的第三个参数不仅可以是回调函数,也可以为一个正则表达式:
program
.version('0.1.0')
.option('-s --size <size>', 'Pizza size', /^(large|medium|small)$/i, 'medium')
.option('-d --drink [drink]', 'Drink', /^(coke|pepsi|izze)$/i)
.parse(process.argv);
console.log(' size: %j', program.size);
console.log(' drink: %j', program.drink);
如果匹配成功则显示匹配值,匹配不成功则显示默认值或者true
或者false
,没有这个选项的话则为undefined
版本号
向你的项目中添加版本号,当在命令行中使用-V
或者--version
的时候显示版本号。
$ ./examples/pizza -V
0.0.1
如果你想使用-v
而不是-V
来显示版本号,只要自定义版本号的选项即可,版本的属性选项可以是任何名字,但是长属性不能省略。
program
.version('0.0.1', '-v, --version')
Command-具体的选项
你也可以为一个命令添加若干选项:
#!/usr/bin/env node
var program = require('commander');
program
.command('rm <dir>')
.option('-r, --recursive', 'Remove recursively')
.action(function (dir, cmd) {
console.log('remove ' + dir + (cmd.recursive ? ' recursively' : ''))
})
program.parse(process.argv)
一个命令的选项只有在这个命令使用的时候才可以使用,任何未知的选项都会报错,如果一个基于action
的命令没有定义action
,那么选项也是不合法的。
可变的参数
command
的最后一个参数可以是一个可变的参数,如果想要使用可变的参数的话你要在参数名字后面加上...
:
#!/usr/bin/env node
/**
* Module dependencies.
*/
var program = require('commander');
program
.version('0.1.0')
.command('rmdir <dir> [otherDirs...]')
.action(function (dir, otherDirs) {
console.log('rmdir %s', dir);
if (otherDirs) {
otherDirs.forEach(function (oDir) {
console.log('rmdir %s', oDir);
});
}
});
program.parse(process.argv);
一个数组会用在可变的参数里面,这不仅会应用在program.args
也会传递给你的action
中显示。
具体化参数语法
我们可以使用arguments()
来更加具体地处理参数,注意这个参数是除了选项属性之外的参数。
#!/usr/bin/env node
var program = require('commander');
program
.version('0.1.0')
.arguments('<cmd> [env]')
.action(function (cmd, env) {
cmdValue = cmd;
envValue = env;
});
program.parse(process.argv);
if (typeof cmdValue === 'undefined') {
console.error('no command given!');
process.exit(1);
}
console.log('command:', cmdValue);
console.log('environment:', envValue || "no environment given");
node env -a b cd #command: c environment: d
node env a b # command: a environment: b
类Git风格子命令
当command()
被调用的时候且有description
这个参数,不能有action()
调用处理子命令,否则的话会报错。这会告诉commander
你要使用分离的可执行文件对于子命令,就像Git
和一些其他的工具一样。
commander
会尝试去在目录里的入口脚本搜索同名的可执行的文件,例如pm-install
,pm-search
。
选项会被传递进command()
,填写opts.noHelp:true
会移除生成help
输出,填写opts.isDefaut
会运行这个子命令如果没有子命令被指定运行的话。
如果你的程序想要被设计成全局安装,注意可执行文件拥有正确的权限,比如755
。
// file: ./examples/pm
var program = require('commander');
program
.version('0.1.0')
.command('install [name]', 'install one or more packages')
.command('search [query]', 'search with optional query')
.command('list', 'list packages installed', {isDefault: true})
.parse(process.argv);
事件监听
命名多少个命令就监听多少命令,--help
为默认监听事件。
program.on('--help', function(argv,test){
process.exit(1);
});
以和谐方式执行--harmony
你可以有两种方式使用--harmony
参数:
#! /usr/bin/env node --harmony
在子命令脚本头加入,但是可能有些操作系统不支持- 使用
--harmony
在你使用命令行的时候
自动生成帮助信息--help
Commander
会根据配置的option
,sub-command
等信息,自动生成help信息。
自定义帮助信息
可以通过监听--help
事件来输出额外的帮助信息
#!/usr/bin/env node
/**
* Module dependencies.
*/
var program = require('commander');
program
.version('0.1.0')
.option('-f, --foo', 'enable some foo')
.option('-b, --bar', 'enable some bar')
.option('-B, --baz', 'enable some baz');
// must be before .parse() since
// node's emit() is immediate
program.on('--help', function(){
console.log(' Examples:');
console.log('');
console.log(' $ custom-help --help');
console.log(' $ custom-help -h');
console.log('');
});
program.parse(process.argv);
console.log('stuff');
.outputHelp(cb)
输出帮助信息并且不退出,可选的回调函数允许处理帮助信息在展示之前。
.help(cb)
输出帮助信息立刻退出。