Skip to content

Commit ae0783f

Browse files
committed
feat: [Command] apply implied options
Signed-off-by: Lexus Drumgold <[email protected]>
1 parent 6e933f0 commit ae0783f

26 files changed

+915
-156
lines changed

README.md

Lines changed: 92 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,8 @@
127127
- [`Parseable#variadic`](#parseablevariadic)
128128
- [`VersionOption(info)`](#versionoptioninfo)
129129
- [`VersionOption#version`](#versionoptionversion)
130+
- [`keid`](#keid)
131+
- [`optionValueSource`](#optionvaluesource)
130132
- [Types](#types)
131133
- [`Action`](#action)
132134
- [`ArgumentData`](#argumentdata)
@@ -170,16 +172,18 @@
170172
- [`OptionMetadata`](#optionmetadata)
171173
- [`OptionPriority`](#optionpriority)
172174
- [`OptionValueSourceMap`](#optionvaluesourcemap)
173-
- [`OptionValueSource`](#optionvaluesource)
175+
- [`OptionValueSource`](#optionvaluesource-1)
174176
- [`OptionValueSources`](#optionvaluesources)
175177
- [`OptionsData`](#optionsdata)
176178
- [`ParseArg`](#parsearg)
177179
- [`ParseOptions`](#parseoptions)
180+
- [`ParseUnknownResult`](#parseunknownresult)
178181
- [`ParseableInfo`](#parseableinfo-1)
179182
- [`ParseableMetadata`](#parseablemetadata)
180183
- [`ProcessEnv`](#processenv)
181184
- [`Process`](#process)
182185
- [`RawOptionValue`](#rawoptionvalue)
186+
- [`RawParseValue`](#rawparsevalue)
183187
- [`SubcommandInfo`](#subcommandinfo)
184188
- [`SubcommandsData`](#subcommandsdata)
185189
- [`SubcommandsInfo`](#subcommandsinfo)
@@ -703,7 +707,7 @@ Emit a parsed `option` event.
703707
— the command option instance
704708
- `value` ([`RawOptionValue`](#rawoptionvalue))
705709
— the raw `option` value
706-
- `source` ([`OptionValueSource`](#optionvaluesource))
710+
- `source` ([`OptionValueSource`](#optionvaluesource-1))
707711
— the source of the raw option `value`
708712
- `flag?` ([`Flags`](#flags), optional)
709713
— the parsed `option` flag
@@ -951,7 +955,7 @@ Get or set an option value.
951955
— option key
952956
- `value` (`unknown`)
953957
— the parsed option value to store
954-
- `source` ([`OptionValueSource`](#optionvaluesource) | `null` | `undefined`)
958+
- `source` ([`OptionValueSource`](#optionvaluesource-1) | `null` | `undefined`)
955959
— the source of the original option value
956960

957961
##### Returns
@@ -971,12 +975,12 @@ Get or set an option value source.
971975

972976
- `key` ([`Option['key']`](#optionkey))
973977
— option key
974-
- `source` ([`OptionValueSource`](#optionvaluesource) | `null` | `undefined`, optional)
978+
- `source` ([`OptionValueSource`](#optionvaluesource-1) | `null` | `undefined`, optional)
975979
— the source of the option value
976980

977981
##### Returns
978982

979-
([`OptionValueSource`](#optionvaluesource) | [`this`](#commandinfo) | `null` | `undefined`)
983+
([`OptionValueSource`](#optionvaluesource-1) | [`this`](#commandinfo) | `null` | `undefined`)
980984
Option value source for `key` or `this` command
981985

982986
#### `Command#options([infos])`
@@ -1424,6 +1428,9 @@ when `this` option is passed, but the implied option is not.
14241428

14251429
Lone keys (string `implies`) imply `true`, i.e. `{ [implies]: true }`.
14261430

1431+
The option-argument [`parser`](#parseableparserparser) will be called for implied values
1432+
that are strings and string arrays.
1433+
14271434
##### Overloads
14281435

14291436
- `implies(implies: OptionValues | string | null | undefined): this`
@@ -1531,10 +1538,17 @@ Get the option as a human-readable string.
15311538

15321539
A parsed option event (`class`).
15331540

1541+
> 👉 **Note**: For options where the `source` is `'implied'`, the `value` may not be a raw option value.
1542+
15341543
#### Extends
15351544

15361545
- [`KronkEvent`](#kronkeventid)
15371546

1547+
#### Signatures
1548+
1549+
- `constructor(option: T, value: RawOptionValue, source: OptionValueSource, flag?: Flags | null | undefined)`
1550+
- `constructor(option: T, value: unknown, source: optionValueSource.implied, flag?: Flags | null | undefined)`
1551+
15381552
##### Type Parameters
15391553

15401554
- `T` ([`Option`](#optioninfo), optional)
@@ -1545,9 +1559,9 @@ A parsed option event (`class`).
15451559
- `option` (`T`)
15461560
— the command option instance
15471561
- `value` ([`RawOptionValue`](#rawoptionvalue))
1548-
— the raw `option` value
1549-
- `source` ([`OptionValueSource`](#optionvaluesource))
1550-
— the source of the raw option `value`
1562+
— the `option` value
1563+
- `source` ([`OptionValueSource`](#optionvaluesource-1))
1564+
— the source of the option `value`
15511565
- `flag` ([`Flags`](#flags), optional)
15521566
— the parsed `option` flag
15531567

@@ -1571,7 +1585,7 @@ The command [`option`](#optioninfo) instance.
15711585

15721586
#### `OptionEvent#source`
15731587

1574-
[`OptionValueSource`](#optionvaluesource)
1588+
[`OptionValueSource`](#optionvaluesource-1)
15751589

15761590
The source of the raw option [`value`](#optioneventvalue).
15771591

@@ -1652,13 +1666,13 @@ Get or set the handler used to parse candidate-arguments.
16521666
##### Overloads
16531667

16541668
- `parser(parser: ParseArg<any, any> | null | undefined): this`
1655-
- `parser<T, V extends string | string[] = string | string[]>(): ParseArg<T, V>`
1669+
- `parser<T, Value extends RawParseValue = RawParseValue>(): ParseArg<T, Value>`
16561670

16571671
##### Type Parameters
16581672

16591673
- `T` (`any`)
16601674
— parse result
1661-
- `V` (`string | string[]`, optional)
1675+
- `Value` ([`RawParseValue`](#rawparsevalue), optional)
16621676
— the argument or arguments to parse
16631677

16641678
##### Parameters
@@ -1668,7 +1682,7 @@ Get or set the handler used to parse candidate-arguments.
16681682

16691683
##### Returns
16701684

1671-
([`ParseArg<T, V>`](#parsearg) | [`this`](#parseableinfo)) The candidate-argument parser or `this` candidate
1685+
([`ParseArg<T, Value>`](#parsearg) | [`this`](#parseableinfo)) The candidate-argument parser or `this` candidate
16721686

16731687
#### `Parseable#required`
16741688

@@ -1712,6 +1726,44 @@ A command version option (`class`).
17121726

17131727
The version of the command.
17141728

1729+
### `keid`
1730+
1731+
Default error ids (`const enum`).
1732+
1733+
```ts
1734+
const enum keid {
1735+
argument_after_variadic = 'kronk/argument-after-variadic',
1736+
conflicting_option = 'kronk/conflicting-option',
1737+
duplicate_option = 'kronk/duplicate-option',
1738+
duplicate_subcommand = 'kronk/duplicate-subcommand',
1739+
error = 'kronk/error',
1740+
excess_arguments = 'kronk/excess-arguments',
1741+
invalid_argument = 'kronk/invalid-argument',
1742+
invalid_argument_syntax = 'kronk/invalid-argument-syntax',
1743+
invalid_flags = 'kronk/invalid-flags',
1744+
invalid_subcommand_name = 'kronk/invalid-subcommand-name',
1745+
missing_argument = 'kronk/missing-argument',
1746+
missing_mandatory_option = 'kronk/missing-mandatory-option',
1747+
no_flags = 'kronk/no-flags',
1748+
unknown_implied_option = 'kronk/unknown-implied-option',
1749+
unknown_option = 'kronk/unknown-option'
1750+
}
1751+
```
1752+
1753+
### `optionValueSource`
1754+
1755+
Default option value sources (`const enum`).
1756+
1757+
```ts
1758+
const enum optionValueSource {
1759+
cli = 'cli',
1760+
config = 'config',
1761+
default = 'default',
1762+
env = 'env',
1763+
implied = 'implied'
1764+
}
1765+
```
1766+
17151767
## Types
17161768

17171769
This package is fully typed with [TypeScript][].
@@ -2321,14 +2373,16 @@ Data transfer object for command options (TypeScript interface).
23212373
an error will be displayed if conflicting options are found during parsing
23222374
- `env?` ([`List<string>`](#list) | `string`, optional)
23232375
— the name of the environment variable to check for option value, or a list of names, in order of priority, to check
2376+
- `implies?` ([`OptionValues`](#optionvalues) | `string`, optional)
2377+
— the key of an implied option, or a map where each key is an implied option key and each value is the value to use
2378+
when the option is set but the implied option is not.\
2379+
lone keys imply (string `implies`) `true`, i.e. `{ [implies]: true }`.\
2380+
the option-argument [`parser`](#parseableparserparser) will be called for implied values
2381+
that are strings and string arrays
23242382
- `mandatory?` (`boolean`, optional)
23252383
— whether the option is mandatory. mandatory options must have a value after parsing, which usually means the option
23262384
must be specified on the command line
23272385
- default: `false`
2328-
- `implies?` ([`OptionValues`](#optionvalues) | `string`, optional)
2329-
— the key of an implied option, or a map where each key is an implied option key and each value is the value to use
2330-
when the option is set but the implied option is not.\
2331-
lone keys imply (string `implies`) `true`, i.e. `{ [implies]: true }`
23322386
- `preset?` (`string`, optional)
23332387
— for boolean and optional options, the preset to use when the option is specified without an option-argument.
23342388
> 👉 **note**: the option-argument `parser` will be called.
@@ -2467,7 +2521,7 @@ type OptionValueSource = OptionValueSourceMap[keyof OptionValueSourceMap]
24672521
### `OptionValueSources`
24682522
24692523
Record, where each key is an option key ([`Option.key`](#optioninfo))
2470-
and each value is an [`OptionValueSource`](#optionvaluesource) (TypeScript type).
2524+
and each value is an [`OptionValueSource`](#optionvaluesource-1) (TypeScript type).
24712525
24722526
```ts
24732527
type OptionValueSources = {
@@ -2505,7 +2559,7 @@ type OptionsData =
25052559
Parse a command or option argument `value` (TypeScript type).
25062560
25072561
```ts
2508-
type ParseArg<T = any, Value extends string | string[] = string | string[]> = (
2562+
type ParseArg<T = any, Value extends RawParseValue = RawParseValue> = (
25092563
this: void,
25102564
value: Value,
25112565
previous: T | undefined
@@ -2516,7 +2570,7 @@ type ParseArg<T = any, Value extends string | string[] = string | string[]> = (
25162570
25172571
- `T` (`any`, optional)
25182572
— parse result
2519-
- `Value` (`string | string[]`, optional)
2573+
- `Value` ([`RawParseValue`](#rawparsevalue), optional)
25202574
— the argument or arguments to parse
25212575
25222576
#### Parameters
@@ -2541,6 +2595,17 @@ Options for parsing command-line arguments (TypeScript interface).
25412595
- `from?` ([`ArgvSource`](#argvsource), optional)
25422596
— the source of the command line arguments
25432597
2598+
### `ParseUnknownResult`
2599+
2600+
The result of parsing unknown arguments (TypeScript interface).
2601+
2602+
#### Properties
2603+
2604+
- `operands` (`string[]`)
2605+
— list of arguments that are operands (not options or values)
2606+
- `unknown` (`string[]`)
2607+
— list containing the first unknown option and any remaining unknown arguments
2608+
25442609
### `ParseableInfo`
25452610
25462611
Data used to create parse candidates (TypeScript interface).
@@ -2613,6 +2678,14 @@ Union of raw option value types (TypeScript type).
26132678
type RawOptionValue = boolean | string | string[] | null
26142679
```
26152680
2681+
### `RawParseValue`
2682+
2683+
The argument or arguments passed to an argument [parser](#parseableparserparser) (TypeScript type).
2684+
2685+
```ts
2686+
type RawParseValue = string | readonly string[]
2687+
```
2688+
26162689
### `SubcommandInfo`
26172690
26182691
Data used to create subcommands (TypeScript interface).
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/**
2+
* @file Command Fixtures - greaseBad
3+
* @module fixtures/commands/greaseBad
4+
*/
5+
6+
import grease from '#fixtures/commands/grease'
7+
import type { SubcommandInfo as CommandInfo } from '@flex-development/kronk'
8+
9+
/**
10+
* `grease` program info with invalid configurations.
11+
*
12+
* @type {CommandInfo}
13+
*/
14+
export default Object.assign({}, grease, {
15+
options: grease.options.map(info => {
16+
if (!info.flags.endsWith('--json')) return info
17+
return { ...info, implies: { LEVEL: 'log' } }
18+
}),
19+
subcommands: Object.assign({}, grease.subcommands, {
20+
info: {
21+
...grease.subcommands.info,
22+
options: grease.subcommands.info.options.map(info => {
23+
if (!info.flags.endsWith('--markdown')) return info
24+
return { ...info, implies: { logLevel: 'log' } }
25+
})
26+
}
27+
})
28+
})

src/enums/keid.mts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,10 @@
66
import type { KronkErrorId } from '@flex-development/kronk'
77

88
/**
9-
* Kronk error ids.
9+
* Default error ids.
1010
*
1111
* @see {@linkcode KronkErrorId}
1212
*
13-
* @internal
14-
*
1513
* @enum {KronkErrorId}
1614
*/
1715
const enum keid {
@@ -28,6 +26,7 @@ const enum keid {
2826
missing_argument = 'kronk/missing-argument',
2927
missing_mandatory_option = 'kronk/missing-mandatory-option',
3028
no_flags = 'kronk/no-flags',
29+
unknown_implied_option = 'kronk/unknown-implied-option',
3130
unknown_option = 'kronk/unknown-option'
3231
}
3332

src/enums/option-value-source.mts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ const enum optionValueSource {
1414
cli = 'cli',
1515
config = 'config',
1616
default = 'default',
17-
env = 'env'
17+
env = 'env',
18+
implied = 'implied'
1819
}
1920

2021
export default optionValueSource

src/events/option.event.mts

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import KronkEvent from '#events/kronk.event'
77
import type {
88
Flags,
99
Option,
10+
optionValueSource,
1011
OptionValueSource,
1112
RawOptionValue
1213
} from '@flex-development/kronk'
@@ -54,9 +55,56 @@ class OptionEvent<T extends Option = Option> extends KronkEvent {
5455
* @param {Flags | null | undefined} [flag]
5556
* The parsed `option` flag
5657
*/
58+
constructor(
59+
option: T,
60+
value: RawOptionValue,
61+
source: OptionValueSource,
62+
flag?: Flags | null | undefined
63+
)
64+
65+
/**
66+
* Create a new implied `option` event.
67+
*
68+
* @see {@linkcode Flags}
69+
* @see {@linkcode optionValueSource}
70+
*
71+
* @param {T} option
72+
* The command option instance
73+
* @param {unknown} value
74+
* The implied `option` value
75+
* @param {optionValueSource.implied} source
76+
* The source of the option `value`
77+
* @param {Flags | null | undefined} [flag]
78+
* The parsed `option` flag
79+
*/
80+
constructor(
81+
option: T,
82+
value: unknown,
83+
source: optionValueSource.implied,
84+
flag?: Flags | null | undefined
85+
)
86+
87+
/**
88+
* Create a new parsed `option` event.
89+
*
90+
* > 👉 **Note**: For options where the `source` is `'implied'`, the `value`
91+
* > may not be a raw option value.
92+
*
93+
* @see {@linkcode Flags}
94+
* @see {@linkcode OptionValueSource}
95+
*
96+
* @param {T} option
97+
* The command option instance
98+
* @param {unknown} value
99+
* The raw or implied `option` value
100+
* @param {OptionValueSource} source
101+
* The source of the option `value`
102+
* @param {Flags | null | undefined} [flag]
103+
* The parsed `option` flag
104+
*/
57105
constructor(
58106
public option: T,
59-
public value: RawOptionValue,
107+
public value: unknown,
60108
public source: OptionValueSource,
61109
public flag?: Flags | null | undefined
62110
) {

0 commit comments

Comments
 (0)