From bcb4a18b92f6b5342dde07a8ad25bb089cfdfdcb Mon Sep 17 00:00:00 2001 From: wenjie Date: Wed, 18 May 2022 16:56:40 +0800 Subject: [PATCH 1/9] docs: quick start --- Readme_zh-CN.md | 95 ++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 86 insertions(+), 9 deletions(-) diff --git a/Readme_zh-CN.md b/Readme_zh-CN.md index 729b4908a..4fdf87890 100644 --- a/Readme_zh-CN.md +++ b/Readme_zh-CN.md @@ -11,6 +11,7 @@ - [Commander.js](#commanderjs) - [安装](#%e5%ae%89%e8%a3%85) + - [快速开始](#%E5%BF%AB%E9%80%9F%E5%BC%80%E5%A7%8B) - [声明 program 变量](#%e5%a3%b0%e6%98%8e-program-%e5%8f%98%e9%87%8f) - [选项](#%e9%80%89%e9%a1%b9) - [常用选项类型,boolean 型选项和带参数的选项](#%e5%b8%b8%e7%94%a8%e9%80%89%e9%a1%b9%e7%b1%bb%e5%9e%8bboolean-%e5%9e%8b%e9%80%89%e9%a1%b9%e5%92%8c%e5%b8%a6%e5%8f%82%e6%95%b0%e9%80%89%e9%a1%b9) @@ -55,37 +56,113 @@ ## 安装 -```bash +```sh npm install commander ``` -## 声明 program 变量 +## 快速开始 -为简化使用,Commander 提供了一个全局对象。本文档的示例代码均按此方法使用: +编写代码来描述你的命令行界面。 +Commander 负责将参数解析为选项和命令参数,为问题显示使用错误,并实现一个有帮助的系统。 + +Commander 是严格的,并且会针对无法识别的选项显示错误。 +两种最常用的选项类型是布尔选项,和从参数中获取值的选项。 + +示例代码:[split.js](./examples/split.js) ```js const { program } = require('commander'); + +program + .option('--first') + .option('-s, --separator '); + +program.parse(); + +const options = program.opts(); +const limit = options.first ? 1 : undefined; +console.log(program.args[0].split(options.separator, limit)); +``` + +```console +$ node split.js -s / --fits a/b/c +error: unknown option '--fits' +(Did you mean --first?) +$ node split.js -s / --first a/b/c +[ 'a' ] ``` -如果程序较为复杂,用户需要以多种方式来使用 Commander,如单元测试等。创建本地`Command`对象是一种更好的方式: +这是一个使用子命令并带有帮助描述的更完整的程序。在多命令程序中,每个命令(或命令的独立可执行文件)都有一个操作处理程序。 + +示例代码:[string-util.js](./examples/string-util.js) ```js const { Command } = require('commander'); const program = new Command(); + +program + .name('string-util') + .description('CLI to some JavaScript string utilities') + .version('0.8.0'); + +program.command('split') + .description('Split a string into substrings and display as an array') + .argument('', 'string to split') + .option('--first', 'display just the first substring') + .option('-s, --separator ', 'separator character', ',') + .action((str, options) => { + const limit = options.first ? 1 : undefined; + console.log(str.split(options.separator, limit)); + }); + +program.parse(); +``` + +```console +$ node string-util.js help split +Usage: string-util split [options] + +Split a string into substrings and display as an array. + +Arguments: + string string to split + +Options: + --first display just the first substring + -s, --separator separator character (default: ",") + -h, --help display help for command + +$ node string-util.js split --separator=/ a/b/c +[ 'a', 'b', 'c' ] ``` -要在 ECMAScript 模块中使用命名导入,可从`commander/esm.mjs`中导入。 +More samples can be found in the [examples](https://github.com/tj/commander.js/tree/master/examples) directory. + +## 声明 program 变量 + +为简化使用,Commander 提供了一个全局对象。本文档的示例代码均按此方法使用: ```js -// index.mjs -import { Command } from 'commander/esm.mjs'; +// CommonJS (.cjs) +const { program } = require('commander'); +``` + +如果程序较为复杂,用户需要以多种方式来使用 Commander,如单元测试等。创建本地 Command 对象是一种更好的方式: + +```js +// CommonJS (.cjs) +const { Command } = require('commander'); const program = new Command(); ``` -TypeScript 用法: +```js +// ECMAScript (.mjs) +import { Command } from 'commander'; +const program = new Command(); +``` ```ts -// index.ts +// TypeScript (.ts) import { Command } from 'commander'; const program = new Command(); ``` From 156cdba5f6ac34a942d04f44f655df2c187a0a82 Mon Sep 17 00:00:00 2001 From: wenjie Date: Thu, 19 May 2022 11:14:56 +0800 Subject: [PATCH 2/9] docs: options --- Readme_zh-CN.md | 64 +++++++++++++++++++++++++++++++++++++------------ 1 file changed, 49 insertions(+), 15 deletions(-) diff --git a/Readme_zh-CN.md b/Readme_zh-CN.md index 4fdf87890..81bb238fa 100644 --- a/Readme_zh-CN.md +++ b/Readme_zh-CN.md @@ -171,17 +171,29 @@ const program = new Command(); Commander 使用`.option()`方法来定义选项,同时可以附加选项的简介。每个选项可以定义一个短选项名称(-后面接单个字符)和一个长选项名称(--后面接一个或多个单词),使用逗号、空格或`|`分隔。 -解析后的选项可以通过`Command`对象上的`.opts()`方法获取,同时会被传递给命令处理函数。可以使用`.getOptionValue()`和`.setOptionValue()`操作单个选项的值。 +解析后的选项可以通过`Command`对象上的`.opts()`方法获取,同时会被传递给命令处理函数。 对于多个单词的长选项,选项名会转为驼峰命名法(camel-case),例如`--template-engine`选项可通过`program.opts().templateEngine`获取。 -多个短选项可以合并简写,其中最后一个选项可以附加参数。 -例如,`-a -b -p 80`也可以写为`-ab -p80`,甚至进一步简化为`-abp80`。 +选项及其选项参数可以用空格分隔,也可以组合成同一个参数。选项参数可以直接跟在短选项之后,也可以在长选项后面加上 `=`。 + +```sh +serve -p 80 +serve -p80 +serve --port 80 +serve --port=80 +``` `--`可以标记选项的结束,后续的参数均不会被命令解释,可以正常使用。 默认情况下,选项在命令行中的顺序不固定,一个选项可以在其他参数之前或之后指定。 +当`.opts()`不够用时,还有其他相关方法: + +- `.optsWithGlobals()`返回合并的本地和全局选项值 +- `.getOptionValue()`和`.setOptionValue()`操作单个选项的值 +- `.getOptionValueSource()`和`.setOptionValueWithSource()`包括选项值的来源 + ### 常用选项类型,boolean 型选项和带参数选项 有两种最常用的选项,一类是 boolean 型选项,选项无需配置参数,另一类选项则可以设置参数(使用尖括号声明在该选项后,如`--expect `)。如果在命令行中不指定具体的选项及参数,则会被定义为`undefined`。 @@ -203,7 +215,7 @@ if (options.small) console.log('- small pizza size'); if (options.pizzaType) console.log(`- ${options.pizzaType}`); ``` -```bash +```console $ pizza-options -p error: option '-p, --pizza-type ' argument missing $ pizza-options -d -s -p vegetarian @@ -216,6 +228,12 @@ pizza details: - cheese ``` +多个布尔短选项可以在破折号之后组合在一起,并且可以跟一个取值的单一选项。 +例如 `-d -s -p cheese` 可以写成 `-ds -p cheese` 甚至 `-dsp cheese`。 + +具有预期选项参数的选项是贪婪的,并且无论值如何,都会消耗参数。 +所以 `--id -xyz` 读取 `-xyz` 作为选项参数。 + 通过`program.parse(arguments)`方法处理参数,没有被使用的选项会存放在`program.args`数组中。该方法的参数是可选的,默认值为`process.argv`。 ### 选项的默认值 @@ -233,7 +251,7 @@ program.parse(); console.log(`cheese: ${program.opts().cheese}`); ``` -```bash +```console $ pizza-options cheese: blue $ pizza-options --cheese stilton @@ -244,7 +262,7 @@ cheese: stilton 可以定义一个以`no-`开头的 boolean 型长选项。在命令行中使用该选项时,会将对应选项的值置为`false`。当只定义了带`no-`的选项,未定义对应不带`no-`的选项时,该选项的默认值会被置为`true`。 -如果已经定义了`--foo`,那么再定义`--no-foo`并不会改变它本来的默认值。可以为一个 boolean 类型的选项指定一个默认的布尔值,在命令行里可以重写它的值。 +如果已经定义了`--foo`,那么再定义`--no-foo`并不会改变它本来的默认值。 示例代码:[options-negatable.js](./examples/options-negatable.js) @@ -261,7 +279,7 @@ const cheeseStr = (options.cheese === false) ? 'no cheese' : `${options.cheese} console.log(`You ordered a pizza with ${sauceStr} and ${cheeseStr}`); ``` -```bash +```console $ pizza-options You ordered a pizza with sauce and mozzarella cheese $ pizza-options --sauce @@ -288,7 +306,7 @@ else if (options.cheese === true) console.log('add cheese'); else console.log(`add cheese type ${options.cheese}`); ``` -```bash +```console $ pizza-options no cheese $ pizza-options --cheese @@ -297,6 +315,8 @@ $ pizza-options --cheese mozzarella add cheese type mozzarella ``` +带有可选选项参数的选项不是贪婪的,并且会忽略以破折号开头的参数。因此对于`--id -5`,`id`表现为布尔选项,但如果需要,您可以使用组合形式,例如 `--id=-5`。 + 关于可能有歧义的用例,请见[可变参数的选项](./docs/zh-CN/%E5%8F%AF%E5%8F%98%E5%8F%82%E6%95%B0%E7%9A%84%E9%80%89%E9%A1%B9.md)。 ### 必填选项 @@ -312,7 +332,7 @@ program program.parse(); ``` -```bash +```console $ pizza error: required option '-c, --cheese ' not specified ``` @@ -334,7 +354,7 @@ console.log('Options: ', program.opts()); console.log('Remaining arguments: ', program.args); ``` -```bash +```console $ collect -n 1 2 3 --letter a b c Options: { number: [ '1', '2', '3' ], letter: [ 'a', 'b', 'c' ] } Remaining arguments: [] @@ -356,7 +376,7 @@ Remaining arguments: [ 'operand' ] program.version('0.0.1'); ``` -```bash +```console $ ./examples/pizza -V 0.0.1 ``` @@ -371,26 +391,40 @@ program.version('0.0.1', '-v, --vers', 'output the current version'); 大多数情况下,选项均可通过`.option()`方法添加。但对某些不常见的用例,也可以直接构造`Option`对象,对选项进行更详尽的配置。 -示例代码:[options-extra.js](./examples/options-extra.js) +示例代码:[options-extra.js](./examples/options-extra.js), [options-env.js](./examples/options-env.js), [options-conflicts.js](./examples/options-conflicts.js), [options-implies.js](./examples/options-implies.js) ```js program .addOption(new Option('-s, --secret').hideHelp()) .addOption(new Option('-t, --timeout ', 'timeout in seconds').default(60, 'one minute')) - .addOption(new Option('-d, --drink ', 'drink size').choices(['small', 'medium', 'large'])); + .addOption(new Option('-d, --drink ', 'drink size').choices(['small', 'medium', 'large'])) + .addOption(new Option('-p, --port ', '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' })); ``` -```bash +```console $ extra --help Usage: help [options] Options: -t, --timeout timeout in seconds (default: one minute) -d, --drink drink cup size (choices: "small", "medium", "large") + -p, --port port number (env: PORT) + --donate [amount] optional donation in dollars (preset: "20") + --disable-server disables the server + --free-drink small drink included free -h, --help display help for command $ extra --drink huge error: option '-d, --drink ' argument 'huge' is invalid. Allowed choices are small, medium, large. + +$ PORT=80 extra --donate --free-drink +Options: { timeout: 60, donate: 20, port: '80', freeDrink: true, drink: 'small' } + +$ extra --disable-server --port 8000 +error: option '--disable-server' cannot be used with option '-p, --port ' ``` ### 自定义选项处理 @@ -443,7 +477,7 @@ if (options.collect.length > 0) console.log(options.collect); if (options.list !== undefined) console.log(options.list); ``` -```bash +```console $ custom -f 1e2 float: 100 $ custom --integer 2 From 838b544eb23740458c55030fdc7a9d829941836f Mon Sep 17 00:00:00 2001 From: wenjie Date: Thu, 19 May 2022 11:49:17 +0800 Subject: [PATCH 3/9] docs: others --- Readme_zh-CN.md | 138 ++++++++++++++++++++++-------------------------- 1 file changed, 62 insertions(+), 76 deletions(-) diff --git a/Readme_zh-CN.md b/Readme_zh-CN.md index 81bb238fa..e75889249 100644 --- a/Readme_zh-CN.md +++ b/Readme_zh-CN.md @@ -617,6 +617,20 @@ program }); ``` +如果你愿意,你可以跳过为处理函数声明参数直接使用 command。 `this` 关键字设置为运行命令,可以在函数表达式中使用(但不能从箭头函数中使用)。 + +示例代码:[action-this.js](./examples/action-this.js) + +```js +program + .command('serve') + .argument('