dry-cli-help 0.2.1 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +12 -0
- data/README.md +73 -26
- data/Rakefile +1 -1
- data/lib/dry/cli/help/version.rb +1 -1
- metadata +3 -10
- data/SPECIFICATION.md +0 -213
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 10fb8e86e571ad96c6f523f4807d040b0421ebe1fa65e334738fa785e0212196
|
|
4
|
+
data.tar.gz: 408f6dd175e32d407f38306c9c61211a9b8e9d7e82f8870cde02ce58cfe64a23
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f42c06e5cb90eae00d6fc11f1fa4cbfed1f789005b4aa6dc0ea27cd60522de63019804c154e818efc4eb4bc52e673765ad638f881f94faa445b0b1a6ce637060
|
|
7
|
+
data.tar.gz: 9e711ac3f6b30580e1e979f391019de8f1c5d155b9ded6b1c72881e698d79347e337299aca96316b9c9806507d9b1d7022c0f30d9bf715083e60a7a651775c82
|
data/CHANGELOG.md
CHANGED
|
@@ -1,10 +1,22 @@
|
|
|
1
1
|
## [Unreleased]
|
|
2
2
|
|
|
3
|
+
## [0.5.0] - Unreleased
|
|
4
|
+
|
|
5
|
+
- The `dry-cli` dependency no longer pins a version range; any release satisfies it.
|
|
6
|
+
- `SPECIFICATION.md` moves to `docs/SPECIFICATION.md`, marked as the specification for 0.1.0, and stays out of the YARD documentation.
|
|
7
|
+
- The README documents which sections each screen prints, how groups and nested commands list, the description column and minimum wrap width, `Help.config`, `Help.reset!`, and the `ArgumentError` a bad setting raises.
|
|
8
|
+
|
|
9
|
+
## [0.2.1] - 2026-09-15
|
|
10
|
+
|
|
3
11
|
- Every setting is made once, in `Dry::CLI::Help.configure`, which now also accepts a block without an argument and runs it against the configuration. The `help` block on registries is removed, along with `Help.config_for` and `Configuration#merge`: the gem adds nothing to dry-cli's registry or command DSL.
|
|
4
12
|
- A `styles` block declares every element's look in one place, replacing `style(element, *names)`. New elements `usage`, `example` and `example_comment`; `comment` is renamed `example_comment` and defaults to bold black.
|
|
5
13
|
- Heading case moves into the heading style: `styles { heading :bold, case: :Capitalize }`, one of `:UPPERCASE`, `:Capitalize`, `:lowercase` or `:as_is`. The `heading_case` setting is removed.
|
|
6
14
|
- `examples/` holds three single-file dry-cli tools that switch this gem on with `--with-dry-cli-help` or `-w`.
|
|
7
15
|
|
|
16
|
+
## [0.2.0] - 2026-09-14
|
|
17
|
+
|
|
18
|
+
- Documentation, justfile, lefthook and packaging fixes after the conversion. No change to behavior.
|
|
19
|
+
|
|
8
20
|
## [0.1.0] - 2026-09-12
|
|
9
21
|
|
|
10
22
|
- Initial release as `dry-cli-help`, converted from `dry-cli-autocomplete`. The shell completion generator is removed; that gem remains the place for it.
|
data/README.md
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
Configurable, wrapped, colored help screens for [dry-cli](https://github.com/dry-rb/dry-cli) applications.
|
|
6
6
|
|
|
7
7
|
> [!NOTE]
|
|
8
|
-
> The design, the settings and
|
|
8
|
+
> The original design, the settings and the decisions behind them are in [docs/SPECIFICATION.md](docs/SPECIFICATION.md), written for version 0.1.0.
|
|
9
9
|
|
|
10
10
|
dry-cli prints help as it finds it: no title, no description of the program, no color, one line per description however long, and commands sorted alphabetically. This gem keeps the command structure you already declared and changes only what the user reads before a command runs. Progress bars, spinners and error panels belong in `dry-cli-ui`.
|
|
11
11
|
|
|
@@ -54,7 +54,7 @@ OPTIONS
|
|
|
54
54
|
|
|
55
55
|
Headings are bold and yellow, commands green, options and arguments cyan, and every description wraps to the terminal with a hanging indent.
|
|
56
56
|
|
|
57
|
-
|
|
57
|
+
The same comparison as screenshots, taken from `examples/rbcheck`:
|
|
58
58
|
|
|
59
59
|
| Standard dry-cli Help Screen | Require `dry/cli/help` |
|
|
60
60
|
| :---------------------------------------------- | :--------------------------------------- |
|
|
@@ -69,6 +69,8 @@ gem install dry-cli-help
|
|
|
69
69
|
|
|
70
70
|
Or add `gem "dry-cli-help"` to your `Gemfile`.
|
|
71
71
|
|
|
72
|
+
It requires Ruby 4.0 or newer, and depends on `dry-cli` and `pastel`.
|
|
73
|
+
|
|
72
74
|
## Usage
|
|
73
75
|
|
|
74
76
|
Require it after dry-cli. That alone changes every help screen in the process.
|
|
@@ -85,7 +87,7 @@ Dry::CLI::Help.configure do
|
|
|
85
87
|
title "MyCLI"
|
|
86
88
|
|
|
87
89
|
description <<~TEXT
|
|
88
|
-
|
|
90
|
+
Compile, validate, and evaluate rules.
|
|
89
91
|
TEXT
|
|
90
92
|
|
|
91
93
|
epilogue "Documentation: https://example.com/my-cli"
|
|
@@ -99,10 +101,10 @@ module My
|
|
|
99
101
|
module CLI
|
|
100
102
|
extend Dry::CLI::Registry
|
|
101
103
|
|
|
102
|
-
register "compile",
|
|
104
|
+
register "compile", Compile
|
|
103
105
|
register "validate", Validate
|
|
104
106
|
register "evaluate", Evaluate
|
|
105
|
-
register "version",
|
|
107
|
+
register "version", Version, aliases: ["--version", "-v"]
|
|
106
108
|
end
|
|
107
109
|
end
|
|
108
110
|
```
|
|
@@ -130,7 +132,7 @@ OPTIONS
|
|
|
130
132
|
Documentation: https://example.com/my-cli
|
|
131
133
|
```
|
|
132
134
|
|
|
133
|
-
A command reachable as `--version` lists under Options by its dashed names.
|
|
135
|
+
A command reachable as `--version` lists under Options by its dashed names. Commands marked `hidden: true` in the registry stay out of every list, and a non-dashed alias prints next to its command, as in `build, b`.
|
|
134
136
|
|
|
135
137
|
A block that takes an argument receives the configuration instead of running against it:
|
|
136
138
|
|
|
@@ -141,6 +143,8 @@ Dry::CLI::Help.configure do |config|
|
|
|
141
143
|
end
|
|
142
144
|
```
|
|
143
145
|
|
|
146
|
+
Every setting validates its value and raises `ArgumentError` on one it cannot use. `Dry::CLI::Help.config` returns the current settings, and `Dry::CLI::Help.reset!` forgets them all, which is handy between tests.
|
|
147
|
+
|
|
144
148
|
## Examples
|
|
145
149
|
|
|
146
150
|
The [`examples`](examples) folder holds three single-file tools built on dry-cli. Each one loads and configures this gem only when you pass `--with-dry-cli-help`, or `-w` for short, so you can run the same command both ways and compare:
|
|
@@ -160,7 +164,7 @@ if [ARGV.delete("--with-dry-cli-help"), ARGV.delete("-w")].any?
|
|
|
160
164
|
require "dry/cli/help"
|
|
161
165
|
|
|
162
166
|
Dry::CLI::Help.configure do
|
|
163
|
-
title "
|
|
167
|
+
title "rbcheck"
|
|
164
168
|
description "Small checks for Ruby projects."
|
|
165
169
|
epilogue "Report bugs at https://example.com/rbcheck/issues"
|
|
166
170
|
end
|
|
@@ -202,7 +206,7 @@ Every screen below comes from running it in an 80-column terminal.
|
|
|
202
206
|
|
|
203
207
|
### `rbcheck -h`
|
|
204
208
|
|
|
205
|
-
dry-cli alone prints a list of commands and exits 1
|
|
209
|
+
dry-cli alone prints a list of commands to stderr and exits 1, and does not wrap the long description.
|
|
206
210
|
|
|
207
211
|
```text
|
|
208
212
|
Commands:
|
|
@@ -210,10 +214,13 @@ Commands:
|
|
|
210
214
|
rbcheck version # Print the version
|
|
211
215
|
```
|
|
212
216
|
|
|
213
|
-
With this gem
|
|
217
|
+
With this gem, `rbcheck -h` prints the help below to stdout and exits 0.
|
|
218
|
+
|
|
219
|
+
> [!NOTE]
|
|
220
|
+
> Whether a CLI run with no arguments should exit 1 or 0 is debatable. dry-cli exits 1, and so does this gem by default: plain `rbcheck` prints the same screen to stderr and exits 1. Set [`exit_code_without_arguments`](#dsl-based-configuration-api) to `0` to treat it like `-h` instead.
|
|
214
221
|
|
|
215
222
|
```text
|
|
216
|
-
|
|
223
|
+
rbcheck
|
|
217
224
|
|
|
218
225
|
Small checks for Ruby projects.
|
|
219
226
|
|
|
@@ -298,11 +305,13 @@ In a terminal the headings print bold yellow, usage lines, commands and examples
|
|
|
298
305
|
|
|
299
306
|
`examples/todo` shows nested commands, custom headings and a `styles` block. `examples/deploy` shows a fixed width, a banner above command help, reordered sections and help without a command exiting 0. [`examples/README.md`](examples/README.md) lists what each one demonstrates.
|
|
300
307
|
|
|
301
|
-
##
|
|
308
|
+
## DSL-based Configuration API
|
|
309
|
+
|
|
310
|
+
The gem offers a compact DSL in the general spirit of Ruby and `dry-rb` in particular, and makes the following methods available within the `configure` block.
|
|
302
311
|
|
|
303
312
|
| Setting | Values | Default | What it does |
|
|
304
313
|
| ----------------------------- | -------------------------------- | --------------- | ------------------------------------------------------------------------------------------------------------------------- |
|
|
305
|
-
| `title` | String | none | Prints
|
|
314
|
+
| `title` | String | none | Prints the first line of the banner, above the top-level help |
|
|
306
315
|
| `description` | String | none | Prints paragraphs under the title, reflowed to the wrap width |
|
|
307
316
|
| `epilogue` | String | none | Prints paragraphs at the very end of the top-level help |
|
|
308
317
|
| `color` | `true`, `false`, `:auto` | `:auto` | Paints headings, commands, arguments and options; `:auto` paints only a terminal |
|
|
@@ -315,7 +324,15 @@ In a terminal the headings print bold yellow, usage lines, commands and examples
|
|
|
315
324
|
|
|
316
325
|
`color :auto` colors a terminal and honors [`NO_COLOR`](https://no-color.org). `width :terminal` reads `COLUMNS`, then the console, then falls back to 80, and `margin` keeps columns free at the right edge.
|
|
317
326
|
|
|
318
|
-
Running the program with no command prints
|
|
327
|
+
Running the program, or a group such as `my-cli db`, with no command prints its help to stderr and exits 1, as dry-cli does. With
|
|
328
|
+
|
|
329
|
+
```ruby
|
|
330
|
+
exit_code_without_arguments 0
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
it prints to stdout and exits 0 instead. `-h` and `--help` always print to stdout and exit 0. A mistyped command prints dry-cli's suggestion, then the help, to stderr and exits 1.
|
|
334
|
+
|
|
335
|
+
The banner (title and description) and the epilogue print on the top-level help. A CLI built from a single command, `Dry::CLI.new(Deploy)`, counts as top level, so its command help gets both.
|
|
319
336
|
|
|
320
337
|
### Headings, sections and groups
|
|
321
338
|
|
|
@@ -331,11 +348,24 @@ Dry::CLI::Help.configure do
|
|
|
331
348
|
end
|
|
332
349
|
```
|
|
333
350
|
|
|
334
|
-
- `heading` replaces one section's heading text. How headings are cased belongs to their style, below.
|
|
335
|
-
- `group` lists commands under a heading of their own, in the order given. Ungrouped commands stay under Commands. A group
|
|
351
|
+
- `heading` replaces one section's heading text. It takes `:usage`, `:description`, `:commands`, `:subcommands`, `:arguments`, `:options` or `:examples`; `banner` and `epilogue` have no heading. How headings are cased belongs to their style, below.
|
|
352
|
+
- `group` lists commands under a heading of their own, in the order given. Ungrouped commands stay under Commands, and groups print below them in the order declared. A group with no commands raises `ArgumentError`; a group whose commands a screen does not list prints no heading there. A nested command is named by its full path, such as `"db migrate"`, and its group shows on `my-cli db -h`.
|
|
336
353
|
- `sections` sets the order; a section left out is hidden. `hide` hides sections without restating the order.
|
|
337
354
|
|
|
338
|
-
The sections are `banner`, `usage`, `description`, `commands`, `subcommands`, `arguments`, `options`, `examples` and `epilogue`. Each screen prints the ones that apply to it
|
|
355
|
+
The sections are `banner`, `usage`, `description`, `commands`, `subcommands`, `arguments`, `options`, `examples` and `epilogue`. Each screen prints the ones that apply to it:
|
|
356
|
+
|
|
357
|
+
| Screen | Sections it can print |
|
|
358
|
+
| --------------------------------------------- | ----------------------------------------------------------------------------------------------- |
|
|
359
|
+
| A listing: `my-cli`, `my-cli -h`, `my-cli db` | `banner`, `usage`, `commands`, `options`, `epilogue` |
|
|
360
|
+
| A command: `my-cli compile -h` | `banner`, `usage`, `description`, `subcommands`, `arguments`, `options`, `examples`, `epilogue` |
|
|
361
|
+
|
|
362
|
+
A few details of those screens:
|
|
363
|
+
|
|
364
|
+
- A command that also has subcommands gets a second usage line, `my-cli db COMMAND [OPTIONS]`, and a Subcommands section.
|
|
365
|
+
- A group registered without a command of its own describes itself by what it holds, as in `Subcommands: add, remove`.
|
|
366
|
+
- An array argument prints as `FILES...`.
|
|
367
|
+
- Every definition list on a screen shares one description column, never wider than half the wrap width. A term longer than that column puts its description on the next line.
|
|
368
|
+
- Text never wraps narrower than 20 columns, however small the terminal.
|
|
339
369
|
|
|
340
370
|
### Styles
|
|
341
371
|
|
|
@@ -386,7 +416,7 @@ class Deploy < Dry::CLI::Command
|
|
|
386
416
|
end
|
|
387
417
|
```
|
|
388
418
|
|
|
389
|
-
The methods are the eight colors `black red green yellow blue magenta cyan white`, their `bright_` forms, the `on_` and `on_bright_` backgrounds, and `clear bold dim italic underline inverse hidden strikethrough`. `Dry::CLI::Help::Colors.enabled
|
|
419
|
+
The methods are the eight colors `black red green yellow blue magenta cyan white`, their `bright_` forms, the `on_` and `on_bright_` backgrounds, and `clear bold dim italic underline inverse hidden strikethrough`. `Dry::CLI::Help::Colors.enabled` takes `true`, `false` or `:auto` (the default, which colors only a terminal and honors `NO_COLOR`). Help screens ignore that switch and follow the `color` setting.
|
|
390
420
|
|
|
391
421
|
## How it works
|
|
392
422
|
|
|
@@ -410,7 +440,7 @@ flowchart TB
|
|
|
410
440
|
command_screen --> formatter["Formatter"]
|
|
411
441
|
listing_screen --> formatter
|
|
412
442
|
|
|
413
|
-
help_config["Help.configure
|
|
443
|
+
help_config["Help.configure"] --> formatter
|
|
414
444
|
|
|
415
445
|
formatter --> output["stdout or stderr"]
|
|
416
446
|
```
|
|
@@ -420,13 +450,16 @@ Both methods are `@api private` in dry-cli. `spec/dry/cli/help/dry_cli_contract_
|
|
|
420
450
|
## Development
|
|
421
451
|
|
|
422
452
|
```bash
|
|
423
|
-
just install
|
|
424
|
-
just test
|
|
425
|
-
just
|
|
426
|
-
just
|
|
427
|
-
just
|
|
428
|
-
just
|
|
429
|
-
|
|
453
|
+
just install # bundle install
|
|
454
|
+
just test # the suite; a full run enforces 100% line and branch coverage
|
|
455
|
+
just test-coverage # measure coverage even for a partial run
|
|
456
|
+
just lint # rubocop
|
|
457
|
+
just ci # rubocop, then the suite with coverage
|
|
458
|
+
just lefthook # every pre-commit hook against every file
|
|
459
|
+
just format # mdformat --wrap no on every Markdown file, then rubocop -a
|
|
460
|
+
just doc # YARD documentation
|
|
461
|
+
just build # build the .gem into pkg/
|
|
462
|
+
bin/console # IRB with the gem loaded
|
|
430
463
|
```
|
|
431
464
|
|
|
432
465
|
## Contributing
|
|
@@ -434,7 +467,21 @@ bin/console # IRB with the gem loaded
|
|
|
434
467
|
Bug reports and pull requests are welcome at <https://github.com/kigster/dry-cli-help>.
|
|
435
468
|
|
|
436
469
|
> [!WARNING]
|
|
437
|
-
> The `dry-` prefix and the `Dry::CLI::Help` namespace do not imply endorsement by dry-rb.
|
|
470
|
+
> The `dry-` prefix and the `Dry::CLI::Help` namespace do not imply endorsement by dry-rb.
|
|
471
|
+
>
|
|
472
|
+
> This is an independent and opinionated gem that extends theirs.
|
|
473
|
+
|
|
474
|
+
## Note to Dry-Rb Maintainers
|
|
475
|
+
|
|
476
|
+
First — hats off to all of you who tirelessly built out one of the most valuable collections of libraries in the Ruby ecosystem.
|
|
477
|
+
|
|
478
|
+
While I admire and would be willing to contribute any or all of the extension gem's code to the original gem, I feel that creating plugins and extensions allows the author to fully express their needs and wants, and then, if the authors of `dry-cli` become interested in any of them, I would be honored to submit a PR to `dry-cli` itself.
|
|
479
|
+
|
|
480
|
+
This method offered a very open road to extensibility and experimentation. If the code quality or design is not up to the level required for direct contributions to `dry-rb`, then let it be known that:
|
|
481
|
+
|
|
482
|
+
1. We would be very happy to receive any feedback and improve, refactor, and update the gem assuming it improves it
|
|
483
|
+
1. Roll any part of the codebase as a PR to the `dry-cli` core.
|
|
484
|
+
1. We hold the authors of `dry-rb` in high regard, and generally would love to collaborate, as long as the feedback loop/cycle is not so long that the context of the changes gets lost in time, as with so many contributions made to other gems in the past.
|
|
438
485
|
|
|
439
486
|
## License
|
|
440
487
|
|
data/Rakefile
CHANGED
|
@@ -28,7 +28,7 @@ end
|
|
|
28
28
|
task build: :permissions
|
|
29
29
|
|
|
30
30
|
YARD::Rake::YardocTask.new(:doc) do |t|
|
|
31
|
-
t.files = %w[lib/**/*.rb - README.md LICENSE.txt CHANGELOG.md
|
|
31
|
+
t.files = %w[lib/**/*.rb - README.md LICENSE.txt CHANGELOG.md]
|
|
32
32
|
t.options.unshift("--title", '"dry-cli-help: configurable help screens for dry-cli"')
|
|
33
33
|
t.after = -> { exec("open doc/index.html") } if RUBY_PLATFORM =~ /darwin/
|
|
34
34
|
end
|
data/lib/dry/cli/help/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: dry-cli-help
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.5.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Konstantin Gredeskoul
|
|
@@ -15,20 +15,14 @@ dependencies:
|
|
|
15
15
|
requirements:
|
|
16
16
|
- - ">="
|
|
17
17
|
- !ruby/object:Gem::Version
|
|
18
|
-
version:
|
|
19
|
-
- - "<"
|
|
20
|
-
- !ruby/object:Gem::Version
|
|
21
|
-
version: '2'
|
|
18
|
+
version: '0'
|
|
22
19
|
type: :runtime
|
|
23
20
|
prerelease: false
|
|
24
21
|
version_requirements: !ruby/object:Gem::Requirement
|
|
25
22
|
requirements:
|
|
26
23
|
- - ">="
|
|
27
24
|
- !ruby/object:Gem::Version
|
|
28
|
-
version:
|
|
29
|
-
- - "<"
|
|
30
|
-
- !ruby/object:Gem::Version
|
|
31
|
-
version: '2'
|
|
25
|
+
version: '0'
|
|
32
26
|
- !ruby/object:Gem::Dependency
|
|
33
27
|
name: pastel
|
|
34
28
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -56,7 +50,6 @@ files:
|
|
|
56
50
|
- LICENSE.txt
|
|
57
51
|
- README.md
|
|
58
52
|
- Rakefile
|
|
59
|
-
- SPECIFICATION.md
|
|
60
53
|
- lib/dry-cli-help.rb
|
|
61
54
|
- lib/dry/cli/help.rb
|
|
62
55
|
- lib/dry/cli/help/colors.rb
|
data/SPECIFICATION.md
DELETED
|
@@ -1,213 +0,0 @@
|
|
|
1
|
-
# dry-cli-help
|
|
2
|
-
|
|
3
|
-
Enhanced help presentation for [`dry-cli`](https://github.com/dry-rb/dry-cli).
|
|
4
|
-
|
|
5
|
-
## Purpose
|
|
6
|
-
|
|
7
|
-
`dry-cli-help` improves the **static, human-facing documentation** generated by `dry-cli`.
|
|
8
|
-
|
|
9
|
-
It does not replace `dry-cli` or introduce another command framework. It takes the command structure already defined through `dry-cli` and provides richer, more configurable help output.
|
|
10
|
-
|
|
11
|
-
## Responsibilities
|
|
12
|
-
|
|
13
|
-
- Top-level application title and description
|
|
14
|
-
- Command descriptions
|
|
15
|
-
- Automatic line wrapping based on terminal width
|
|
16
|
-
- ANSI color and styling
|
|
17
|
-
- Configurable headings
|
|
18
|
-
- Improved spacing and indentation
|
|
19
|
-
- Usage formatting
|
|
20
|
-
- Arguments and options formatting
|
|
21
|
-
- Examples
|
|
22
|
-
- Epilogues
|
|
23
|
-
- Command grouping
|
|
24
|
-
- Section ordering
|
|
25
|
-
- Hiding or customizing sections
|
|
26
|
-
- Consistent formatting across commands
|
|
27
|
-
|
|
28
|
-
## Example
|
|
29
|
-
|
|
30
|
-
Every setting is made once, in one block, before any CLI runs. The registry, its commands and their options stay exactly as dry-cli declares them:
|
|
31
|
-
|
|
32
|
-
```ruby
|
|
33
|
-
require "dry/cli"
|
|
34
|
-
require "dry/cli/help"
|
|
35
|
-
|
|
36
|
-
Dry::CLI::Help.configure do
|
|
37
|
-
title "MyCLI"
|
|
38
|
-
|
|
39
|
-
description <<~TEXT
|
|
40
|
-
Compile, validate, and evaluate tax rules.
|
|
41
|
-
TEXT
|
|
42
|
-
|
|
43
|
-
color :auto
|
|
44
|
-
width :terminal
|
|
45
|
-
|
|
46
|
-
styles do
|
|
47
|
-
heading :bold, :yellow, case: :UPPERCASE
|
|
48
|
-
example_comment :bold, :black
|
|
49
|
-
end
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
module CLI
|
|
53
|
-
extend Dry::CLI::Registry # plain dry-cli, nothing added
|
|
54
|
-
|
|
55
|
-
register "compile", Compile
|
|
56
|
-
register "validate", Validate
|
|
57
|
-
register "evaluate", Evaluate
|
|
58
|
-
end
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
Result:
|
|
62
|
-
|
|
63
|
-
```text
|
|
64
|
-
MyCLI
|
|
65
|
-
|
|
66
|
-
Compile, validate, and evaluate tax rules.
|
|
67
|
-
|
|
68
|
-
USAGE
|
|
69
|
-
my-cli COMMAND [OPTIONS]
|
|
70
|
-
|
|
71
|
-
COMMANDS
|
|
72
|
-
compile Compile tax rules
|
|
73
|
-
validate Validate the rule corpus
|
|
74
|
-
evaluate Evaluate a tax return
|
|
75
|
-
|
|
76
|
-
OPTIONS
|
|
77
|
-
--help Show help
|
|
78
|
-
--version Show version
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
## Design Principle
|
|
82
|
-
|
|
83
|
-
`dry-cli-help` owns what the user sees **before a command runs**.
|
|
84
|
-
|
|
85
|
-
It should remain focused on documentation and presentation rather than runtime command UI.
|
|
86
|
-
|
|
87
|
-
Runtime features such as progress bars, spinners, status displays, and error panels belong in `dry-cli-ui`.
|
|
88
|
-
|
|
89
|
-
## Relationship
|
|
90
|
-
|
|
91
|
-
```text
|
|
92
|
-
dry-cli
|
|
93
|
-
│
|
|
94
|
-
└── dry-cli-help
|
|
95
|
-
│
|
|
96
|
-
├── descriptions
|
|
97
|
-
├── usage
|
|
98
|
-
├── wrapping
|
|
99
|
-
├── headings
|
|
100
|
-
├── colors
|
|
101
|
-
├── arguments/options
|
|
102
|
-
└── examples
|
|
103
|
-
```
|
|
104
|
-
|
|
105
|
-
## Requirements carried from the first draft
|
|
106
|
-
|
|
107
|
-
1. **Exit status without arguments.** dry-cli prints the command list and exits 1 when run with no command. The status is configurable. Asking for help with `-h` or `--help` always exits 0.
|
|
108
|
-
1. **Banner.** The title and description print above the command list for `mycli`, `mycli -h` and `mycli --help`. A separate setting decides whether they also print for `mycli subcommand -h`.
|
|
109
|
-
1. **Wrapping.** Three modes: no wrapping (dry-cli's behavior), wrapping at a fixed column such as 80 or 100, and wrapping at the terminal's width minus an optional margin.
|
|
110
|
-
1. **Colors.** Built on `pastel`. A `Colors` module, when included, makes each style below available as a method: `red("text")` returns decorated text, and `red.bold("text")` chains.
|
|
111
|
-
- Foreground: `black`, `red`, `green`, `yellow`, `blue`, `magenta`, `cyan`, `white`, and the `bright_` form of each.
|
|
112
|
-
- Background: `on_black`, `on_red`, `on_green`, `on_yellow`, `on_blue`, `on_magenta`, `on_cyan`, `on_white`, and the `on_bright_` form of each.
|
|
113
|
-
- Styles: `clear`, `bold`, `dim`, `italic`, `underline`, `inverse`, `hidden`, `strikethrough`.
|
|
114
|
-
|
|
115
|
-
## Decisions
|
|
116
|
-
|
|
117
|
-
### Integration
|
|
118
|
-
|
|
119
|
-
Requiring `dry/cli/help` changes help output for every `Dry::CLI` in the process. It does not replace `Dry::CLI::Banner` or `Dry::CLI::Usage`. It prepends one module to `Dry::CLI` that overrides two private methods, the only two places dry-cli prints help:
|
|
120
|
-
|
|
121
|
-
| dry-cli method | When dry-cli calls it |
|
|
122
|
-
| -------------------------------------- | ---------------------------------------------------------- |
|
|
123
|
-
| `Dry::CLI#help(command, prog_name)` | `mycli deploy -h`, for any command with a class |
|
|
124
|
-
| `Dry::CLI#spell_checker(result, argv)` | `mycli`, `mycli -h`, `mycli db` for a group, `mycli bogus` |
|
|
125
|
-
|
|
126
|
-
Both are `@api private` in dry-cli 1.4.1. A spec asserts they exist, so a dry-cli release that renames them fails this gem's suite rather than a host's help screen. `Dry::CLI::Help::Integration` holds the override.
|
|
127
|
-
|
|
128
|
-
The gem adds nothing to `Dry::CLI::Registry` or `Dry::CLI::Command`. The DSL a host uses to declare commands, arguments, options and examples is dry-cli's, unchanged, so adding or removing this gem never touches a command definition.
|
|
129
|
-
|
|
130
|
-
### Configuration
|
|
131
|
-
|
|
132
|
-
One place. `Dry::CLI::Help.configure` holds every setting for the process, and every CLI in the process renders with it. A setting it leaves alone takes the default below.
|
|
133
|
-
|
|
134
|
-
The block reads and writes both ways: `title "MyCLI"` when the block takes no argument and runs against the configuration, and `config.title = "MyCLI"` when it takes one and receives it.
|
|
135
|
-
|
|
136
|
-
| Setting | Values | Default | Effect |
|
|
137
|
-
| ----------------------------- | -------------------------------- | --------------- | ------------------------------------------------------------------ |
|
|
138
|
-
| `title` | String | none | First line of the banner |
|
|
139
|
-
| `description` | String | none | Paragraphs under the title, wrapped |
|
|
140
|
-
| `epilogue` | String | none | Paragraphs at the end of the top-level help |
|
|
141
|
-
| `color` | `true`, `false`, `:auto` | `:auto` | `:auto` colors a terminal and honors `NO_COLOR` |
|
|
142
|
-
| `wrap` | `true`, `false` | `true` | `false` prints descriptions as written |
|
|
143
|
-
| `width` | `:terminal`, Integer | `:terminal` | The column text wraps at |
|
|
144
|
-
| `margin` | Integer | `0` | Columns kept free at the right edge when `width` is `:terminal` |
|
|
145
|
-
| `exit_code_without_arguments` | Integer, 0 to 255 | `1` | Status for `mycli` or `mycli group` with no command |
|
|
146
|
-
| `banner_on_subcommands` | `true`, `false` | `false` | Print the title and description above `mycli command -h` |
|
|
147
|
-
| `command_order` | `:registration`, `:alphabetical` | `:registration` | Order commands list in; dry-cli sorts alphabetically |
|
|
148
|
-
| `heading(section, text)` | Section name, String | see below | Replaces one heading's text |
|
|
149
|
-
| `styles { ... }` | One line per element | see below | Declares how every element looks, and how headings are cased |
|
|
150
|
-
| `group(name, *commands)` | String, command paths | none | Lists those commands under their own heading, in declaration order |
|
|
151
|
-
| `sections(*names)` | Section names | all | Order of sections; a section left out is hidden |
|
|
152
|
-
| `hide(*names)` | Section names | none | Hides sections without restating the order |
|
|
153
|
-
|
|
154
|
-
Terminal width comes from `COLUMNS`, then the console, then 80. A resolved wrap width never falls below 20 columns.
|
|
155
|
-
|
|
156
|
-
### Sections
|
|
157
|
-
|
|
158
|
-
In default order, with default headings:
|
|
159
|
-
|
|
160
|
-
| Section | Heading | Top-level help | Command help |
|
|
161
|
-
| ------------- | ----------- | -------------- | ----------------------------------- |
|
|
162
|
-
| `banner` | none | yes | when `banner_on_subcommands` is set |
|
|
163
|
-
| `usage` | Usage | yes | yes |
|
|
164
|
-
| `description` | Description | no | yes |
|
|
165
|
-
| `commands` | Commands | yes | no |
|
|
166
|
-
| `subcommands` | Subcommands | no | when the command has children |
|
|
167
|
-
| `arguments` | Arguments | no | yes |
|
|
168
|
-
| `options` | Options | yes | yes |
|
|
169
|
-
| `examples` | Examples | no | yes |
|
|
170
|
-
| `epilogue` | none | yes | only for a single command |
|
|
171
|
-
|
|
172
|
-
A single command passed to `Dry::CLI.new(SomeCommand)` is the whole program, so its command help prints the banner and the epilogue too.
|
|
173
|
-
|
|
174
|
-
A group listing, `mycli db` where `db` has no command of its own, renders as top-level help scoped to the group, with the banner only when `banner_on_subcommands` is set, and no epilogue.
|
|
175
|
-
|
|
176
|
-
Every Options section starts with `-h, --help Show help`, because both spellings work at every level. The example above shows `--help` alone; `spec/dry/cli/help/integration_spec.rb` holds the exact output.
|
|
177
|
-
|
|
178
|
-
At any level, a command registered under a name or alias starting with `-`, such as `register "version", Version, aliases: ["--version"]`, lists under Options rather than Commands.
|
|
179
|
-
|
|
180
|
-
### Styles
|
|
181
|
-
|
|
182
|
-
Every element's look is declared in one `styles` block inside `configure`. Each line names an element and its styles, from `Colors::STYLES`. An element left out keeps its default; a line with no styles prints the element plain.
|
|
183
|
-
|
|
184
|
-
```ruby
|
|
185
|
-
styles do
|
|
186
|
-
heading :bold, :blue, case: :Capitalize
|
|
187
|
-
example :yellow
|
|
188
|
-
example_comment # plain
|
|
189
|
-
end
|
|
190
|
-
```
|
|
191
|
-
|
|
192
|
-
| Element | Default styles | Applies to |
|
|
193
|
-
| ----------------- | ---------------- | ------------------------------------------ |
|
|
194
|
-
| `title` | `bold` | The banner title |
|
|
195
|
-
| `heading` | `bold`, `yellow` | Every section and group heading |
|
|
196
|
-
| `usage` | `green` | Every usage line, whole |
|
|
197
|
-
| `command` | `green` | Command names in a list |
|
|
198
|
-
| `argument` | `cyan` | Argument names |
|
|
199
|
-
| `option` | `cyan` | Option names |
|
|
200
|
-
| `example` | `green` | The command line of an example |
|
|
201
|
-
| `example_comment` | `bold`, `black` | The part of an example after the first `#` |
|
|
202
|
-
|
|
203
|
-
`heading` alone takes `case:`, one of `:UPPERCASE` (the default), `:Capitalize`, `:lowercase` or `:as_is`, each written the way it cases. It applies to every heading. `:Capitalize` raises only the first letter and leaves the rest as written. `heading case: :as_is` with no styles changes the case and keeps the heading's styles.
|
|
204
|
-
|
|
205
|
-
### Layout
|
|
206
|
-
|
|
207
|
-
- Every section after the first starts after one blank line. Section bodies indent two columns.
|
|
208
|
-
- A definition list (commands, arguments, options) aligns its descriptions in one column across the whole screen, two columns past the longest term that has a description. The column never passes half the wrap width, and a term longer than the column puts its description on the next line.
|
|
209
|
-
- Examples align among themselves. A full command line is longer than any option, and sharing its column would push every other description to the right.
|
|
210
|
-
- A group registered without a command has no description of its own, so it lists as `Subcommands: a, b`.
|
|
211
|
-
- An argument or option description ends with what a reader needs to supply it: `(required; one of: json, yaml; default: "json")`. An array argument reads `NAME...`.
|
|
212
|
-
- Descriptions wrap with a hanging indent under the description column. Paragraphs split on blank lines and reflow; a line starting with whitespace prints verbatim.
|
|
213
|
-
- An example written `"prod # ship to production"` renders the part after the first `#` surrounded by spaces as its description.
|