Skip to content

Commit

Permalink
Rework default program name, and searching for subcommands (#1571)
Browse files Browse the repository at this point in the history
* Simplify how default program name found. Just use args.

* Rework search for executable files

* Adjust error messaging, still WIP

* Add executableDir and use searching for subcommands

* Wording improvements

* Add TypeScript for nameFromFilename

* Add new tests for name (and nameFromFilename)

* Add TypeScript for executableDir

* Start tests for subcommand search

* Comment-out unused routine for lint, WIP

* Refactor tests and skip launchable executable tests on Windows

* Add notes on further tests

* Filling out mock executable tests

* Expand tests

* Remove debugging and ToDo

* Relative and absolute test for executableDir

* Avoid memory leak warning

* Fix relative search test

* Separate and expand .name section in README.

And some lint, remove trailing spaces et al

* Add .name to multiple subcommand example

* Update description of executable search.

Add mention of .executableDir

* Add coverage of naming subcommands.
  • Loading branch information
shadowspawn committed Aug 6, 2021
1 parent 3f77e7e commit b1b7aca
Show file tree
Hide file tree
Showing 13 changed files with 483 additions and 91 deletions.
37 changes: 26 additions & 11 deletions Readme.md
Expand Up @@ -32,7 +32,8 @@ Read this in other languages: English | [简体中文](./Readme_zh-CN.md)
- [Custom help](#custom-help)
- [Display help after errors](#display-help-after-errors)
- [Display help from code](#display-help-from-code)
- [.usage and .name](#usage-and-name)
- [.name](#name)
- [.usage](#usage)
- [.helpOption(flags, description)](#helpoptionflags-description)
- [.addHelpCommand()](#addhelpcommand)
- [More configuration](#more-configuration-2)
Expand Down Expand Up @@ -66,15 +67,13 @@ This is used in the examples in this README for brevity.

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

For larger programs which may use commander in multiple ways, including unit testing, it is better to create a local Command object to use.

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

For named imports in ECMAScript modules, import from `commander/esm.mjs`.
Expand All @@ -93,7 +92,6 @@ import { Command } from 'commander';
const program = new Command();
```


## Options

Options are defined with the `.option()` method, also serving as documentation for the options. Each option can have a short flag (single character) and a long name, separated by a comma or space or vertical bar ('|').
Expand Down Expand Up @@ -550,15 +548,17 @@ pass more arguments than declared, but you can make this an error with `.allowEx
### Stand-alone executable (sub)commands
When `.command()` is invoked with a description argument, this tells Commander that you're going to use stand-alone executables for subcommands.
Commander will search the executables in the directory of the entry script (like `./examples/pm`) with the name `program-subcommand`, like `pm-install`, `pm-search`.
You can specify a custom name with the `executableFile` configuration option.
Commander will search the files in the directory of the entry script for a file with the name combination `command-subcommand`, like `pm-install` or `pm-search` in the example below. The search includes trying common file extensions, like `.js`.
You may specify a custom name (and path) with the `executableFile` configuration option.
You may specify a custom search directory for subcommands with `.executableDir()`.
You handle the options for an executable (sub)command in the executable, and don't declare them at the top-level.
Example file: [pm](./examples/pm)
```js
program
.name('pm')
.version('0.1.0')
.command('install [name]', 'install one or more packages')
.command('search [query]', 'search with optional query')
Expand Down Expand Up @@ -696,10 +696,25 @@ error: unknown option '--unknown'
`.helpInformation()`: get the built-in command help information as a string for processing or displaying yourself.
### .usage and .name
### .name
These allow you to customise the usage description in the first line of the help. The name is otherwise
deduced from the (full) program arguments. Given:
The command name appears in the help, and is also used for locating stand-alone executable subcommands.
You may specify the program name using `.name()` or in the Command constructor. For the program, Commander will
fallback to using the script name from the full arguments passed into `.parse()`. However, the script name varies
depending on how your program is launched so you may wish to specify it explicitly.
```js
program.name('pizza');
const pm = new Command('pm');
```
Subcommands get a name when specified using `.command()`. If you create the subcommand yourself to use with `.addCommand()`,
then set the name using `.name()` or in the Command constructor.
### .usage
This allows you to customise the usage description in the first line of the help. Given:
```js
program
Expand All @@ -715,7 +730,7 @@ Usage: my-command [global options] command
### .helpOption(flags, description)
By default every command has a help option. Override the default help flags and description. Pass false to disable the built-in help option.
By default every command has a help option. You may change the default help flags and description. Pass false to disable the built-in help option.
```js
program
Expand Down Expand Up @@ -903,7 +918,6 @@ You can modify this behaviour for custom applications. In addition, you can modi
Example file: [configure-output.js](./examples/configure-output.js)
```js
function errorColor(str) {
// Add ANSI escape codes to display text in red.
Expand Down Expand Up @@ -960,6 +974,7 @@ const { Command } = require('commander');
const program = new Command();
program
.name('deploy')
.version('0.0.1')
.option('-c, --config <path>', 'set config path', './deploy.conf');
Expand Down
7 changes: 4 additions & 3 deletions Readme_zh-CN.md
Expand Up @@ -65,15 +65,13 @@ npm install commander

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

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

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

要在 ECMAScript 模块中使用命名导入,可从`commander/esm.mjs`中导入。
Expand Down Expand Up @@ -270,6 +268,7 @@ $ collect --letter -n 1 -n 2 3 -- operand
Options: { number: [ '1', '2', '3' ], letter: true }
Remaining arguments: [ 'operand' ]
```
关于可能有歧义的用例,请见[可变参数的选项](./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)。
### 版本选项
Expand Down Expand Up @@ -534,6 +533,7 @@ Commander 将会尝试在入口脚本(例如`./examples/pm`)的目录中搜
```js
program
.name('pm')
.version('0.1.0')
.command('install [name]', 'install one or more packages')
.command('search [query]', 'search with optional query')
Expand Down Expand Up @@ -708,6 +708,7 @@ program.addHelpCommand('assist [command]', 'show assistance');
内建帮助信息通过`Help`类进行格式化。如有需要,可以使用`.configureHelp()`来更改其数据属性和方法,或使用`.createHelp()`来创建子类,从而配置`Help`类的行为。
数据属性包括:
- `helpWidth`:指明帮助信息的宽度。可在单元测试中使用。
- `sortSubcommands`:以字母序排列子命令
- `sortOptions`:以字母序排列选项
Expand Down Expand Up @@ -862,7 +863,6 @@ Commander 默认用作命令行应用,其输出写入 stdout 和 stderr。
示例代码:[configure-output.js](./examples/configure-output.js)
```js
function errorColor(str) {
// 添加 ANSI 转义字符,以将文本输出为红色
Expand Down Expand Up @@ -919,6 +919,7 @@ const { Command } = require('commander');
const program = new Command();
program
.name('deploy')
.version('0.0.1')
.option('-c, --config <path>', 'set config path', './deploy.conf');
Expand Down
1 change: 1 addition & 0 deletions examples/deploy
Expand Up @@ -5,6 +5,7 @@ const { Command } = require('../'); // include commander in git clone of command
const program = new Command();

program
.name('deploy')
.version('0.0.1')
.option('-c, --config <path>', 'set config path', './deploy.conf');

Expand Down
1 change: 1 addition & 0 deletions examples/pm
Expand Up @@ -5,6 +5,7 @@ const { Command } = require('../'); // include commander in git clone of command
const program = new Command();

program
.name('pm')
.version('0.0.1')
.description('Fake package manager')
.command('install [name]', 'install one or more packages').alias('i')
Expand Down
2 changes: 1 addition & 1 deletion examples/pm-install
Expand Up @@ -17,7 +17,7 @@ if (!pkgs.length) {
}

console.log();
if (program.force) console.log(' force: install');
if (program.opts().force) console.log(' force: install');
pkgs.forEach(function(pkg) {
console.log(' install : %s', pkg);
});
Expand Down

0 comments on commit b1b7aca

Please sign in to comment.