指挥官.js
彻底解决 节点.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合作,为您用来构建应用程序的开源依赖提供商业支持和维护. 节省时间,降低风险,改善代码健康,同时向维护者支付使用的确切依赖性. 学多取.