commanderJs编写命令行工具(cli)
前言:
新手误区:
一个简单的cli:
bin:
package.json 中有一个 bin 字段,指定各个内部命令对应的可执行文件的位置。 在包安装时,如果是全局安装,npm 将会把 package.json 里定义的 bin 文件软连接到全局 node_modules/bin,如果是非全局安装,会软链接到项目文件夹./node_modules/.bin/。 根据下面代码的配置,当我们全局安装此包后,在任意位置运行 cli-test,都会执行全局 node_modules 中的 cli-test 文件。
/*cli-test 的 package.json*/
"bin": {
"cli-test": "./bin/cli-test"
}
如果我们把cli安装在项目A node_modules中,通过设置项目中 package.json 的 scripts,运行 npm run cli,npm 就会在项目的 node_modules/.bin 寻找并运行 cli-test 文件。
/*项目A package.json*/
"scripts": {
"cli": "cli-test"
}
cli文件:
下面是 cli-test 文件,第一行必写,是告诉Unix和Linux系统这个文件中的代码用node可执行程序去运行它。 后面就做我们要做的事情就行了 。
#!/usr/bin/env node //do something
好了,到这里我们的cli就完成了。 其实有很多三方cli也并没有用类似 commander 的 node 库,如果我们的 cli 足够简单,以上这样就可以了。 下面接着讲 commander。
commander:
现在我们先写一个简单的文件来理解(也推荐先自行预览一下 commander 官方文档),下面是 bin 文件夹的 cli-test,代码如下:
#!/usr/bin/env node
const program =require('commander');
program
.usage('[option]', '--type required')
.option('--type [typeName]', 'type: dev && build')
.parse(process.argv);
const {type} = program;
if(type == 'dev'){
console.log('do something', type)
}else if(type == 'build'){
console.log('do something', type)
}else{
console.log('params error');
program.help();
}
解释一下上面的代码,从查看源码里发现 require('commander') 会 new一个commander 内部的单例对象并返回,program 已经是一个实例,
。 .usage 仅仅描述了参数规则,会在 --help 中打印出来。.option 定义了一个参数名和描述, parse 会解析命令之中的参数,根据上面定义好的规则执行相关命令。 比如上面的代码定义了 option 类型的参数 --type,执行 .parse 的时候,parse 根据 process.argv 之中的参数,获取到 --type,并把参数命和参数值存储在内部 commander 实例的属性之中,因此后面的代码就能从 program 之中取到 type,如果 type 不存在或者不是我们约定的值,最后我们打印参数错误,并执行help方法打印了 --help。 如下截图,我们 node 执行 cli-test,因为没有约定参数,所以执行了 else 的程序。(因为这里是本地的demo程序,所以直接使用node命令)

接着,我们执行正确的命令参数,如下

这样一个简单的demo就实现了,看起来也挺简单的,commander 封装了一些也不算很复杂的功能。
再来一个例子:
新建了两个文件,要以 bin 命令的执行文件命后面加上 -name,作为子命令文件

cli-test:
#!/usr/bin/env node
const program =require('commander');
program
.usage('<command> [option]', 'option --type required')
.command('h5', 'to h5')
.command('rn', 'to rn')
.parse(process.argv);
cli-test-h5:
#!/usr/bin/env node
const program =require('commander');
program
.option('--type [typeName]', 'type: dev && build')
.parse(process.argv);
const {type} = program;
if(type == 'dev'){
console.log('do something h5', type)
}else if(type == 'build'){
console.log('do something h5', type)
}else{
console.log('params error');
program.help();
}
cli-test-rn:
#!/usr/bin/env node
const program =require('commander');
program
.option('--type [typeName]', 'type: dev && build')
.parse(process.argv);
const {type} = program;
if(type == 'dev'){
console.log('do something rn', type)
}else if(type == 'build'){
console.log('do something rn', type)
}else{
console.log('params error');
program.help();
}
先直接运行3个命令运行程序,看下结果,而后分别解释一下:

