@expo/commander

中文文档
5.0.0发布于 2020/04/15MITTypeScriptCommonJS近 30 天下载 2.5万

用于节点.js命令行程序的完整解决方案

中文使用文档
文档目录34 节
  1. 安装
  2. 声明 程序 变量
  3. 选项
  4. 常见选项类型、布尔和值
  5. 默认选项值
  6. 其他选项类型,可负布尔和旗下值
  7. 自定义选项处理
  8. 所需选项
  9. 版本选项
  10. 图标
  11. 指定参数语法
  12. 动作处理器( 子) 命令
  13. 独立的可执行(子)命令
  14. 自动帮助
  15. 自定义帮助
  16. 使用和名称
  17. 帮助(cb)
  18. 输出帮助( cb)
  19. 帮助信息 ()
  20. 。帮助选项(旗帜,描述)
  21. 添加帮助命令 ()
  22. 自定义事件听众
  23. 位和块
  24. .parse () 和.parse Async () (中文(简体) )
  25. 避免选项名称冲突
  26. 类型脚本
  27. 创建命令( C)
  28. 节点选项, 如 --harmony
  29. 调试独立可执行子命令
  30. 覆盖退出处理
  31. 实例
  32. 许可证
  33. 支助
  34. 企业指挥官

指挥官.js

Build Status NPM Version NPM Downloads Install Size

彻底解决 节点.js 命令行界面,灵感来自Ruby's 指挥官。 。 。 .

以其他语言阅读:英语 简体中文

安装

npm install commander

声明 程序 变量

指挥官输出一个全球目标 方便快速程序. 本文中的例子中将此用作简短.

const { program } = require('commander');
program.version('0.0.1');

对于可能以多种方式使用指挥官的较大程序,包括单位测试,最好创建一个本地命令对象来使用.

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

选项

选项与 .option() 方法,也可作为选项的文档。 每个选项可以有一个短的旗帜(单字符)和一个长名,由逗号或空格或垂直栏('|')相隔.

可以在命令对象上作为属性访问这些选项. "--template-engine"等多词选项被骆驼套取出,成为了"--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- program.templateEngine 包括: ưμ㼯A 避免名称冲突。 。 。 .

多个短旗可以选择在破折号后的一个单一参数中合并:布尔旗,上一旗可能取出一个值,和值. 举个例子 -a -b -p 80 可写为: -ab -p80 甚至是 -abp80。 。 。 .

你用得着 -- 以表示选项的结束,任何剩余参数将被使用而不作解释. 这对将选项传递给另一个特别有用 命令,例如: do -- git --version。 。 。 .

命令行上的选项不是位置的,可以在其他命令参数之前或之后指定.

常见选项类型、布尔和值

使用最多的两种选项类型是布尔旗和取值的选项(用角括号声明)。 两者都是 undefined 除非命令行上指定.

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

program
  .option('-d, --debug', 'output extra debugging')
  .option('-s, --small', 'small pizza size')
  .option('-p, --pizza-type <type>', 'flavour of pizza');

program.parse(process.argv);

if (program.debug) console.log(program.opts());
console.log('pizza details:');
if (program.small) console.log('- small pizza size');
if (program.pizzaType) console.log(`- ${program.pizzaType}`);
$ pizza-options -d
{ debug: true, small: undefined, pizzaType: undefined }
pizza details:
$ pizza-options -p
error: option '-p, --pizza-type <type>' argument missing
$ pizza-options -ds -p vegetarian
{ debug: true, small: true, pizzaType: 'vegetarian' }
pizza details:
- small pizza size
- vegetarian
$ pizza-options --pizza-type=cheese
pizza details:
- cheese

program.parse(arguments) 处理参数,在 program.args 阵列.

默认选项值

您可以为需要值的选项指定默认值.

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

program
  .option('-c, --cheese <type>', 'add the specified type of cheese', 'blue');

program.parse(process.argv);

console.log(`cheese: ${program.cheese}`);
$ pizza-options
cheese: blue
$ pizza-options --cheese stilton
cheese: stilton

其他选项类型,可负布尔和旗下值

您可以指定布尔选项长名, 并带有线索 no- 以设置选项值. 仅此定义也可以默认实现选项.

如果您定义 --foo 首先,添加 --no-foo 切换默认值 否则就是了 您可以指定布尔旗的默认布尔值, 并在命令行上被覆盖 .

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

