Base
用 node
写一个在终端运行的命令行程序。
首先基础是基于 node
的一个全局变量 process
,他提供有关当前 node
进程的信息,并对其进行控制。
而 process.argv
是包含启动 node
进程时传入的命令行参数,写终端程序的基础就是这个数组。
测试 code:
#! /usr/bin/env node
console.log(process.argv)
运行程序,可以看到如下输出
$ node init/index rm test
[
'C:\\Program Files\\nodejs\\node.exe',
'D:\\Alibaba\\Dawn\\test\\init\\index',
'rm',
'test'
]
process.argv
属性返回一个数组,其中包含当启动 node
进程时传入的命令行参数。 第一个元素是 process.execPath
。 如果需要访问 argv[0]
的原始值,输出 process.argv0
。 第二个元素将是正在执行的 JavaScript 文件的路径。 其余元素将是任何其他命令行参数。
我们需要解析的是此数组的第三个极其之后的元素。
但是自己解析是非常麻烦的,这里引入一个库 commander.js
commander
commander
是一个 node.js
命令行界面的完整解决方案,受 Ruby
的启发。 API文档
commander
的 code 看起来是下面这样
#!/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);
并且会自动生成 help
文档
常用的参数如下:
version
格式:.version('0.0.1')
描述:用于设置程序的版本信息
program
.version('0.0.1')
.parse(process.argv)
option
格式:.option('-n, --name <param>', 'description', 'GK')
描述:
- 第一个参数定义配置的选项,用「
|
、,
」去连接缩写和全写。参数可以使用「<>
、[]
」去描述,前者是必选参数,后者为可选参数。 - 第二个参数用来简单描述你的配置选项功能。
- 第三个参数为选项默认值,可选。
没有匹配任何选项的参数将会放到 program.args 数组中
option
使用规则如下
program
.option('-m --paramm [value]', 'description')
.option('-n --paramn <value>', 'description')
.parse(process.argv)
console.log('cli')
if (program.paramm) console.log('paramM: ', program.paramm)
if (program.paramn) console.log('paramN: ', program.paramn)
[]
为可选参数不添加不会报错
$ node ./bin/cli.js -m
在 program.[paramName]
中获取到输入的参数
$ node ./bin/cli.js -m testCode
$ node ./bin/cli.js -n testCode
<>
为必选参数
$ node ./bin/cli.js -n
而下面的这两种命令时相同的 -abc
、-a -b -c
还可以下像下面这样去输出,以峰驼法获取参数
program
.option('-i --template-engine <value>', 'description')
.parse(process.argv)
console.log('cli')
if (program.templateEngine) console.log('templateEngine: ', program.templateEngine)
然后执行命令
$ node ./bin/cli.js -i testCode
command
格式:.command('name <param>', 'description')
描述:command 可以单独使用或者和 action(fn)
配合使用
-
第一个参数为命令定义,同样可以使用「
<>
、[]
」去定义参数。
命令的最后一个参数可以是可变参数, 并且只有最后一个参数可变。例如这样去使用,.command('rmdir <dir> [otherDirs...]')
,然后在.action
中获取然后解析,.action(function(oDir) {})
,可变参数的值以 数组 的形式保存。 -
第二个参数可选,为命令描述。
当.command()
带有描述参数时,不能采用.action(fn)
来处理子命令,否则会出错。这告诉commander
,你将采用单独的可执行文件作为子命令,就像git(1)
和其他流行的工具一样。Commander
将会尝试在入口脚本(例如 ./examples/pm)的目录中搜索program-command
形式的可执行文件,例如pm-install
,pm-search
。 -
第三个参数可以控制其他的一些行为,例如指定
opts.noHelp
为true
将从生成的帮助输出中剔除该选项。指定opts.isDefault
为true
将会在没有其它子命令指定的情况下,执行该子命令。
program
.version('0.0.1')
.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);
Other
-
如果你打算全局安装该命令,请确保可执行文件有对应的权限,例如 755。
-
--harmony
你可以采用两种方式启用--harmony
- 在子命令脚本中加上
#!/usr/bin/env node --harmony
。注意一些系统版本不支持此模式。 - 在指令调用时加上
--harmony
参数,例如node --harmony examples/pm publish
。--harmony
选项在开启子进程时会被保留。
- 在子命令脚本中加上
arguments
格式:.arguments('<cmd> [env]')
描述:指定参数的语法,和 .action
结合使用
action
格式:.action(fn)
描述:用来定义 command
、arguments
的命令执行回调函数
和 command
结合使用
program
.version('0.0.1')
.command('rm <dir>', 'remove dir')
.option('-r, --recursive [name]', 'Remove recursively')
.action(function (dir, cmd) {
console.log(dir, cmd.recursive)
console.log('remove ' + dir + (cmd.recursive ? ' recursively' : ''))
})
console.log("cli")
program.parse(process.argv)
$ node ./bin/cli.js rm -r testCode testDir
和 arguments
结合使用
program
.version('0.0.1')
.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");
alias
格式:alias(‘t’)
描述:定义 command
的简写命令
program
.command('exec <cmd>')
.alias('ex')
parse
格式:program.parse(process.argv)
描述:在程序最后调用,解析 process.argv
命令行代码
outputHelp
格式:.outputHelp(cb)
描述:不退出输出帮助信息。 可选的回调可在显示帮助文本后处理。
var program = require('commander');
var colors = require('colors');
program
.version('0.0.1')
.command('getstream [url]', 'get stream URL')
.parse(process.argv);
if (!process.argv.slice(2).length) {
program.outputHelp(make_red);
}
function make_red(txt) {
return colors.red(txt); // 在控制台上显示红色的帮助文本
}
help
描述:输出帮助信息并立即退出。 可选的回调可在显示帮助文本后处理。你可以通过监听 --help
来控制 -h
, --help
显示任何信息。一旦调用完成, Commander
将自动退出,你的程序的其余部分不会展示。例如文件中的 console 等,如果要展示可以使用上面的 outputHelp
program
.command('exec <cmd>')
.alias('ex')
.description('execute the given remote cmd')
.option("-e, --exec_mode <mode>", "Which exec mode to use")
.action(function(cmd, options){
console.log('exec "%s" using %s mode', cmd, options.exec_mode);
}).on('--help', function() {
console.log('');
console.log('Examples:');
console.log('');
console.log(' $ deploy exec sequential');
console.log(' $ deploy exec async');
});