node ./bin/cli-test:
定义了.command子命令却没有相应执行参数,commander对象会直接打印-help,并process.exit退出进程。
node ./bin/cli-test h5 --type dev:
cli-test 通过 command 方法约定子命令名称和描述,如 h5,当执行 node cli-test h5 --type dev的时候,cli-test 执行到 .command('h5', 'to h5') ,会在当前 commander 实例内部,new 一个 name 为 h5 的子 commander,存储在当前父实例的 commands 数组中,当 .parse(process.argv) 执行,获取到参数中 h5 后,在 commands 里查找是否有 name 为 h5 的 commander 子实例,如果查找到,启动一个子进程按照命名规则执行 cli-test-h5 文件并带入后面的 option 参数。 这样 commander 就帮助我们实现了多文件命令划分,我们可以把不同类型的执行代码放在不同的文件中。
node ./bin/cli-test rn --type build:
同上
小结
bin 文件夹下的这3个 node 文件他们都是 commander 实例,commander 库只是一个简单的封装,帮助定义 多文件命令、执行参数 、简易文档,参数验证等。 以上就是 commander 的大致使用和我对其的理解。 源码不多,建议可以深入学习一下。
最后
到最后大家结合实现以上所说的 cli 和 commander,一个 commander 实现的命令行工具就能完成了,是不是很简单!?
注意
如果执行命令发现报错为 error: xx(1) not executable. try chmod or run with root,要注意下创建的文件类型。
commanderJs编写命令行工具(cli)的更多相关文章
- 使用.Net Core编写命令行工具(CLI)
命令行工具(CLI) 命令行工具(CLI)是在图形用户界面得到普及之前使用最为广泛的用户界面,它通常不支持鼠标,用户通过键盘输入指令,计算机接收到指令后,予以执行. 通常认为,命令行工具(CLI)没有 ...
- 如何用Node编写命令行工具
0. 命令行工具 当全局安装模块之后,我们可以在控制台下执行指定的命令来运行操作,如果npm一样.我把这样的模块称之为命令行工具模块(如理解有偏颇,欢迎指正) 1.用Node编写命令行工具 在Node ...
- 一个小时学会用 Go 编写命令行工具
前言 最近因为项目需要写了一段时间的 Go ,相对于 Java 来说语法简单同时又有着一些 Python 之类的语法糖,让人大呼"真香". 但现阶段相对来说还是 Python 写的 ...
- 如何用node编写命令行工具,附上一个ginit示例,并推荐好用的命令行工具
原文 手把手教你写一个 Node.js CLI 强大的 Node.js 除了能写传统的 Web 应用,其实还有更广泛的用途.微服务.REST API.各种工具……甚至还能开发物联网和桌面应用.Java ...
- golang开发:类库篇(三)命令行工具cli的使用
为什么要使用命令行 觉得这个问题不应该列出来,又觉得如果初次进行WEB开发的话,可能会觉得所有的东西都可以使用API去做,会觉得命令行没有必要. 其实,一个生产的项目命令行是绕不过去的.比如运营需要导 ...
- Flask内置命令行工具—CLI
应用发现 flask命令在Flask库安装后可使用,使用前需要正确配置FLASK_APP环境变量以告知用户程序所在位置.不同平台设置方式有所不同. Unix Bash (Linux, Mac, etc ...
- nodejs 编写(添加时间戳)命令行工具 timestamp
Nodejs除了编写服务器端程序还可以编写命令行工具,如gulp.js就是Nodejs编写的. 接下来我们来实现一个添加时间戳的命令: $ timestamp action https://www.n ...
- node命令行工具之实现项目工程自动初始化的标准流程
一.目的 传统的前端项目初始流程一般是这样: 可以看出,传统的初始化步骤,花费的时间并不少.而且,人工操作的情况下,总有改漏的情况出现.这个缺点有时很致命. 甚至有马大哈,没有更新项目仓库地址,导致提 ...
- Node.js 命令行工具的编写
日常开发中,编写 Node.js 命令行工具来完成一些小任务是很常见的操作.其编写也不难,和日常编写 Node.js 代码并无二致. package.json 中的 bin 字段 一个 npm 模块, ...
随机推荐
- 关于opencv的cv2.WINDOW_一类
用法:cv2.namedWindow('窗口标题',默认参数) 默认参数:cv2.WINDOW_AUTOSIZE+cv2.WINDOW_KEEPRATIO+cv2.WINDOW_GUI_EXPANDE ...
- Zabbix通过Orabbix监控Oracle数据库
一.背景 公司业务使用的是一直Oracle数据库,因为多次出现表空间满的时候不能及时发现,每次都是业务组的人员通知处理,这样下来DBA这边就比较被动,所以老大要求监控表空间剩余大小并且当剩余过小时能够 ...
- Linux基本命令总结(九)
接上篇: 46,scp是secure copy的简写,用于在Linux下进行远程拷贝文件的命令,和它类似的命令有cp,不过cp只是在本机进行拷贝不能跨服务器,而且scp传输是加密的.可能会稍微影响一下 ...
- Springboot 6.Springboot 返回cookies信息的验证和post接口开发及常见错误解决
在介绍之前先将一个小插件:lombok ,在prefrence里面点击plugins,然后搜索lombok,进行install就可以了 首先将pom文件里面的lombok引进来 <depend ...
- 映像文件工具srec
目录 映像文件工具srec 介绍与帮助 常用例子 常用选项 一个实际的例子 hex转bin 数据填充 文件合并 文件分割 加入CRC 查看信息 使用命令集合的文本 详细文件格式的描述 附录:MDK的例 ...
- JAVA IO练习
停车场有进场和出场的功能1. 进场时:采用键盘录入的方式,录入汽车的品牌.颜色.车牌号. 把品牌.颜色.车牌号,以及进场时间写入car.txt文件中. 2. 出场时:键盘录入车牌号,去文件中查找该车 ...
- SpringBoot系列: 设计Restful风格的API
RESTful 架构REST 并非一种技术或规范, 而是一种架构风格, 如果一个架构符合Rest的约束条件和原则, 就可以称作是 RESTful 架构. REST全称是Representational ...
- burp suite 基础入门超详细教程
介绍: 都是我个人了解到的信息,,分享给大家 欢迎指正 burp suite 被誉为web安全工具中的瑞士军刀. 大家知道,瑞士军刀,都是体积小,功能强悍,.西方军队的标配.说这么多,只是想强调这款工 ...
- 第30月第6天 git log
1. git log git log 96a6f18b1e0a1b7301cb4f350537d947afeb22bc -p -1 我们常用 -p 选项展开显示每次提交的内容差异,用 -2 则仅显示最 ...
- 基于STM32F1的语音合成芯片SYN6288驱动
目录 说明 SYN6288.h SYN6288.c 说明 基于USART2制作,封装了各种通信协议 SYN6288.h #ifndef _SYN6288_H_ #define _SYN6288_H_ ...