program
  .option('--no-sauce', 'Remove sauce')
  .option('--cheese <flavour>', 'cheese flavour', 'mozzarella')
  .option('--no-cheese', 'plain with no cheese')
  .parse(process.argv);

const sauceStr = program.sauce ? 'sauce' : 'no sauce';
const cheeseStr = (program.cheese === false) ? 'no cheese' : `${program.cheese} cheese`;
console.log(`You ordered a pizza with ${sauceStr} and ${cheeseStr}`);
$ pizza-options
You ordered a pizza with sauce and mozzarella cheese
$ pizza-options --sauce
error: unknown option '--sauce'
$ pizza-options --cheese=blue
You ordered a pizza with sauce and blue cheese
$ pizza-options --no-sauce --no-cheese
You ordered a pizza with no sauce and no cheese

您可以指定一个选项, 该选项具有旗帜的功能, 但也可以取一个值( 使用方括号声明) .

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

program
  .option('-c, --cheese [type]', 'Add cheese with optional type');

program.parse(process.argv);

if (program.cheese === undefined) console.log('no cheese');
else if (program.cheese === true) console.log('add cheese');
else console.log(`add cheese type ${program.cheese}`);
$ pizza-options
no cheese
$ pizza-options --cheese
add cheese
$ pizza-options --cheese mozzarella
add cheese type mozzarella

自定义选项处理

您可以指定一个功能来进行选项值的自定义处理。 回调函数收到两个参数,用户指定值和 选项的上一个值。 它返回选项的新值 .

这使得您可以将选项值强制到想要的类型,或者积累值,或者完全自定义处理.

您可以在函数后选择指定选项的默认/启动值 .

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

function myParseInt(value, dummyPrevious) {
  // parseInt takes a string and an optional radix
  return parseInt(value);
}

function increaseVerbosity(dummyValue, previous) {
  return previous + 1;
}

function collect(value, previous) {
  return previous.concat([value]);
}

function commaSeparatedList(value, dummyPrevious) {
  return value.split(',');
}

program
  .option('-f, --float <number>', 'float argument', parseFloat)
  .option('-i, --integer <number>', 'integer argument', myParseInt)
  .option('-v, --verbose', 'verbosity that can be increased', increaseVerbosity, 0)
  .option('-c, --collect <value>', 'repeatable value', collect, [])
  .option('-l, --list <items>', 'comma separated list', commaSeparatedList)
;

program.parse(process.argv);

if (program.float !== undefined) console.log(`float: ${program.float}`);
if (program.integer !== undefined) console.log(`integer: ${program.integer}`);
if (program.verbose > 0) console.log(`verbosity: ${program.verbose}`);
if (program.collect.length > 0) console.log(program.collect);
if (program.list !== undefined) console.log(program.list);
$ custom -f 1e2
float: 100
$ custom --integer 2
integer: 2
$ custom -v -v -v
verbose: 3
$ custom -c a -c b -c c
[ 'a', 'b', 'c' ]
$ custom --list x,y,z
[ 'x', 'y', 'z' ]

所需选项

您可使用 .requiredOption。该选项在解析后必须有一个值,通常在命令行上指定,或者可能从默认值(从环境角度讲)中指定。 这种方法在其他方面与 .option 格式、取出旗帜和描述,以及可选的默认值或自定义处理.

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

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

program.parse(process.argv);
$ pizza
error: required option '-c, --cheese <type>' not specified

版本选项

可选 version 方法添加显示命令版本的处理。 默认选项旗是 -V 财务报告和审定财务报表 --version,并在显示命令时打印出版本编号和出处.

program.version('0.0.1');
$ ./examples/pizza -V
0.0.1

您可以通过向 version 方法,使用 旗帜的语法与 option 方法。 版本旗可以任意取名,但需要长名.

program.version('0.0.1', '-v, --vers', 'output the current version');

图标

您可以使用 .command() 或者说 .addCommand()。这些可以有两种方式执行:使用附加在命令上的动作处理器,或者作为独立的可执行文件(稍后更详细地描述). 子命令可能会被嵌入( Name实例) (中文(简体) ).

在第一个参数中改为 .command() 您指定命令名称和任何命令参数。 论点可能是 <required> 或者说 [optional],最后的论点也可能是 variadic...。 。 。 .

你用得着 .addCommand() 将已配置的子命令添加到程序中.

例如:

