From eef4b77ff64658ce4ab03ce37ed04d6d2fac7779 Mon Sep 17 00:00:00 2001 From: tommy-mitchell Date: Sun, 19 Mar 2023 11:51:43 -0500 Subject: [PATCH 1/3] feat(`flags`): add `aliases` option --- index.d.ts | 5 ++++- index.js | 15 +++++++++++++++ index.test-d.ts | 4 +++- readme.md | 4 +++- test/test.js | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 73 insertions(+), 3 deletions(-) diff --git a/index.d.ts b/index.d.ts index 5c06aaa..eb44d8d 100644 --- a/index.d.ts +++ b/index.d.ts @@ -21,6 +21,7 @@ export type Flag = { readonly default?: Default; readonly isRequired?: boolean | IsRequiredPredicate; readonly isMultiple?: IsMultiple; + readonly aliases?: string[]; }; type StringFlag = Flag<'string', string> | Flag<'string', string[], true>; @@ -47,6 +48,7 @@ export type Options = { If it's only known at runtime whether the flag is required or not you can pass a Function instead of a boolean, which based on the given flags and other non-flag arguments should decide if the flag is required. - `isMultiple`: Indicates a flag can be set multiple times. Values are turned into an array. (Default: false) Multiple values are provided by specifying the flag multiple times, for example, `$ foo -u rainbow -u cat`. Space- or comma-separated values are *not* supported. + - `aliases`: Other names for the flag. (Not a short flag) Note that flags are always defined using a camel-case key (`myKey`), but will match arguments in kebab-case (`--my-key`). @@ -64,7 +66,8 @@ export type Options = { } return false; - } + }, + aliases: ['unicorns'] } } ``` diff --git a/index.js b/index.js index b17499c..d855c6a 100644 --- a/index.js +++ b/index.js @@ -86,6 +86,15 @@ const buildParserFlags = ({flags, booleanDefault}) => { delete flag.isMultiple; } + if (Array.isArray(flag.aliases)) { + if (flag.alias) { + flag.aliases.push(flag.alias); + } + + flag.alias = flag.aliases; + delete flag.aliases; + } + parserFlags[flagKey] = flag; } @@ -224,6 +233,12 @@ const meow = (helpText, options = {}) => { validateFlags(flags, options); for (const flagValue of Object.values(options.flags)) { + if (Array.isArray(flagValue.aliases)) { + for (const alias of flagValue.aliases) { + delete flags[alias]; + } + } + delete flags[flagValue.alias]; } diff --git a/index.test-d.ts b/index.test-d.ts index add5eb3..95ea6a2 100644 --- a/index.test-d.ts +++ b/index.test-d.ts @@ -53,7 +53,7 @@ const result = meow('Help text', { importMeta, flags: { foo: {type: 'boolean', alias: 'f'}, - 'foo-bar': {type: 'number'}, + 'foo-bar': {type: 'number', aliases: ['foobar', 'fooBar']}, bar: {type: 'string', default: ''}, abc: {type: 'string', isMultiple: true}, }, @@ -70,6 +70,8 @@ expectType(result.flags.abc); expectType(result.unnormalizedFlags.foo); expectType(result.unnormalizedFlags.f); expectType(result.unnormalizedFlags['foo-bar']); +expectType(result.unnormalizedFlags.foobar); +expectType(result.unnormalizedFlags.fooBar); expectType(result.unnormalizedFlags.bar); expectType(result.unnormalizedFlags.abc); diff --git a/readme.md b/readme.md index 188d32e..b9d0cec 100644 --- a/readme.md +++ b/readme.md @@ -112,6 +112,7 @@ The key is the flag name in camel-case and the value is an object with any of: - The function should return a `boolean`, true if the flag is required, otherwise false. - `isMultiple`: Indicates a flag can be set multiple times. Values are turned into an array. (Default: false) - Multiple values are provided by specifying the flag multiple times, for example, `$ foo -u rainbow -u cat`. Space- or comma-separated values are [currently *not* supported](https://github.com/sindresorhus/meow/issues/164). +- `aliases`: Other names for the flag. (Not a short flag) Note that flags are always defined using a camel-case key (`myKey`), but will match arguments in kebab-case (`--my-key`). @@ -130,7 +131,8 @@ flags: { } return false; - } + }, + aliases: ['unicorns'] } } ``` diff --git a/test/test.js b/test/test.js index d9b8033..699165a 100644 --- a/test/test.js +++ b/test/test.js @@ -580,6 +580,54 @@ test('isMultiple - handles multi-word flag name', t => { }); }); +test('aliases - accepts one', t => { + t.deepEqual(meow({ + importMeta, + argv: ['--foo=baz'], + flags: { + fooBar: { + type: 'string', + aliases: ['foo'], + }, + }, + }).flags, { + fooBar: 'baz', + }); +}); + +test('aliases - accepts multiple', t => { + t.deepEqual(meow({ + importMeta, + argv: ['--foo=baz1', '--bar=baz2'], + flags: { + fooBar: { + type: 'string', + aliases: ['foo', 'bar'], + isMultiple: true, + }, + }, + }).flags, { + fooBar: ['baz1', 'baz2'], + }); +}); + +test('aliases - works with short flag alias', t => { + t.deepEqual(meow({ + importMeta, + argv: ['--foo=baz1', '--bar=baz2', '-f=baz3'], + flags: { + fooBar: { + type: 'string', + alias: 'f', + aliases: ['foo', 'bar'], + isMultiple: true, + }, + }, + }).flags, { + fooBar: ['baz1', 'baz2', 'baz3'], + }); +}); + if (NODE_MAJOR_VERSION >= 14) { test('supports es modules', async t => { try { From 01780f9b2c4bdebe002c580f74c5400eeaabac34 Mon Sep 17 00:00:00 2001 From: tommy-mitchell Date: Sun, 19 Mar 2023 11:58:01 -0500 Subject: [PATCH 2/3] chore(`test.js`): update to `shortFlag` --- test/test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/test.js b/test/test.js index 337e0a1..7735091 100644 --- a/test/test.js +++ b/test/test.js @@ -633,14 +633,14 @@ test('aliases - accepts multiple', t => { }); }); -test('aliases - works with short flag alias', t => { +test('aliases - works with short flag', t => { t.deepEqual(meow({ importMeta, argv: ['--foo=baz1', '--bar=baz2', '-f=baz3'], flags: { fooBar: { type: 'string', - alias: 'f', + shortFlag: 'f', aliases: ['foo', 'bar'], isMultiple: true, }, From f14e3de66730554d22ef7397f97b057087ba7f3b Mon Sep 17 00:00:00 2001 From: tommy-mitchell Date: Sun, 19 Mar 2023 12:05:16 -0500 Subject: [PATCH 3/3] fix(`aliases`): allowed to be a short flag --- index.d.ts | 2 +- readme.md | 2 +- test/test.js | 15 +++++++++++++++ 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/index.d.ts b/index.d.ts index 60b3e22..b9ba23c 100644 --- a/index.d.ts +++ b/index.d.ts @@ -48,7 +48,7 @@ export type Options = { If it's only known at runtime whether the flag is required or not you can pass a Function instead of a boolean, which based on the given flags and other non-flag arguments should decide if the flag is required. - `isMultiple`: Indicates a flag can be set multiple times. Values are turned into an array. (Default: false) Multiple values are provided by specifying the flag multiple times, for example, `$ foo -u rainbow -u cat`. Space- or comma-separated values are *not* supported. - - `aliases`: Other names for the flag. (Not a short flag) + - `aliases`: Other names for the flag. Note that flags are always defined using a camel-case key (`myKey`), but will match arguments in kebab-case (`--my-key`). diff --git a/readme.md b/readme.md index 37c213e..a3a5c15 100644 --- a/readme.md +++ b/readme.md @@ -112,7 +112,7 @@ The key is the flag name in camel-case and the value is an object with any of: - The function should return a `boolean`, true if the flag is required, otherwise false. - `isMultiple`: Indicates a flag can be set multiple times. Values are turned into an array. (Default: false) - Multiple values are provided by specifying the flag multiple times, for example, `$ foo -u rainbow -u cat`. Space- or comma-separated values are [currently *not* supported](https://github.com/sindresorhus/meow/issues/164). -- `aliases`: Other names for the flag. (Not a short flag) +- `aliases`: Other names for the flag. Note that flags are always defined using a camel-case key (`myKey`), but will match arguments in kebab-case (`--my-key`). diff --git a/test/test.js b/test/test.js index 7735091..38ab8ba 100644 --- a/test/test.js +++ b/test/test.js @@ -633,6 +633,21 @@ test('aliases - accepts multiple', t => { }); }); +test('aliases - can be a short flag', t => { + t.deepEqual(meow({ + importMeta, + argv: ['--f=baz'], + flags: { + fooBar: { + type: 'string', + aliases: ['f'], + }, + }, + }).flags, { + fooBar: 'baz', + }); +}); + test('aliases - works with short flag', t => { t.deepEqual(meow({ importMeta,