命令行构造工具之 Yargs 详细介绍
目录
- 简介
- 光速开始
- 总结
简介
话说 yargs 是什么呢?简单来说,就是用来解析 cli 参数的。话不多说,我们来简单了解一下。
光速开始
.argv 一切的开始,简单的不要不要的
使用这个最简单的方式就是直接调用 .argv 这个 getter,他会自动对 process.argv 进行解析。并返回解析后的对象。
1 | // argv.js |
1 | # node argv.js -v --version --name whos |
什么缩写,什么参数,统统搞定。是不是 so easy。
在默认情况下,所有的参数只有三种值,Boolean、String、Array<Boolean|String。
而且 $0 代表当前脚本的名称,这个就不多讲了
参数后面可以使用空格或者 = 。例如 -d=ok —name=bill
普通参数
如果参数没有 - 开头,那么将它放入 _ ,简称为普通参数
1 | # node argv.js a b c |
简写参数
如果参数只有一个 - 开头,那么后面的参数为缩写参数,缩写参数的值默认设置成 true。
1 | # node argv.js -a -b -c |
同时,yargs 支持将缩写参数合并在一起书写。
1 | # node argv.js -abc |
效果和上面是一样的。
如果缩写参数后面跟着普通参数,那么缩写参数的值就会自动设置成普通参数的值而不再是 true。
1 | # node argv.js -a haha -b lala -c hehe |
那么有人问了,如果我这样写会怎么样? -abc hahaha,let’s try.
1 | # node argv.js -abc hahaha |
结果显示,其实就和
1 | # node argv.js -a -b -c hahaha |
是一样的,可以见得,代码中其实就是将 -abc 拆成了 -a -b -c 进行解析的。
全写参数
除去上面两种参数,就剩下全写参数(不要吐槽为啥叫全写参数,因为实在是不知道该叫什么名字)
全写参数和缩写参数差不多,只不过他不能合并成一个书写,其他都是一样的
1 | # node argv.js --version --laugh haha |
结果合并
作为一个好 Module ,怎么会没有考虑到下面这种奇葩情况呢?
1 | # node argv.js -a -a -a -a -a -a -a |
大家猜猜会是什么结果 :) 此处略过 10000 秒。
1 | { _: [], |
没错,yargs 将每一个参数单独处理,然后最后合并成了一个数组,是不是很有意思,也就是说你可以写出下面的东东。
1 | # node argv.js --fuck whose --fuck your --fuck daddy --fuck |
最简单的模式,也是最有趣的模式,值得去玩。
我就要你在我的身边,.demandOption(key, msg)**
如果你需要某个参数一定存在,这怎么办呢?难道要自己手动 if 一下,那真的好蠢啊。
.demandOption 就是这么来了
1 | // demand.js |
baby 在,世界一切太平,不管他是怎么在我的身边的。
1 | # node demand.js --baby |
baby 不在,世界爆炸(exit code != 0)
1 | # node demand.js |
.demandOption(key, msg) 的 key 支持数组和字符串,分别表示单个和多个 required 的参数。而第二个参数值在没有满足条件的时候显示的文字。
啥?你嫌我太长?还是太短:).alias
俗话说的好,参数太长怎么办,变短一点喽
其实是我自己说的,可以给一个命令取一个别名,不管是变长还是变短,都很简单。
1 | // alias.js |
1 | # node alias.js -l --long --lo -s --short |
可以看到 l lo long 是一样的,s short 是一样的,可长可短,自由随意。
你要我怎样我就怎样,.boolean .array .number .count .choices
有的时候,需要某些参数是固定的格式,而不是其他的方式,那么就需要这些方法来描述一个参数的类型。这些参数对于 alias 之后的参数同样也是可以的。
.array(key)
顾名思义,直接将参数的类型设置为数组,他会将后面所有的非普通参数作为当前参数的值。
1 | // array.js |
1 | # node array.js --girls Abby Aimee --stop --girls Alisa Angelia Amanda |
.boolean(key)
将参数类型设置为 Boolean 类型。如果后面的类型不是 Boolean 类型(true、false),那么将不会设置为当前参数的值,并且当有多个的时候,不会合并成数组。
1 | // boolean.js |
1 | # node boolean.js I --love you and --love again |
.number(key)
将参数类型设置为 Number 类型。基本规则如下:
如果没有填写值,那么默认是
undefined如果设置的值不合法,那么是
NaN否则是格式化为数字,使用
Number构造方法
1 | // number.js |
1 | # node number.js --bust --waist 24 --hips zz |
.count(key)
统计一下这个参数被使用了多少次,使用 .count 之后,参数默认就变成了 Boolean 类型,但是只统计他出现的次数。经常用来作为设置 debug 的输出级别。
1 | // count.js |
1 | # node count.js -v -vv --people --people false |
.choices(key, list)
设置某个参数只能为某些值,可以和number boolean count 组合。
其本质是 indexOf 操作,也就是 === 做比较操作,所以这也就是为啥 array 不能和他匹配的原因。
1 | // choices |
1 | # node choices.js --look "oh, god" |
听说你和别人有千丝万缕的关系:( .conflicts .implies
简单一说:
.implies(我, 她)有我先有她,有她不一定有我.confilcts(我, 他)有我没他,有他没我
如果两个都存在在一个参数上面的时候,implies 优先级会更高。
1 | // imcon.js |
1 | # node imcon.js --me --him --her |
大家在一起吧 :) .option .options
其实就是将上面的的所有的命令合并成一个 object,里面的 key 就是对应的函数名,而值就是参数。只不过 .options 是很多 .option 的集合。
有用但是很简单其余参数
.default.defaults设置默认参数值.describe对参数的描述.usage设置命令的提示的使用方法.help设置帮助的指令,添加-help,但是没有h,需要手动添加,可以选择是否添加help子命令.group分组,比如可以设置启动参数为一组,停止参数为一组,只是看起来比较舒服一些,并不影响什么内容。.normalize对参数的值用path.normalize.version添加版本显示参数-version,不过不添加缩写参数.wrap设置信息输出的最大的列宽度,比如说-help显示帮助参数。.wrap(null)取消列宽限制,.wrap(require('yargs').terminalWidth())设置为当前宽度。默认是Math.min(80, windowWidth
小弟来了 (-_-) **.command**
最简单的就是想实现类似 git 的那样的带有子命令的命令行操作,那么就需要这个东西。
他有如下的参数:
.command(cmd, desc, [builder], [handler]).command(cmd, desc, [module]).command(module)builder是构造器,可以是Object|yargs => {},如果是对象,那么和.options是一样的。如果是函数,参数是yargs可以通过上面的函数添加参数。handler是处理器,当解析完成后,传入解析的结果,此时可以对结果进行处理。module最简单了,就是有command命令名aliases别名describe描述builder构造器handler处理器
当匹配到一个命令的时候, yargs 会做如下处理:
把当前命令输入到当前作用域中
清空所有的非全局的配置
如果传入了
builder,就通过其设置当前命令解析和验证参数
如何一切正常,那么运行
handle,如果传入了的话从当前作用域中弹出
这个位置是你的,别人抢不走 [arg1] <arg2>
有的时候希望命令必须要接受一个参数,或者接受一个可选参数,那么可以对命令使用 <> 和 [] 设置他的位置。<> 表示这个命令必须要有,[] 表示这个参数可选。
有如下规则:
通过
|设置别名,例如[name|username],在最后的解析中,name和username是一样的。最后一个可选参数支持添加
…变成可变参数,例如downloadto <from> [to…]那么to是一个数组,并且必须要是命令中的最后一个可选参数才能变成可变参数。
1 | // like.js |
1 | # node like.js like you |
默认命令
有的时候当没有任何命令匹配到的时候,希望有一个默认匹配的,那么可以用 * 代替普通命令的位置。
1 | // defaultCommand.js |
1 | # node defaultCommand.js --name |
方便一点 .commandDir
表示直接从文件夹中动态加载命令。详情请参考文档
从别的地方来 .config .env .coerce
写到这里,作者累了,所以:
.config动态的从命令行中接受一个json文件路径,并自动加载。 doc.env设置环境变量的前缀,自动将这些前缀的环境变量去掉前缀,使用小驼峰和下划线方式加载。doc.coerce获取到变量值之后转化成别的值。doc
还有很多细节的,不过我觉得文档挺详细的,我就不多说了。
总结
感觉还是不错的,接口很简单,也通俗易懂。相比 commander 是两种不同的风格。commander 上手简单,但是前置知识有一些,而 yargs 相比前置知识的要求比较少,而且更加灵活。