// Command implemented using action handler (description is supplied separately to `.command`)
// Returns new command for configuring.
program
  .command('clone <source> [destination]')
  .description('clone a repository into a newly created directory')
  .action((source, destination) => {
    console.log('clone command called');
  });

// Command implemented using stand-alone executable file (description is second parameter to `.command`)
// Returns top-level command for adding more commands.
program
  .command('start <service>', 'start named service')
  .command('stop [service]', 'stop named service, or all if no name supplied');

// Command prepared separately.
// Returns top-level command for adding more commands.
program
  .addCommand(build.makeBuildCommand());

配置选项可随调用传递到 .command()指定 true 页:1 opts.noHelp 将删除生成的帮助输出中的命令。 指定 true 页:1 opts.isDefault 如果没有指定其他子命令, 将运行该子命令( q)实例) (中文(简体) ).

指定参数语法

你用这个 .arguments 以指定顶级命令的参数,而子命令的参数包含在 .command 电话 尖括号(例如:. <required>) 指明所需投入。 方括号(如:. [optional])表示可选输入.

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

program
  .version('0.1.0')
  .arguments('<cmd> [env]')
  .action(function (cmd, env) {
    cmdValue = cmd;
    envValue = env;
  });

program.parse(process.argv);

if (typeof cmdValue === 'undefined') {
  console.error('no command given!');
  process.exit(1);
}
console.log('command:', cmdValue);
console.log('environment:', envValue || "no environment given");

一个命令的最后一个论点可以是variadic的,只有最后一个论点. 为了跟你争吵 附录 ... 以至参数名称。 例如:

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

program
  .version('0.1.0')
  .command('rmdir <dir> [otherDirs...]')
  .action(function (dir, otherDirs) {
    console.log('rmdir %s', dir);
    if (otherDirs) {
      otherDirs.forEach(function (oDir) {
        console.log('rmdir %s', oDir);
      });
    }
  });

program.parse(process.argv);

Variadic 参数作为数组传递给动作处理器.

动作处理器( 子) 命令

可以在使用动作处理器的命令中添加选项. 动作处理器会为您声明的每个参数传递一个参数, 还有一个参数就是 命令对象本身。 此命令参数有添加为属性的指令特定选项的值 .

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

program
  .command('rm <dir>')
  .option('-r, --recursive', 'Remove recursively')
  .action(function (dir, cmdObj) {
    console.log('remove ' + dir + (cmdObj.recursive ? ' recursively' : ''))
  })

program.parse(process.argv)

你可以提供 async 动作处理器,在此情况下,您会调用 .parseAsync 而不是说 .parse。 。 。 .

async function run() { /* code goes here */ }

async function main() {
  program
    .command('run')
    .action(run);
  await program.parseAsync(process.argv);
}

命令行上的选项在使用命令时会被验证. 任何未知的选项都会被报告为出错.

独立的可执行(子)命令

