前言:

  最近需要做一个内部的node cli来独立构建流程,对整个命令行工具实现流程有了大致了解,下面来解释一下如何实现一个cli,和如何使用 commander 库。
 

新手误区:

  在开始实现之前,我知道有 commander 这个node库,有很多cli使用了它,对它的大致了解就是它可以帮助开发者简化实现命令流程。  于是最初以为不利用库要去实现命令行会很麻烦,commander 帮我们解决了各种兼容问题等等。  后来发现并不是的,没有commander 我们也可以不用化多大力气实现命令行,commander 仅仅是一个本身也不太复杂的封装(源码也只有1200行)。  我们的第一步还是应该先搞清楚,通过npm如何实现命令行。
 

一个简单的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 clinpm 就会在项目的 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也并没有用类似 commandernode 库,如果我们的 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 里查找是否有 nameh5commander 子实例,如果查找到,启动一个子进程按照命名规则执行 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)的更多相关文章

  1. 使用.Net Core编写命令行工具(CLI)

    命令行工具(CLI) 命令行工具(CLI)是在图形用户界面得到普及之前使用最为广泛的用户界面,它通常不支持鼠标,用户通过键盘输入指令,计算机接收到指令后,予以执行. 通常认为,命令行工具(CLI)没有 ...

  2. 如何用Node编写命令行工具

    0. 命令行工具 当全局安装模块之后,我们可以在控制台下执行指定的命令来运行操作,如果npm一样.我把这样的模块称之为命令行工具模块(如理解有偏颇,欢迎指正) 1.用Node编写命令行工具 在Node ...

  3. 一个小时学会用 Go 编写命令行工具

    前言 最近因为项目需要写了一段时间的 Go ,相对于 Java 来说语法简单同时又有着一些 Python 之类的语法糖,让人大呼"真香". 但现阶段相对来说还是 Python 写的 ...

  4. 如何用node编写命令行工具,附上一个ginit示例,并推荐好用的命令行工具

    原文 手把手教你写一个 Node.js CLI 强大的 Node.js 除了能写传统的 Web 应用,其实还有更广泛的用途.微服务.REST API.各种工具……甚至还能开发物联网和桌面应用.Java ...

  5. golang开发:类库篇(三)命令行工具cli的使用

    为什么要使用命令行 觉得这个问题不应该列出来,又觉得如果初次进行WEB开发的话,可能会觉得所有的东西都可以使用API去做,会觉得命令行没有必要. 其实,一个生产的项目命令行是绕不过去的.比如运营需要导 ...

  6. Flask内置命令行工具—CLI

    应用发现 flask命令在Flask库安装后可使用,使用前需要正确配置FLASK_APP环境变量以告知用户程序所在位置.不同平台设置方式有所不同. Unix Bash (Linux, Mac, etc ...

  7. nodejs 编写(添加时间戳)命令行工具 timestamp

    Nodejs除了编写服务器端程序还可以编写命令行工具,如gulp.js就是Nodejs编写的. 接下来我们来实现一个添加时间戳的命令: $ timestamp action https://www.n ...

  8. node命令行工具之实现项目工程自动初始化的标准流程

    一.目的 传统的前端项目初始流程一般是这样: 可以看出,传统的初始化步骤,花费的时间并不少.而且,人工操作的情况下,总有改漏的情况出现.这个缺点有时很致命. 甚至有马大哈,没有更新项目仓库地址,导致提 ...

  9. Node.js 命令行工具的编写

    日常开发中,编写 Node.js 命令行工具来完成一些小任务是很常见的操作.其编写也不难,和日常编写 Node.js 代码并无二致. package.json 中的 bin 字段 一个 npm 模块, ...

随机推荐

  1. 关于opencv的cv2.WINDOW_一类

    用法:cv2.namedWindow('窗口标题',默认参数) 默认参数:cv2.WINDOW_AUTOSIZE+cv2.WINDOW_KEEPRATIO+cv2.WINDOW_GUI_EXPANDE ...

  2. Zabbix通过Orabbix监控Oracle数据库

    一.背景 公司业务使用的是一直Oracle数据库,因为多次出现表空间满的时候不能及时发现,每次都是业务组的人员通知处理,这样下来DBA这边就比较被动,所以老大要求监控表空间剩余大小并且当剩余过小时能够 ...

  3. Linux基本命令总结(九)

    接上篇: 46,scp是secure copy的简写,用于在Linux下进行远程拷贝文件的命令,和它类似的命令有cp,不过cp只是在本机进行拷贝不能跨服务器,而且scp传输是加密的.可能会稍微影响一下 ...

  4. Springboot 6.Springboot 返回cookies信息的验证和post接口开发及常见错误解决

    在介绍之前先将一个小插件:lombok  ,在prefrence里面点击plugins,然后搜索lombok,进行install就可以了 首先将pom文件里面的lombok引进来 <depend ...

  5. 映像文件工具srec

    目录 映像文件工具srec 介绍与帮助 常用例子 常用选项 一个实际的例子 hex转bin 数据填充 文件合并 文件分割 加入CRC 查看信息 使用命令集合的文本 详细文件格式的描述 附录:MDK的例 ...

  6. JAVA IO练习

     停车场有进场和出场的功能1. 进场时:采用键盘录入的方式,录入汽车的品牌.颜色.车牌号. 把品牌.颜色.车牌号,以及进场时间写入car.txt文件中. 2. 出场时:键盘录入车牌号,去文件中查找该车 ...

  7. SpringBoot系列: 设计Restful风格的API

    RESTful 架构REST 并非一种技术或规范, 而是一种架构风格, 如果一个架构符合Rest的约束条件和原则, 就可以称作是 RESTful 架构. REST全称是Representational ...

  8. burp suite 基础入门超详细教程

    介绍: 都是我个人了解到的信息,,分享给大家 欢迎指正 burp suite 被誉为web安全工具中的瑞士军刀. 大家知道,瑞士军刀,都是体积小,功能强悍,.西方军队的标配.说这么多,只是想强调这款工 ...

  9. 第30月第6天 git log

    1. git log git log 96a6f18b1e0a1b7301cb4f350537d947afeb22bc -p -1 我们常用 -p 选项展开显示每次提交的内容差异,用 -2 则仅显示最 ...

  10. 基于STM32F1的语音合成芯片SYN6288驱动

    目录 说明 SYN6288.h SYN6288.c 说明 基于USART2制作,封装了各种通信协议 SYN6288.h #ifndef _SYN6288_H_ #define _SYN6288_H_ ...