日常使用Node时,避免不了编写几个命令行工具。作为命令行工具,最直接的就是针对输入的各种参数、选项等,执行相应的命令。使用原生的progress.argv虽然可以进行参数判断,但使用起来十分不方便,为此研究了下Node第三方命令行工具 yargs 和 commander
Yargs 首先来看一个简单的例子
1 2 3 4 5 6 7 8 9 10 11 12 13 14 λ index -h Usage: index.js <command> -a [num] -b [num] Commands: add same as a + b plus same as a - b Options: -a, -A load a parameter [number] [required] -b, -B load b parameter [number] [required] -h, --help Show help [boolean] Examples: index.js add -a 10 -b 3 //compute 10 add 3
这段帮助信息是用 yargs 编写的,实现起来很简单,来看代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 #!/usr/bin/env node var yargs = require ('yargs' );ARGV = yargs.usage('Usage: $0 <command> -a [num] -b [num]' ) .command('add' , 'same as a + b' ) .command('plus' , 'same as a - b' ) .example('$0 add -a 10 -b 3' , '//compute 10 add 3' ) .alias('a' , 'A' ) .alias('b' , 'B' ) .alias('h' , 'help' ) .number('a' ) .number('b' ) .describe('a' , 'load a parameters' ) .describe('b' , 'load b parameters' ) .demand(['a' ,'b' ]) .help('h' ) .argv if (ARGV.h || ARGV.help){ print(ARGV.help()); process.exit(0 ); }
上述代码可以分为几个阶段
usage: 命令行工具的使用方法
command: 如果需要输入命令,则用 command('命令','描述') 的方式标注
example: 给出使用的例子,用 example('命令','描述') 的方式标注
alias: 对输入参数别名化,比如 -a 和 -A 是等效的
number(string,boolean,array…): 对输入的参数进行类型转换,比如.array(a), -a 10 4 3 5,那么 ARGV.a 是 [10,4,3,5]
describe: 对输入参数进行描述,用 describe('参数','描述') 的方式标注
require:标注哪些参数是必备的,比如 a 和 b 的后面加入了 [require] 的描述
help/epilog: 辅助的帮助/版权信息
就这样,一个简单的命令行信息交互帮助信息就生成了,后面可以用 ARGV.xxx 获得输入的参数,做后续程序的逻辑判断。
进阶用法
ARGV._ : 获得未指定的输入参数,比如 index -a 10 -b 3 5 “no” “13”,则 ARGV._ 获得 [‘5’,’no’,’13’]
.check(cb):检查输入参数合法性,如果 cb 返回 false,则输出帮助信息并退出
.fail(cb):当工具运行出错时,输出错误信息
更多用法请参考 yargs ,一般情况下,用 yargs 快速搭建一个命令行的使用帮助信息就足够了,不建议把判断的复杂逻辑也集成到 yargs 中
Commander 还是之前的例子,用 commander 实现的运行结果如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 λ commander --help Usage: commander <command> -a [num] -b [num] Commands: add same as a + b plus same as a - b Options: -h, --help output usage information -a, -A [num] load a parameter -b, -B [num] load b parameter
来看代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 #!/usr/bin/env node var program = require ('commander' );program .usage('<command> -a [num] -b [num]' ) .option('-a, -A [num]' , 'load a parameter' ) .option('-b, -B [num]' , 'load b parameter' ); program .command('add' ) .description('same as a + b' ); program .command('plus' ) .description('same as a - b' ); program.parse(process.argv);
通过对比,个人比较喜欢 commander 的代码风格,每个 command 单独处理,可以各种自定义,比如针对某个命令输出 help 信息,而 yargs 的那种分块编码,也值得借鉴,从代码量而言,yargs 和 commander 指定复杂的命令时,前者的代码量会比较少,同样,前者在功能上比后者更加丰富,适合复杂通用的命令行工具,更多用法请参考 commander
后记:Windows 上如何调用nodejs命令行工具 在本机上找到任意一个npm的安装包,都能发现有 xxx.cmd 这样的文件,打开如下
1 2 3 4 5 6 7 @IF EXIST "%~dp0\node.exe" ( "%~dp0\node.exe" "%~dp0\xxx.js" %* ) ELSE ( @SETLOCAL @SET PATHEXT=%PATHEXT:;.JS;=;% node "%~dp0\xxx.js" %* )
不难理解,在window上要执行nodejs,必须要用 node xxx.js 的方式,而这段代码就是省略了前面的node,直接用 xxx 即可,比如之前的例子中,#!/usr/bin/env node用来在linux上指定脚本运行环境为node,所以可以直接用 ./script.js 加参数运行,在window上,将上面的文件中 xxx 替换成script,即可用 script 加参数运行了
如果以后涉及到用Node写两个平台通用的工具,请记住编写这个文件