@thi.ng/args 2.10.0 → 2.10.2
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.
- package/CHANGELOG.md +1 -1
- package/README.md +252 -27
- package/cli.js +1 -1
- package/package.json +4 -4
package/CHANGELOG.md
CHANGED
package/README.md
CHANGED
|
@@ -15,22 +15,29 @@
|
|
|
15
15
|
> GitHub](https://github.com/sponsors/postspectacular). Thank you! ❤️
|
|
16
16
|
|
|
17
17
|
- [About](#about)
|
|
18
|
+
- [Built-in argument types](#built-in-argument-types)
|
|
19
|
+
- [Re-usable argument presets](#re-usable-argument-presets)
|
|
20
|
+
- [CLI app framework](#cli-app-framework)
|
|
18
21
|
- [Status](#status)
|
|
19
22
|
- [Installation](#installation)
|
|
20
23
|
- [Dependencies](#dependencies)
|
|
21
24
|
- [Projects using this package](#projects-using-this-package)
|
|
22
25
|
- [API](#api)
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
+
- [Basic usage](#basic-usage)
|
|
27
|
+
- [Generate & display help](#generate--display-help)
|
|
28
|
+
- [Parsing, value coercions & side effects](#parsing-value-coercions--side-effects)
|
|
29
|
+
- [Declarative, multi-command CLI application](#declarative-multi-command-cli-application)
|
|
26
30
|
- [Authors](#authors)
|
|
27
31
|
- [License](#license)
|
|
28
32
|
|
|
29
33
|
## About
|
|
30
34
|
|
|
31
|
-
Declarative, functional CLI argument/options parser, value coercions, sub-commands etc..
|
|
35
|
+
Declarative, functional CLI argument/options parser, app framework, arg value coercions, multi/sub-commands, usage generation, error handling etc..
|
|
32
36
|
|
|
33
|
-
|
|
37
|
+
### Built-in argument types
|
|
38
|
+
|
|
39
|
+
The parser includes built-in support for the following argument types (of course
|
|
40
|
+
custom arg types are supported too):
|
|
34
41
|
|
|
35
42
|
| **Argument type** | **Multiple** | **Example** | **Result** |
|
|
36
43
|
|----------------------|--------------|----------------------------|-----------------------------------|
|
|
@@ -45,8 +52,44 @@ Includes built-in support for the following argument types (of course custom arg
|
|
|
45
52
|
|
|
46
53
|
If multiple values/repetitions are allowed for an argument, the values will be
|
|
47
54
|
collected into an array (apart from KV pairs, which will yield an object).
|
|
48
|
-
Furthermore, for multi-args, an optional delimiter can be specified
|
|
49
|
-
individual values, e.g. `-a 1,2,3` equals `-a 1 -a 2 -a 3`
|
|
55
|
+
Furthermore, for multi-args and tuples, an optional delimiter can be specified
|
|
56
|
+
to extract individual values, e.g. `-a 1,2,3` equals `-a 1 -a 2 -a 3`
|
|
57
|
+
|
|
58
|
+
### Re-usable argument presets
|
|
59
|
+
|
|
60
|
+
The following commonly used arguments are available as predefined presets:
|
|
61
|
+
|
|
62
|
+
- [`ARG_DRY_RUN`](https://docs.thi.ng/umbrella/args/variables/ARG_DRY_RUN.html)
|
|
63
|
+
- [`ARG_QUIET`](https://docs.thi.ng/umbrella/args/variables/ARG_QUIET.html)
|
|
64
|
+
- [`ARG_VERBOSE`](https://docs.thi.ng/umbrella/args/variables/ARG_VERBOSE.html)
|
|
65
|
+
|
|
66
|
+
Higher order, configurable preset specs:
|
|
67
|
+
|
|
68
|
+
- [`ARG_OUT_DIR`](https://docs.thi.ng/umbrella/args/functions/ARG_OUT_DIR.html)
|
|
69
|
+
- [`ARG_OUT_FILE`](https://docs.thi.ng/umbrella/args/functions/ARG_OUT_FILE.html)
|
|
70
|
+
|
|
71
|
+
To use these presets, simply import and splice them into your own arg
|
|
72
|
+
definitions (see code examples below).
|
|
73
|
+
|
|
74
|
+
### CLI app framework
|
|
75
|
+
|
|
76
|
+
The package provides a simple framework to conveniently define single and
|
|
77
|
+
multi-command applications in a declarative and modular manner. Such apps are
|
|
78
|
+
defined via command specs and other configuration options. The framework then
|
|
79
|
+
handles all argument parsing, validation, usage display and delegation to
|
|
80
|
+
sub-commands.
|
|
81
|
+
|
|
82
|
+
The wrapper defines a user-customizable [command
|
|
83
|
+
context](https://docs.thi.ng/umbrella/args/interfaces/CommandCtx.html) with all
|
|
84
|
+
important information which is passed to the commands and also includes a logger
|
|
85
|
+
(writing to `stderr`). Other help/usage and error output also respects the
|
|
86
|
+
[`NO_COLOR` convention](https://no-color.org/).
|
|
87
|
+
|
|
88
|
+
A [fully documented code example](#declarative-multi-command-cli-application) is
|
|
89
|
+
further below.
|
|
90
|
+
|
|
91
|
+
For some _publicly available_ production uses, please see the [related packages
|
|
92
|
+
section](#projects-using-this-package) in this readme.
|
|
50
93
|
|
|
51
94
|
## Status
|
|
52
95
|
|
|
@@ -72,7 +115,7 @@ For Node.js REPL:
|
|
|
72
115
|
const args = await import("@thi.ng/args");
|
|
73
116
|
```
|
|
74
117
|
|
|
75
|
-
Package sizes (brotli'd, pre-treeshake): ESM: 3.
|
|
118
|
+
Package sizes (brotli'd, pre-treeshake): ESM: 3.31 KB
|
|
76
119
|
|
|
77
120
|
## Dependencies
|
|
78
121
|
|
|
@@ -97,15 +140,17 @@ Note: @thi.ng/api is in _most_ cases a type-only import (not used at runtime)
|
|
|
97
140
|
tangling / codegen utility, inspired by org-mode & noweb
|
|
98
141
|
- [@thi.ng/wasm-api-bindgen](https://thi.ng/wasm-api-bindgen): Polyglot bindings
|
|
99
142
|
code generators (TS/JS, Zig, C11) for hybrid WebAssembly projects
|
|
143
|
+
- [thing-tools](https://codeberg.org/thi.ng/thing-tools)
|
|
100
144
|
|
|
101
145
|
## API
|
|
102
146
|
|
|
103
147
|
[Generated API docs](https://docs.thi.ng/umbrella/args/)
|
|
104
148
|
|
|
105
|
-
|
|
149
|
+
## Basic usage
|
|
106
150
|
|
|
107
151
|
```ts tangle:export/readme.ts
|
|
108
152
|
import {
|
|
153
|
+
ARG_VERBOSE,
|
|
109
154
|
flag,
|
|
110
155
|
hex,
|
|
111
156
|
json,
|
|
@@ -132,10 +177,14 @@ interface TestArgs {
|
|
|
132
177
|
pos?: Tuple<number>;
|
|
133
178
|
xtra?: { a: number; b: string };
|
|
134
179
|
define?: KVDict;
|
|
180
|
+
verbose: boolean;
|
|
135
181
|
}
|
|
136
182
|
|
|
137
183
|
// arg specifications
|
|
138
184
|
const specs: Args<TestArgs> = {
|
|
185
|
+
// re-use predefined preset (see readme section above)
|
|
186
|
+
...ARG_VERBOSE,
|
|
187
|
+
|
|
139
188
|
// string arg
|
|
140
189
|
configPath: string({
|
|
141
190
|
alias: "c",
|
|
@@ -223,6 +272,7 @@ illegal argument(s): missing arg: --type
|
|
|
223
272
|
Flags:
|
|
224
273
|
|
|
225
274
|
-f, --force Force operation
|
|
275
|
+
-v, --verbose Display extra information
|
|
226
276
|
|
|
227
277
|
Main:
|
|
228
278
|
|
|
@@ -240,7 +290,7 @@ Extra:
|
|
|
240
290
|
-x JSON, --xtra JSON Extra options
|
|
241
291
|
```
|
|
242
292
|
|
|
243
|
-
|
|
293
|
+
### Generate & display help
|
|
244
294
|
|
|
245
295
|
Usage information can be generated via `usage()` and is automatically triggered
|
|
246
296
|
via the special `--help` option (configurable, see
|
|
@@ -256,23 +306,7 @@ By default, ANSI colors are used to format the result string of `usage()`, but
|
|
|
256
306
|
can be disabled (see
|
|
257
307
|
[`UsageOpts`](https://docs.thi.ng/umbrella/args/interfaces/UsageOpts.html)).
|
|
258
308
|
|
|
259
|
-
|
|
260
|
-
bun index.ts --help
|
|
261
|
-
|
|
262
|
-
-f, --force Force operation
|
|
263
|
-
|
|
264
|
-
--bg HEX Background color
|
|
265
|
-
-c PATH, --config-path PATH Config file path (CLI args always take
|
|
266
|
-
precedence over those settings)
|
|
267
|
-
-D key=val, --define key=val [multiple] Define dict entry
|
|
268
|
-
--pos N,N Lat/Lon
|
|
269
|
-
--size WxH Target size
|
|
270
|
-
-t ID, --type ID [required] Image type: 'png', 'jpg', 'gif',
|
|
271
|
-
'tiff'
|
|
272
|
-
-x JSON, --xtra JSON Extra options
|
|
273
|
-
```
|
|
274
|
-
|
|
275
|
-
#### Parsing, value coercions & side effects
|
|
309
|
+
### Parsing, value coercions & side effects
|
|
276
310
|
|
|
277
311
|
The below invocation demonstrates how the various argument types are handled &
|
|
278
312
|
represented in the result. Parsing stops with the first non-argument value (here
|
|
@@ -295,6 +329,7 @@ bun index.ts \
|
|
|
295
329
|
# size: Tuple { value: [640, 480] }
|
|
296
330
|
# define: { author: 'toxi', date: '2018-03-24' },
|
|
297
331
|
# xtra: { foo: [23] },
|
|
332
|
+
# verbose: false,
|
|
298
333
|
# },
|
|
299
334
|
# index: 15,
|
|
300
335
|
# rest: [ 'sourcefile.png' ],
|
|
@@ -302,6 +337,196 @@ bun index.ts \
|
|
|
302
337
|
# }
|
|
303
338
|
```
|
|
304
339
|
|
|
340
|
+
## Declarative, multi-command CLI application
|
|
341
|
+
|
|
342
|
+
The following example defines a CLI app with two sub-commands: `hello` and
|
|
343
|
+
`list`. Each command has its own options, in addition to common/shared ones.
|
|
344
|
+
Each command is defined in a modular manner (usually in its own source file).
|
|
345
|
+
All aspects like arg parsing, validation, and command selection/delegation is
|
|
346
|
+
handled by the `cliApp()` wrapper.
|
|
347
|
+
|
|
348
|
+
```ts tangle:export/readme-cliapp.ts
|
|
349
|
+
import {
|
|
350
|
+
ARG_VERBOSE,
|
|
351
|
+
cliApp,
|
|
352
|
+
configureLogLevel,
|
|
353
|
+
int,
|
|
354
|
+
string,
|
|
355
|
+
type Command,
|
|
356
|
+
type CommandCtx,
|
|
357
|
+
} from "@thi.ng/args";
|
|
358
|
+
import { files } from "@thi.ng/file-io";
|
|
359
|
+
|
|
360
|
+
// common command opts
|
|
361
|
+
interface CommonOpts {
|
|
362
|
+
verbose: boolean;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
// custom command context
|
|
366
|
+
interface AppCtx<T extends CommonOpts> extends CommandCtx<T, CommonOpts> {
|
|
367
|
+
// plus any custom additions here...
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
// command-specific options
|
|
371
|
+
interface HelloOpts extends CommonOpts {
|
|
372
|
+
name: string;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
// command definition
|
|
376
|
+
const HELLO: Command<HelloOpts, CommonOpts> = {
|
|
377
|
+
// brief description (for `--help` usage)
|
|
378
|
+
desc: "Print out a greeting",
|
|
379
|
+
// command specific options (arguments)
|
|
380
|
+
// (will be combined with common opts)
|
|
381
|
+
opts: {
|
|
382
|
+
name: string({
|
|
383
|
+
alias: "n",
|
|
384
|
+
desc: "Name for greeting",
|
|
385
|
+
optional: false,
|
|
386
|
+
}),
|
|
387
|
+
},
|
|
388
|
+
// this command does not accept any inputs
|
|
389
|
+
inputs: 0,
|
|
390
|
+
// command implementation
|
|
391
|
+
fn: async (ctx) => {
|
|
392
|
+
// log message only shown if `--verbose`/`-v` given
|
|
393
|
+
ctx.logger.debug("opts", ctx.opts);
|
|
394
|
+
console.log(`Hello, ${ctx.opts.name}!`);
|
|
395
|
+
},
|
|
396
|
+
};
|
|
397
|
+
|
|
398
|
+
// command-specific options
|
|
399
|
+
interface ListFilesOpts extends CommonOpts {
|
|
400
|
+
depth: number;
|
|
401
|
+
filter?: string;
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
// command definition
|
|
405
|
+
const LIST_FILES: Command<ListFilesOpts, CommonOpts> = {
|
|
406
|
+
// brief description (for `--help` usage)
|
|
407
|
+
desc: "List files in given dir",
|
|
408
|
+
// command specific options
|
|
409
|
+
opts: {
|
|
410
|
+
filter: string({
|
|
411
|
+
alias: "f",
|
|
412
|
+
desc: "Filter regexp",
|
|
413
|
+
}),
|
|
414
|
+
depth: int({
|
|
415
|
+
alias: "d",
|
|
416
|
+
desc: "Recursion depth (directory levels)",
|
|
417
|
+
default: Infinity,
|
|
418
|
+
}),
|
|
419
|
+
},
|
|
420
|
+
// this command requires exactly 1 input
|
|
421
|
+
// (if supporting a range, use `[min, max]`)
|
|
422
|
+
inputs: 1,
|
|
423
|
+
// command implementation
|
|
424
|
+
fn: async (ctx) => {
|
|
425
|
+
for (let f of files(ctx.inputs[0], ctx.opts.filter, ctx.opts.depth)) {
|
|
426
|
+
console.log(f);
|
|
427
|
+
}
|
|
428
|
+
},
|
|
429
|
+
};
|
|
430
|
+
|
|
431
|
+
// define & start CLI app
|
|
432
|
+
cliApp<CommonOpts, AppCtx<any>>({
|
|
433
|
+
// app name
|
|
434
|
+
name: "example",
|
|
435
|
+
// process.argv index from which to start parsing from
|
|
436
|
+
start: 2,
|
|
437
|
+
// list common command opts here
|
|
438
|
+
opts: {
|
|
439
|
+
// re-use verbose flag arg spec preset
|
|
440
|
+
...ARG_VERBOSE,
|
|
441
|
+
},
|
|
442
|
+
// list of commands
|
|
443
|
+
commands: {
|
|
444
|
+
hello: HELLO,
|
|
445
|
+
list: LIST_FILES,
|
|
446
|
+
},
|
|
447
|
+
// set to true if only a single command
|
|
448
|
+
// in this case the command name would NOT be required/expected
|
|
449
|
+
// single: true,
|
|
450
|
+
|
|
451
|
+
// usage opts
|
|
452
|
+
usage: {
|
|
453
|
+
// prefix/header string
|
|
454
|
+
prefix: `Example app
|
|
455
|
+
===================================
|
|
456
|
+
Usage: example [opts] [inputs]\n`,
|
|
457
|
+
// configure column width for param usage info
|
|
458
|
+
paramWidth: 24,
|
|
459
|
+
lineWidth: 80,
|
|
460
|
+
},
|
|
461
|
+
|
|
462
|
+
// context initialization/augmentation
|
|
463
|
+
// (called before arg parsing commences)
|
|
464
|
+
ctx: async (ctx) => {
|
|
465
|
+
configureLogLevel(ctx.logger, ctx.opts.verbose);
|
|
466
|
+
return ctx;
|
|
467
|
+
},
|
|
468
|
+
});
|
|
469
|
+
```
|
|
470
|
+
|
|
471
|
+
Example usage (here using `bun` to launch the above CLI app, though the usage
|
|
472
|
+
info is written to assume an `example` launcher/wrapper):
|
|
473
|
+
|
|
474
|
+
```bash
|
|
475
|
+
bun readme-cliapp.ts
|
|
476
|
+
|
|
477
|
+
# Example app
|
|
478
|
+
# ===================================
|
|
479
|
+
# Usage: example [opts] [inputs]
|
|
480
|
+
#
|
|
481
|
+
# Available commands:
|
|
482
|
+
#
|
|
483
|
+
# hello : Print out a greeting
|
|
484
|
+
# list : List files in given dir
|
|
485
|
+
#
|
|
486
|
+
# -v, --verbose Display extra information
|
|
487
|
+
```
|
|
488
|
+
|
|
489
|
+
```bash
|
|
490
|
+
# displaying help for a sub-command
|
|
491
|
+
bun readme-cliapp.ts hello --help
|
|
492
|
+
|
|
493
|
+
# Example app
|
|
494
|
+
# ===================================
|
|
495
|
+
# Usage: example [opts] [inputs]
|
|
496
|
+
#
|
|
497
|
+
# Current command:
|
|
498
|
+
#
|
|
499
|
+
# hello : Print out a greeting
|
|
500
|
+
#
|
|
501
|
+
# -v, --verbose Display extra information
|
|
502
|
+
#
|
|
503
|
+
# -n STR, --name STR [required] Name for greeting
|
|
504
|
+
```
|
|
505
|
+
|
|
506
|
+
```bash
|
|
507
|
+
# invoking `hello` sub-command (with verbose flag)
|
|
508
|
+
bun readme-cliapp.ts hello --name thi.ng -v
|
|
509
|
+
# [DEBUG] example: opts {"name":"thi.ng","verbose":true}
|
|
510
|
+
# Hello, thi.ng!
|
|
511
|
+
```
|
|
512
|
+
|
|
513
|
+
```bash
|
|
514
|
+
# invoking `list` sub-command
|
|
515
|
+
bun readme-cliapp.ts list -d 2 -f '.js' .
|
|
516
|
+
# ./dev/api.js
|
|
517
|
+
# ./dev/runtime.js
|
|
518
|
+
# ./dev/test/main.js
|
|
519
|
+
# ./index.js
|
|
520
|
+
```
|
|
521
|
+
|
|
522
|
+
```bash
|
|
523
|
+
# missing arg error
|
|
524
|
+
bun readme-cliapp.ts hello
|
|
525
|
+
# illegal argument(s): missing arg: --name
|
|
526
|
+
#
|
|
527
|
+
# (...additional usage output omitted for brevity)
|
|
528
|
+
```
|
|
529
|
+
|
|
305
530
|
## Authors
|
|
306
531
|
|
|
307
532
|
- [Karsten Schmidt](https://thi.ng)
|
package/cli.js
CHANGED
|
@@ -60,7 +60,7 @@ const cliApp = async (config) => {
|
|
|
60
60
|
if (isArray(cmd.inputs)) {
|
|
61
61
|
const [min, max] = cmd.inputs;
|
|
62
62
|
if (num < min || num > max) {
|
|
63
|
-
err = max < Infinity ? `expected ${min}-${max} inputs` : `expected at least ${min}
|
|
63
|
+
err = max < Infinity ? `expected ${min}-${max} inputs` : `expected at least ${min} input(s)`;
|
|
64
64
|
}
|
|
65
65
|
} else if (num !== cmd.inputs) {
|
|
66
66
|
err = `expected ${cmd.inputs} input(s)`;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@thi.ng/args",
|
|
3
|
-
"version": "2.10.
|
|
4
|
-
"description": "Declarative, functional CLI argument/options parser, value coercions, sub-commands etc.",
|
|
3
|
+
"version": "2.10.2",
|
|
4
|
+
"description": "Declarative, functional CLI argument/options parser, app framework, arg value coercions, multi/sub-commands, usage generation, error handling etc.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"module": "./index.js",
|
|
7
7
|
"typings": "./index.d.ts",
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
"@thi.ng/api": "^8.12.2",
|
|
43
43
|
"@thi.ng/checks": "^3.7.18",
|
|
44
44
|
"@thi.ng/errors": "^2.5.42",
|
|
45
|
-
"@thi.ng/logger": "^3.
|
|
45
|
+
"@thi.ng/logger": "^3.2.0",
|
|
46
46
|
"@thi.ng/strings": "^3.9.22",
|
|
47
47
|
"@thi.ng/text-format": "^2.2.41"
|
|
48
48
|
},
|
|
@@ -110,5 +110,5 @@
|
|
|
110
110
|
"tag": "cli",
|
|
111
111
|
"year": 2018
|
|
112
112
|
},
|
|
113
|
-
"gitHead": "
|
|
113
|
+
"gitHead": "3c3531350eec56011982583c694aeb1a2e0d0ff4\n"
|
|
114
114
|
}
|