通常在开发脚手架时,才会需要注册和配置命令,所以我们先来创建一个脚手架
创建脚手架 mycli
npm init -y
#!/usr/bin/env node
console.log("成功运行 mycli");
重要提醒:脚手架的核心原理
此处必须在第一行添加 #!/usr/bin/env node ,因为它会去找操作系统的环境变量 node 对应的 node.exe 来执行 index.js
mycli 到文件index.js 的映射 "bin": {
"mycli": "./index.js"
},
npm link
此时在系统安装的 node 源文件的 bin 文件夹中会生成命令 mycli 的软链接,当在命令行执行 mycli 时,node 便会从该软链接中找到并执行 index.js
myclimycli

脚手架创建成功!
安装 commander
cnpm install commander
无 cnpm 的朋友先执行 npm i cnpm
导入并实例化 commander
import { Command } from "commander";
// 实例化一个 commander
const program = new Command();
为了支持 import,记得在 package.json 中添加
"type": "module",
注册命令
// 给实例 program 注册并配置命令
program
.command("init") // 注册命令,参数 init 为自定义的命令名称
.description("初始化") // 描述命令的描述,在帮助信息中会展示
// 命令的具体行为(执行的代码)
.action((params, options, cmd) => {
console.log("---- 开始对 mycli 进行初始化 ----");
// 自定义初始化需执行的代码,此范例为打印当前目录
console.log("当前目录为:" + process.cwd());
console.log("---- 完成了 mycli 的初始化 ----");
});
// 解析 commander
program.parse();
此时便可执行命令
mycli init

同时,还会自动注册 help 命令,执行 mycli help 、 mycli -h 或 mycli --help 都能看到脚手架 mycli 可执行的所有命令以及命令的描述。

给命令设置别名、添加参数、添加配置
program
.command("split") // 注册命令
.alias("sp") // 命令的别名
.description("将字符串分割成数组") // 对命令功能的描述
.option("-s, --separator " , "分割符", ",") // 命令的配置信息,最后的 ","为默认值
.argument("" , "被分割的字符串") // 命令的参数
.action((params, options, cmd) => {
// action中函数的第一个参数为命令的参数,此范例中params是一个字符串
console.log(params);
// action中函数的第二个参数为命令的配置信息
// 此范例中 options 是一个对象,有一个属性 separator, 属性值为分割符
console.log(options);
// action中函数的第三个参数为命令对象自己
// console.log(cmd);
// 命令的功能代码为分割字符串,打印最终分割成的数组
console.log(params.split(options.separator));
});
// 解析 commander
program.parse();
此时便可执行命令
mycli split --separator=/ a/b/c
或(用空格代替 = )
mycli split --separator / a/b/c
此命令的功能是:将字符串 a/b/c 按分割符 / 分割为数组

因给命令设置了别名 sp,所以命令可简写为
mycli sp --separator=/ a/b/c
命令的配置 -s 是 --separator 的缩写,所以命令还简写为(-s 后紧跟 / )
mycli sp -s/ a/b/c
或(-s 后有空格再 / )
mycli sp -s / a/b/c
再试下
mycli sp 'a,b,c'

可见默认的分割符为设置的 ,
从 help 中也能了解命令配置和参数的写法

[] 包裹,说明命令的配置信息都是可选的<> 包裹,则是一个必传的参数,数据类型为 string添加多种参数
共三种参数
<>包裹[]包裹argument() 的语法为:
argument(参数字段和类型定义,参数描述,参数默认值)
省略参数描述和默认值,可以将多个参数写在一个argument中,如
program.arguments(' ');
program
.command("login")
.description("登录")
.argument("" , "用户名") // 必要参数
.argument("[password]", "密码", "123456") // 可选参数(“123456”为默认值)
.argument("[permissions...]", "权限") // 可变参数
.action((username, password, permissions) => {
console.log("username:", username);
console.log("password:", password);
permissions.forEach((item) => {
console.log("权限 %s", item);
});
});
不传密码时,默认密码为 123456

传密码时,则用传入的密码

传入更多参数,则都是可变参数,一起以数组形式传入

自定义默认命令
默认的命令是 help

在command() 中添加参数 { isDefault: true }
program
.command("init", { isDefault: true }) // 注册默认命令
.description("初始化") // 描述命令的描述,在帮助信息中会展示
// 命令的具体行为(执行的代码)
.action((params, options, cmd) => {
console.log("---- 开始对 mycli 进行初始化 ----");
// 自定义初始化需执行的代码,此范例为打印当前目录
console.log("当前目录为:" + process.cwd());
console.log("---- 完成了 mycli 的初始化 ----");
});

将配置设置为必填 requiredOption
program
.command("split") // 注册命令
.description("将字符串分割成数组") // 对命令功能的描述
.requiredOption("-s, --separator " , "分割符") // 必填的命令配置信息
.argument("" , "被分割的字符串") // 命令的参数
// 命令的具体行为(执行的代码)
.action((params, options, cmd) => {
// 命令的功能代码为分割字符串,打印最终分割成的数组
console.log(params.split(options.separator));
});
若执行配置缺失的命令会报错,加上配置就正常了。

获取版本号的实现
从 package.json 中可以取到版本号
import pkg from "./package.json" assert { type: "json" };
// version() 完成版本号指令的注册和配置
program.version(pkg.version);
// 解析 commander
program.parse();
执行
mycli --version
或
mycli -V
都会打印版本号

自定义 help 信息
默认的 help 信息如下:

program.usage("<命令> [配置]");
效果如下

program.helpInformation = function () {
return "《mycli使用说明》\n命令列表\ninit —— 初始化\nsplit —— 字符串分割";
};

更多功能
可参考官方文档
https://github.com/tj/commander.js/blob/HEAD/Readme_zh-CN.md