何时 .command() 上面引用了一个描述性参数, 这告诉指挥官, 你会使用独立的可执行文件 用于子命令. 命令会在条目脚本目录中搜索可执行文件( 如 ./examples/pm名称 program-subcommand一样 pm-install, (中文(简体) ), pm-search。 。 。 . 您可以指定自定义名称 executableFile 配置选项.

您在可执行文件中处理可执行命令( sub) 的选项, 不要在顶层声明 .

// file: ./examples/pm
const { program } = require('commander');

program
  .version('0.1.0')
  .command('install [name]', 'install one or more packages')
  .command('search [query]', 'search with optional query')
  .command('update', 'update installed packages', {executableFile: 'myUpdateSubCommand'})
  .command('list', 'list packages installed', {isDefault: true})
  .parse(process.argv);

如果程序被设计在全球安装, 确保可执行文件有合适的模式, 如 755。 。 。 .

自动帮助

帮助信息是自动生成的 基于信息指挥官已经知道 您的程序。 默认 帮助选项 -h,--help. (中文(简体) )实例(中文(简体) )

$ node ./examples/pizza --help
Usage: pizza [options]

An application for pizzas ordering

Options:
  -V, --version        output the version number
  -p, --peppers        Add peppers
  -c, --cheese <type>  Add the specified type of cheese (default: "marble")
  -C, --no-cheese      You do not want any cheese
  -h, --help           display help for command

A 类 help 如果命令有子命令,则默认会添加命令。 它可以单独使用,也可以使用子命令名来显示 进一步帮助子命令。 如果 shell 程序有隐含的帮助 :

shell help
shell --help

shell help spawn
shell spawn --help

自定义帮助

您可以通过监听“ -- help” 显示额外信息。 (实例(中文(简体) )

program
  .option('-f, --foo', 'enable some foo');

// must be before .parse()
program.on('--help', () => {
  console.log('');
  console.log('Example call:');
  console.log('  $ custom-help --help');
});

使用以下帮助输出 :

Usage: custom-help [options]

Options:
  -f, --foo   enable some foo
  -h, --help  display help for command

Example call:
  $ custom-help --help

使用和名称

这些允许您在帮助的第一行中自定义使用描述 。 名字不是这个意思 从(完整的)程序论据中推断出来的。 鉴于:

program
  .name("my-command")
  .usage("[global options] command")

帮助将首先:

Usage: my-command [global options] command

帮助(cb)

输出帮助信息并立即退出. 可选的回调cb允许在显示前对帮助文本进行后处理.

输出帮助( cb)

输出帮助信息而不退出. 可选的回调cb允许在显示前对帮助文本进行后处理.

帮助信息 ()

获取命令帮助信息作为处理或显示自己的字符串. (文本不包括自定义帮助) 从 --help 收听者们. )

。帮助选项(旗帜,描述)

覆盖默认帮助标记和描述 .

program
  .helpOption('-e, --HELP', 'read more information');

添加帮助命令 ()

您可以明确打开或关闭隐含的帮助命令 .addHelpCommand() 财务报告和审定财务报表 .addHelpCommand(false)。 。 。 .

您可以打开并定制帮助命令, 提供名称和描述 :

program.addHelpCommand('assist [command]', 'show assistance');

自定义事件听众

您可以通过听指令和选项事件执行自定义动作 .

program.on('option:verbose', function () {
  process.env.VERBOSE = this.verbose;
});

program.on('command:*', function (operands) {
  console.error(`error: unknown command '${operands[0]}'`);
  const availableCommands = program.commands.map(cmd => cmd.name());
  mySuggestBestMatch(operands[0], availableCommands);
  process.exitCode = 1;
});

位和块

.parse () 和.parse Async () (中文(简体) )

第一条理由 .parse 是分析字符串的数组。 您可以省略参数以隐含使用 process.argv。 。 。 .

如果这些论点遵循不同的惯例而不是节点,你就可以通过 from 选项:

  • "节点":默认, argv[0] 是应用程序和 argv[1] 是正在运行的脚本, 之后有用户参数
  • “ 电子 ” : argv[1] 视电子应用程序是否包装而异
  • 用户 : 用户的所有参数

例如:

program.parse(process.argv); // Explicit, node conventions
program.parse(); // Implicit, and auto-detect electron
program.parse(['-f', 'filename'], { from: 'user' });

避免选项名称冲突

初始和默认行为是选项值被存储 作为程序中的属性,动作处理器通过一个 命令对象,其选项值作为属性存储. 这是非常方便的代码, 但缺点是可能的冲突 命令的现有属性.

改变行为有两个新的常规,默认行为在未来可能会有变化:

  • storeOptionsAsProperties:是将选项值作为属性存储在命令对象上,还是单独存储(请注明虚假)并使用 .opts()
  • passCommandToAction: 是否将命令传递给动作处理器, 或仅仅是选项(请注明虚假)

(单位:千美元)实例(中文(简体) )

program
  .storeOptionsAsProperties(false)
  .passCommandToAction(false);

program
  .name('my-program-name')
  .option('-n,--name <name>');

program
  .command('show')
  .option('-a,--action <action>')
  .action((options) => {
    console.log(options.action);
  });

program.parse(process.argv);

const programOptions = program.opts();
console.log(programOptions.name);

类型脚本

Commander软件包包括它的TypeScript定义文件.

如果您使用 ts-node 和独立可执行子命令 .ts 文件,您需要通过节点调用您的程序,以正确调用子命令 。 譬如说.

node -r ts-node/register pm.ts

创建命令( C)

此工厂函数创建了新命令 。 它出口,可以使用而不使用 new,例如:

const { createCommand } = require('commander');
const program = createCommand();

createCommand 也是命令对象的一种方法,并创建一个新的命令而不是子命令。 这是内部使用的 使用 .command(),您可以将其覆盖到 自定义新子命令( 例如使用 子类 财务报告和审定财务报表 函数) (中文(简体) ).

节点选项, 如 --harmony

您可以启用 --harmony 选择的两种方式:

  • 使用 #! /usr/bin/env node --harmony 在子命令脚本中。 (Note Windows不支持这个模式. )
  • 使用 --harmony 选项,例如 node --harmony examples/pm publish编辑 --harmony 选项将在启用子命令进程时被保留.

调试独立可执行子命令

可执行子命令作为单独的子进程启动 .

如果你使用节点检查器 调试 使用可执行子命令 node --inspect 等人, 对产入子命令,检查端口增加1个.

如果您正在使用 VSCode 调试可执行子命令, 您需要设置 "autoAttachChildProcesses": true 标记在您的启动中。 json 配置 .

覆盖退出处理

默认命令 process.exit 当它检测出错误,或在显示帮助或版本后。 您可以覆盖 并随意提供回调。 默认覆盖抛出一个 CommanderError。 。 。 .

超常调用通过 a CommanderError 有属性 exitCode 编号, code 字符串,以及 message。默认的覆盖行为是抛出错误,但可执行子命令完成的同步处理除外。 错误消息或版本或帮助的正常显示 不受显示后调用的覆盖的影响.

program.exitOverride();

try {
  program.parse(process.argv);
} catch (err) {
  // custom processing...
}

实例

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

program
  .version('0.1.0')
  .option('-C, --chdir <path>', 'change the working directory')
  .option('-c, --config <path>', 'set config path. defaults to ./deploy.conf')
  .option('-T, --no-tests', 'ignore test hook');

program
  .command('setup [env]')
  .description('run setup commands for all envs')
  .option("-s, --setup_mode [mode]", "Which setup mode to use")
  .action(function(env, options){
    const mode = options.setup_mode || "normal";
    env = env || 'all';
    console.log('setup for %s env(s) with %s mode', env, mode);
  });

program
  .command('exec <cmd>')
  .alias('ex')
  .description('execute the given remote cmd')
  .option("-e, --exec_mode <mode>", "Which exec mode to use")
  .action(function(cmd, options){
    console.log('exec "%s" using %s mode', cmd, options.exec_mode);
  }).on('--help', function() {
    console.log('');
    console.log('Examples:');
    console.log('');
    console.log('  $ deploy exec sequential');
    console.log('  $ deploy exec async');
  });

program.parse(process.argv);

更多演示词可见于 实例 目录.

许可证

麻省理工学院

支助

Commander 5.x在Node的长期支持版本上获得全力支持,并有可能与Node 6合作,但没有测试. ( 对于节点6下方的版本,使用Command 3.x或 2.x

免费和社区支助的主要论坛是该项目 问题 (原始内容存档于2018-09-29). on GitHub.

企业指挥官

作为Tidelift订阅的一部分提供

指挥官的维护者和上千个其他软件包正与Tidelift合作,为您用来构建应用程序的开源依赖提供商业支持和维护. 节省时间,降低风险,改善代码健康,同时向维护者支付使用的确切依赖性. 学多取.

版本与发布记录

@expo/commander 共发布 4 个版本,首次发布于 2019/06/19;过去 12 个月发布了 0 个版本。

版本发布日期距今
5.0.0latest2020/04/156 年前
2.21.12019/06/257 年前
2.21.02019/06/247 年前
2.20.02019/06/197 年前

关于 @expo/commander 的常见问题

@expo/commander 是什么?

用于节点.js命令行程序的完整解决方案

如何安装 @expo/commander?

在项目目录运行 npm install @expo/commander,或使用 pnpm add / yarn add / bun add。

@expo/commander 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@expo/commander 支持 ESM 还是 CommonJS?

以 CommonJS 形式发布,可以直接 require();在 ES Module 项目中也可以用 import 引入(Node.js 会把 module.exports 作为默认导出)。

@expo/commander 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >= 6。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@expo/commander 可以商用吗?

@expo/commander 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@expo/commander 的下载量有多少?

根据 npm 官方下载统计,@expo/commander 在 2026/10/14 – 2026/11/12 这 30 天内被下载 24,961 次,日均约 832 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@expo/commander 还在维护吗?

最新版本 5.0.0 发布于 2020/04/15(6 年前);至今共发布 4 个版本,其中过去 12 个月发布了 0 个;首次发布于 2019/06/19。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。