Commander基本使用
随着NodeJs
的不断发展,对于前端来说要做的东西也就更多,Vue
脚手架React
脚手架等等等一系列的东西都脱颖而出,进入到人们的视野当中,对于这些脚手架工具来讲也只是停留在应用阶段,从来没有想过脚手架是如何实现的?vue init webpack 项目名称
是如何通过这样的命令创建了一个项目,其最重要的模块就是今天要说的Commander
。
Commander
模块又国外TJ
大神所编写
项目地址:Commander
Commander基本用法
Commander
文档写的很详细,跟着文章详细的学习一下,Commander
是一个Nodejs
模块,需要在Node
环境中运行,在使用前确认一下Node
环境是否已安装。
安装依赖
npm install commander --save
Options 解析
在Commander
模块下存在option
方法用来定义commander
的选项options
,用来作为选项的文档。
var program = require('commander');
program
.option('-g, --git [type]', 'Add [marble]', 'Angie')
.parse(process.argv);
console.log("process.argv",process.argv)
console.log("program.args",program.args)
console.log('you ordered a pizza with:');
if (program.git) console.log(' - git');
console.log(' - %s git', program.git);
上面的示例将解析来自process.argv
的args
和options
,然后将剩下的参数(未定义的参数)赋值给commander
对象的args
属性(program.args
),program.args
是一个数组。
打印输出一下process.argv
和program.args
并查看了一下输出结果如下,使用如下命令运行一下文件:
node index -g type Aaron
process.argv ['F:\\node\\installation\\node.exe',
'C:\\Users\\wo_99\\Desktop\\cli-dome\\index',
'-g',
'type',
'Aaron' ]
program.args [ 'Aaron' ]
option
方法可以接收三个参数:
- 自定义标志
必须
:分为长短标识,中间用逗号、竖线或者空格分割;标志后面可跟必须参数或可选参数,前者用<>
包含,后者用[]
包含。 - 选项描述
省略不报错
:在使用 --help 命令时显示标志描述 - 默认值
可省略
:当没有传入参数时则会使用默认值
若我们执行node index -g
得到的结果则是Angie git
其第三个参数则作为了默认值填写在了对应的位置上。除了上面所说还可以使用如下命令:
// 执行 -g 参数 a
// 执行 -b 参数 s
node index -g a -b s
// 执行 -g和-b 传入a参数给-g
// -b 参数暂时不知道怎么传入
node index -gb a
版本选项
调用版本会默认将-V
和--version
选项添加到命令中。当存在这些选项中的任何一个时,该命令将打印版本号并退出。
var program = require('commander');
program
.version('0.0.1')
.parse(process.argv);
// 执行命令
// node index -V
// 输出结果
// 0.0.1
如果希望程序响应-v
选项而不是-V
选项,只需使用与option
方法相同的语法将自定义标志传递给version
方法,版本标志可以被命名为任何值,但是长选项是必需的。
var program = require('commander');
program
.version('0.0.1', '-e, --version');
command 添加命令名称
该方法允许使用命令行去执行一段命令,也就是一段:
var program = require('commander');
program
.version('0.0.1', '-V, --version')
.command('rm <dir>')
.action(function (dir, cmd) {
console.log('remove ' + dir + (cmd.recursive ? ' recursively' : ''))
});
program.parse(process.argv);
// 执行命令
// node index rm /aaa -r
// 输出结果
// remove /aaa recursively 即:代码中console内容
command
函数接收三个参数:
- 命令名称
必须
:命令后面可跟用<>
或[]
包含的参数;命令的最后一个参数可以是可变的,像实例中那样在数组后面加入...
标志;在命令后面传入的参数会被传入到action
的回调函数以及program.args
数组中。 - 命令描述
可省略
:如果存在,且没有显示调用action(fn)
,就会启动子命令程序,否则会报错 - 配置选项
可省略
:可配置noHelp、isDefault
等
使执行命令时,将验证该命令的options
,任何未知的option
都将报错。但是,如果基于action
的命令如果没有定义action
,则不验证options
。
var program = require('commander');
program
.version('0.0.1', '-V, --version')
.command('rm <dir>')
.option('-r, --recursive', 'Remove recursively')
.action(function (dir, cmd) {
console.log('remove ' + dir + (cmd.recursive ? ' recursively' : ''))
});
program.parse(process.argv);
console.log(program.args)
// 执行命令
// node index rm /aaa -r /ddd
// 输出结果
// remove /ddd recursively
// [ '/aaa' ]
helpOption 帮助
提供帮助信息
var program = require('commander');
program
.version('0.1.0')
.helpOption('-h,--HELP')
.option('-f, --foo', 'enable some foo')
.option('-b, --bar', 'enable some bar')
.option('-B, --baz', 'enable some baz');
program.parse(process.argv);
// 执行命令
// node index -h 或 node index --HELP
/* 输出结果
* Options:
* -V, --version output the version number
* -f, --foo enable some foo
* -b, --bar enable some bar
* -B, --baz enable some baz
* -h,--HELP output usage information
*/
输出帮助信息并立即退出。可选的回调cb允许在显示帮助文本之前对其进行后处理。helpOption
也提供长名
,-h,--HELP
前面为短名
后面为长名
调用时使用两这都是可以的。与version
的使用是类似的。
description 命令描述
用来描述命令,也就是命令的说明,上面说过command
第二个参数也同样是命令的描述,当与description
同时存在的话,则会优先于第二个参数的描述,description
则会作为全局描述在最顶部显示。该描述只用在使用-HELP
的时候才能看见。
var program = require('commander');
program
.version('0.0.1', '-V, --version')
.command('rm <dir>',"arg is description")
.description("this is description")
.option('-r, --recursive', 'Remove recursively')
.action(function (dir, cmd) {
console.log('remove ' + dir + (cmd.recursive ? ' recursively' : ''))
});
program.parse(process.argv);
// 执行命令
// node index -h
// 输出结果
/*
this is description
Options:
-V, --version output the version number
-r, --recursive Remove recursively
-h, --help output usage information
Commands:
rm <dir> arg is description
help [cmd] display help for [cmd]
*/
通过上面的输出结果可以看的出,rm
命令最后的描述是arg is description
,若删除第二个参数则会输出this is description
。
自定义事件侦听器
用于捕获option
与command
,当其被使用贼会被触发函数。
var program = require('commander');
program
.version('0.0.1', '-V, --version')
.command('rm <dir>',"arg is description")
.option('-r, --recursive', 'Remove recursively')
.option('-g, --git [type]', 'Add [marble]', 'Angie')
.option('-a, --am',"ampm")
.action(() => {
console.log(123)
});
program.on('option:am', function () {
console.log("on:am")
});
program.on('option:recursive', function () {
console.log("option:recursive")
});
program.on('command:rm', function () {
console.log("command:rm")
});
program.on('option:git', function () {
console.log("option:git")
});
program.on('command:*', function () {
console.log(987)
console.error('Invalid command: %s\nSee --help for a list of available commands.', program.args.join(' '));
process.exit(1);
});
program.on('--help', function() {
console.log('****************');
console.log('Examples:');
console.log('****************');
console.log(' $ deploy exec sequential');
console.log(' $ deploy exec async');
});
program.parse(process.argv);
分别执行command
和option
,会依次触发对应的函数,但是command:*
具体是什么时候触发的?
command
和option
已经定义但是没有进行事件捕获时会触发- 规定参数或没有参数时,传入了参数也会触发该函数
- 没有该命令
以上情况就会触发command:*
对应的事件,option:
紧紧跟随的是option
的长名。才会捕获到该事件。
开发本地模块
创建项目文件如下:
├─bin
│ └─init-project.js
├─lib
│ └─install.js
└─templates
└─dome1
创建好项目目录以后,安装如下依赖包:
- chalk
- commander
- fs-extra
- path
- through2
- vinyl-fs
- which
命令:npm install --save-dev chalk commander fs-extra through2 vinyl-fs which path
首先在init-project.js
中第一行添加#! /usr/bin/env node
,这是用来指定脚本的执行程序,这里的Node
可以用!/usr/bin/node
,若用户将Node
安装在非默认路径下会找不到Node
。So~最好选择env
环境变量查找Node
安装目录。
init-project.js
#! /usr/bin/env node
// 引入依赖
var program = require('commander');
var vfs = require('vinyl-fs');
var through = require('through2');
const chalk = require('chalk');
const fs = require('fs-extra');
const path = require('path');
// 定义版本号以及命令选项
program
.version('1.0.0')
.option('-i --init [name]', 'init a project', 'myFirstProject')
program.parse(process.argv);
if (program.init) {
// 获取将要构建的项目根目录
var projectPath = path.resolve(program.init);
// 获取将要构建的的项目名称
var projectName = path.basename(projectPath);
console.log(`Start to init a project in ${chalk.green(projectPath)}`);
// 根据将要构建的项目名称创建文件夹
fs.ensureDirSync(projectName);
// 获取本地模块下的demo1目录
var cwd = path.join(__dirname, '../templates/demo1');
// 从demo1目录中读取除node_modules目录下的所有文件并筛选处理
vfs.src(['**/*', '!node_modules/**/*'], { cwd: cwd, dot: true }).
pipe(through.obj(function (file, enc, callback) {
if (!file.stat.isFile()) {
return callback();
}
this.push(file);
return callback();
}))
// 将从demo1目录下读取的文件流写入到之前创建的文件夹中
.pipe(vfs.dest(projectPath))
.on('end', function () {
console.log('Installing packages...')
// 将node工作目录更改成构建的项目根目录下
process.chdir(projectPath);
// 执行安装命令
require('../lib/install');
})
.resume();
}
install.js
// 引入依赖
var which = require('which');
const chalk = require('chalk');
var childProcess = require('child_process');
// 开启子进程来执行npm install命令
function runCmd(cmd, args, fn) {
args = args || [];
var runner = childProcess.spawn(cmd, args, {
stdio: 'inherit'
});
runner.on('close', function (code) {
if (fn) {
fn(code);
}
})
}
// 查找系统中用于安装依赖包的命令
function findNpm() {
var npms = ['tnpm', 'cnpm', 'npm'];
for (var i = 0; i < npms.length; i++) {
try {
// 查找环境变量下指定的可执行文件的第一个实例
which.sync(npms[i]);
console.log('use npm: ' + npms[i]);
return npms[i]
} catch (e) {
}
}
throw new Error(chalk.red('please install npm'));
}
var npm = findNpm();
runCmd(which.sync(npm), ['install'], function () {
console.log(npm + ' install end');
})
完成如上代码之后,更改package.json
添加属性如下:
{
"bin": {
"q-init": "./bin/init-project.js"
}
}
注:自定义指令后指定的文件,一定要添加.js
后缀文件名,否则会抛出错误。
接下来剩下的就是测试了,对于测试来说不需要把安装包推到npm
中,npm
为了方便,提供了npm link
命令,可以实现预发布
。在项目根目录中使用npm link
没有报错的话,就说明推送成功了。现在就可以在全局中使用q-init
了。
在全局中使用initP -h
命令,能够输出所编译的help
信息就说明可以初始化项目了。
Usage: init-project [options]
Options:
-V, --version output the version number
-i --init [name] init a project (default: "myFirstProject")
-h, --help output usage information
总结
commander
在Vue-cli、creat-app(react)
中都起到了很大的作用,这种创建脚手架的方式与vue-cli
的方式不同,vue-cli
则是使用git
远程拉取项目再完成初始化,这样一来要比这种更加的方便灵活,每次模板变更不需要再次上传包,只需要更改git
仓库就好了,方便快捷。
Commander基本使用的更多相关文章
- 如何修改Total Commander配件文件的位置
今天测试了一下Total Commander最新版的安装文件,测试完成后,并删除.结果导致原先一直在使用的绿色版的Total Comander配件文件变成了测试的配件文件,导致许多配置都丢失了,因此不 ...
- 【荐1】Total Commander 7.57 个人使用设置 及 常用快捷键 备忘
Total Commander 7.57a 下载地址:http://www.baidu.com/s?wd=total commander 7.57 破解版 软件整体预览图:(注意,下面的版本我用的是 ...
- 【荐2】Total Commander 7.57 配置选项 个性化设置备份,,,开启时如何自动最大化???(二)
最近安装了下新版的“Total Commander 7.56”,发现它的默认设置是如此的不好用,现把对其个性化设置备份如下(符合大部分用户的操作习惯): 默认打开Total Commander 7.5 ...
- Mac Pro 资源管理器 Double Commander“个性化设置” 备份
操作系统自带的资源管理器,总是有些别扭的地方,在 Windows 系统下,我一般用 Total Commander(破解版)来作为替代品.现在换为 Mac 系统,自带的 Finer 也不怎么好用,连最 ...
- Total Commander 8.52 Beta 1
Total Commander 8.52 Beta 1http://www.ghisler.com/852_b1.php 10.08.15 Release Total Commander 8.52 b ...
- TC(Total Commander)文件管理神器
TC文件管理神器 Total Commander是一个会显著提高文件操作效率的工具,而文件操作是应用计算机最基本的功夫,也是伴随一生的操作.因此花一点时间学习,而会受益一世. Total Comman ...
- Total Commander 常用快捷键(并附快捷键大全)
Total Commander 常用快捷键 喜欢用Total Commander的人,都会记住它的一些快捷键,这会给你的操作带来很大的方便,以下是经常会用到的快捷键,大家可以记住一些自己用得最多的操作 ...
- node生成自定义命令(yargs/commander)
第一部分可以生成一个自定义命令,例如常见的”express”,yargs和commander则可以在生成的自定义命令上做扩展,yargs将命令扩展成类似express --l xx的形式;而comma ...
- Ubuntu下类似于Total Commander的两个工具
Total Commander for linux Is there a Linux version? Unfortunately not. Because of problems with port ...
- total commander相关设置
一. 中文语言包 在官方网站上提供有简体中文语言包,下面的说明以此为准.下载的语言包放至Total Commander安装目录下的Language子目录中.从菜单“Configuration”→“Op ...
随机推荐
- Java事务以及嵌套事务
知识点:java事务属性 Propagation取值: REQUIRED(默认值):在有transaction状态下执行:如当前没有transaction,则创建新的transaction: SUPP ...
- 【maven】命令
一.maven打包命令 mvn打包,并指定 Profiles配置文件 和 模块名 mvn clean package {-P prod} -pl {groupId}:{artifactId} -am ...
- mysql 8.0.18 hash join测试(内外网首文)
CREATE TABLE COLUMNS_hj as select * from information_schema.`COLUMNS`; INSERT INTO COLUMNS_hj SELECT ...
- Spring @RequestMapping 参数说明
@RequestMapping 参数说明: value: 指定请求的实际地址, 比如 /action/info之类.method: 指定请求的method类型, GET.POST.PUT.DELE ...
- Celery 服务搭建
整个项目工程如下 __init__.py """ 注意点:python3.7 需要执行 pip install --upgrade https://github.com/ ...
- npm 更换阿里云镜像
来源:https://blog.csdn.net/a249040113/article/details/81567430 npm安装插件过程:从http://registry.npmjs.org下载对 ...
- 使用 Laravel-Swagger 编写接口文档(php)
使用 Laravel-Swagger 编写接口文档 Table of Contents Swagger 文档管理 官方网站:https://swagger.io/ 快速编写你的 RESTFUL API ...
- C++内存管理2-内存泄漏
1 C++中动态内存分配引发问题的解决方案 假设我们要开发一个String类,它可以方便地处理字符串数据.我们可以在类中声明一个数组,考虑到有时候字符串极长,我们可以把数组大小设为200,但一般的情况 ...
- 使用MAT 分析内存泄漏实战
在分析前可以阅读下这篇文章,很多内容就都知道了https://www.jianshu.com/p/738b4f3bc44b,下面我来分析上一篇文章内存泄漏的为问题 1.上一篇中已经生成了hprf的文件 ...
- win10专业版激活步骤
1.右键开始图标,选择[windows powershell(管理员)],或者命令提示符管理员: 2.打开命令窗口,复制这个命令slmgr /ipk W269N-WFGWX-YVC9B-4J6C9-T ...