Node命令行工具-Yargs和Commander

日常使用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写两个平台通用的工具,请记住编写这个文件

如需转载,请注明出处