Node CLI 之 Commander.js (1)

2023-12-13 10:13:54

官网地址: https://github.com/tj/commander.js/blob/f1ae2db8e2da01d6efcbfd59cbf82202f864b0c1/Readme_zh-CN.md

Commander.js是node.js命令行界面的完整解决方案

开始

  • 新建一个node工程
  • 执行 npm install commander
  • package.json中新增代码
  • 添加 #! /usr/bin/env node,用于识别是node命令文件
"bin": {
  "cli": "./index.js"
}

声明 program 变量

/ CommonJS (.cjs)
const { program } = require('commander');

如果程序较为复杂,用户需要以多种方式来使用 Commander,如单元测试等。创建本地 Command 对象是一种更好的方式:

const { Command } = require('commander');
const program = new Command();

选项 option

使用 .option 实现,举个例子,然后再解释难点

program
  .option('-d, --debug', 'output extra debugging')
  .option('-s, --small', 'small pizza size')
  .option('-p, --pizza-type <type>', 'flavour of pizza');
  .option('-c, --cheese <type>', 'add the specified type of cheese', 'blue');
  .option('-d, --drink [item]', 'output extra debugging', function deb (v) {
        console.log('1---', arguments);
        return '123'
    })
  • 第一个参数是选项名称,第二个参数选项描述, 第三个参数是默认值, 第四个为过滤函数,会改改变用户输入的值
  • 每个选项可以定义一个短选项名称(-后面接单个字符)
  • 一个长选项名称(–后面接一个或多个单词),驼峰命名法(camel-case)
  • 短名称和长名称之间可以使用逗号,空格,|分割
  • 有两种最常用的选项
    • 一类是 boolean 型选项,选项无需配置参数,
    • 另一类选项则可以设置参数(使用尖括号声明在该选项后,如–expect )。如果在命令行中不指定具体的选项及参数,则会被定义为undefine
调用方式
serve -p 80
serve -p80
serve --port 80
serve --port=80

项及其选项参数可以用空格分隔,也可以组合成同一个参数。选项参数可以直接跟在短选项之后,也可以在长选项后面加上 = 。

完整例子
program
  .option('-d, --debug', 'output extra debugging')
  .option('-s, --small', 'small pizza size')
  .option('-p, --pizza-type <type>', 'flavour of pizza');
  .option('-d, --drink [item]', 'output extra debugging', function deb (v) {
        console.log('1---', arguments);
        return '123'
    })

program.parse(process.argv);

const options = program.opts();
if (options.debug) console.log(options);
console.log('pizza details:');
if (options.small) console.log('- small pizza size');
if (options.pizzaType) console.log(`- ${options.pizzaType}`);
必填选项

通过 .requiredOption 方法可以设置选项为必填。必填选项要么设有默认值,要么必须在命令行中输入,对应的属性字段在解析时必定会有赋值。该方法其余参数与 .option一致

program
  .requiredOption('-c, --cheese <type>', 'pizza must have cheese');

program.parse();

终端中部署入参数,会报错
error: required option '-c, --cheese <type>' not specified
变长参数选项

通过使用 来设置参数为可变长参数

program
  .option('-n, --number <numbers...>', 'specify numbers')
  .option('-l, --letter [letters...]', 'specify letters');

program.parse();

console.log('Options: ', program.opts());
console.log('Remaining arguments: ', program.args);
$ collect -n 1 2 3 --letter a b c
Options:  { number: [ '1', '2', '3' ], letter: [ 'a', 'b', 'c' ] }
Remaining arguments:  []
$ collect --letter=A -n80 operand
Options:  { number: [ '80' ], letter: [ 'A' ] }
Remaining arguments:  [ 'operand' ]
$ collect --letter -n 1 -n 2 3 -- operand
Options:  { number: [ '1', '2', '3' ], letter: true }
Remaining arguments:  [ 'operand' ]
其他选项配置

大多数情况下,选项均可通过.option()方法添加。但对某些不常见的用例,也可以直接构造Option对象,对选项进行更详尽的配置

program
  .addOption(new Option('-s, --secret').hideHelp())
  .addOption(new Option('-t, --timeout <delay>', 'timeout in seconds').default(60, 'one minute'))
  .addOption(new Option('-d, --drink <size>', 'drink size').choices(['small', 'medium', 'large']))
  .addOption(new Option('-p, --port <number>', 'port number').env('PORT'))
  .addOption(new Option('--donate [amount]', 'optional donation in dollars').preset('20').argParser(parseFloat))
  .addOption(new Option('--disable-server', 'disables the server').conflicts('port'))
  .addOption(new Option('--free-drink', 'small drink included free ').implies({ drink: 'small' }));

版本选项

.version 方法可以设置版本,其默认选项为-V和–version,设置了版本后,命令行会输出当前的版本号

program.version('0.0.1');

命令

通过 .command.addCommand 可以配置命令, 有两种实现方式

  • 为命令绑定处理函数
  • 将命令单独写成一个可执行文件

先看例子

// 通过绑定处理函数实现命令(这里的指令描述为放在`.command`中)
// 返回新生成的命令(即该子命令)以供继续配置
program
  .command('clone <source> [destination]')
  .description('clone a repository into a newly created directory')
  .option('-t, --typeName <typeName>', '基于哪个项目')
  .action((source, destination) => {
    console.log('clone command called');
  });

// 通过独立的的可执行文件实现命令 (注意这里指令描述是作为`.command`的第二个参数)
// 返回最顶层的命令以供继续添加子命令
program
  .command('start <service>', 'start named service')
  .command('stop [service]', 'stop named service, or all if no name supplied');

// 分别装配命令
// 返回最顶层的命令以供继续添加子命令
program
  .addCommand(build.makeBuildCommand());
  • .command 的第一个参数为命令名称, 命令参数可以跟在名称后面,也可以用.argument 单独指定, 参数可为必选的(尖括号表示)、可选的(方括号表示)或变长参数(点号表示,如果使用,只能是最后一个参数)
  • option 为命令中的选项 比如 vue create my-project -t vue-template
  • .description 为命令描述
  • .action 为命令触发之后,执行的函数

举个例子:

program
  .command('rmdir <soure>')
  .description('remove some directory')
  .option('-f, --force', '强制删除')
  .action((source, destination) => {
    console.log('remove some directory');
  });
// 调用方式
// Try the following:
//    rmdir ./project
//    rmdir ./project -f
//    rmdir ./project --force

program
  .command('add')
  .argument('<first>', 'integer argument', myParseInt)
  .argument('[second]', 'integer argument', myParseInt, 1000)
  .action((first, second) => {
    console.log(`${first} + ${second} = ${first + second}`);
  });
// 调用方式
// Try the following:
//    add 1
//    add 1 2

program
  .argument("<name>")
  .option("-t, --title <honorific>", "title to use before name")
  .option("-d, --debug", "display some debugging")
  .action((name, options, command) => {
    if (options.debug) {
      console.error("Called %s with options %o", command.name(), options);
    }
    const title = options.title ? `${options.title} ` : "";
    console.log(`Thank-you ${title}${name}`);
  });

// 调用方式
// Try the following:
//    node thank.js John
//    node thank.js Doe --title Mr
//    node thank.js --debug Doe --title Mr

文章来源:https://blog.csdn.net/weixin_40639095/article/details/134862038
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。