Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Positional options #1427

Merged
merged 26 commits into from
Jan 4, 2021

Conversation

shadowspawn
Copy link
Collaborator

@shadowspawn shadowspawn commented Jan 1, 2021

Pull Request

Collected issues and background research in #1229

Problem

Two quite similar problems in how they look on command line, but different use cases.

  1. A program option can not be reused in a subcommand, as the program options are recognised anywhere on the command line.

Related: #598 #797 #1033 #1307 #1426

  1. It is not easy to pass through options which are intended for another program. The options are recognised before or after command-arguments.

Related: #1127 #1293

Solution

Add two new routines to alter the parsing of options to be positional. The default behaviour is unchanged.

.enablePositionalOptions()

Enable positional options. Positional means global options are specified before subcommands which lets subcommands reuse the same option names, and also enables subcommands to turn on passThroughOptions.

The default behaviour is non-positional (as before) and global options may appear anywhere on the command line.

Positional options makes it different whether an option comes before or after a subcommand. e.g.

program -p subcommand
program subcommand -p
program -p subcommand -p

.passThroughOptions()

Pass through options that come after command-arguments rather than treat them as command-options, so actual command-options come before command-arguments. Turning this on for a subcommand requires positional options to have been enabled on the program (parent commands).

The default behaviour is non-positional (as before) and options may appear before or after command-arguments.

Pass through options makes it different whether an option comes before or after a command-argument. e.g.

program --verbose arg
program arg --verbose
program --verbose arg --verbose

ChangeLog

  • .enablePositionalOptions() to let program and subcommand reuse same option
  • .passThroughOptions() to pass options through to other programs without needing --

To Do:

  • TypeScript typings
  • tests
  • README
  • examples

@shadowspawn shadowspawn changed the title Feature/positional arguments WIP: Positional options Jan 1, 2021
@shadowspawn shadowspawn self-assigned this Jan 1, 2021
@shadowspawn shadowspawn changed the title WIP: Positional options Positional options Jan 3, 2021
@shadowspawn shadowspawn marked this pull request as ready for review January 3, 2021 00:41
@shadowspawn
Copy link
Collaborator Author

shadowspawn commented Jan 3, 2021

This has been implemented as a non-breaking change, so can go after 7.0.0 if there are concerns.

Copy link
Collaborator

@abetomo abetomo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How nice!

@shadowspawn
Copy link
Collaborator Author

Thanks @abetomo 🎈

@shadowspawn shadowspawn merged commit 8ac84ec into tj:release/7.x Jan 4, 2021
@shadowspawn shadowspawn deleted the feature/positional-arguments branch January 4, 2021 06:59
@shadowspawn shadowspawn added the pending release Merged into a branch for a future release, but not released yet label Jan 4, 2021
@shadowspawn shadowspawn added this to the v7.0.0 milestone Jan 4, 2021
@shadowspawn shadowspawn mentioned this pull request Jan 9, 2021
@shadowspawn shadowspawn removed the pending release Merged into a branch for a future release, but not released yet label Jan 16, 2021
@CMCDragonkai
Copy link

Does this feature allow me to add global options before adding sub commands?

  const polykey = new Command();
  polykey.version('0.0.1');
  polykey.exitOverride();
  polykey.addCommand(commandKeys);

Is it then possible to do polykey -v 2 subcommand?

@shadowspawn
Copy link
Collaborator Author

@CMCDragonkai
You can use global options before subcommands, whether or not positional-arguments is enabled.

@CMCDragonkai
Copy link

CMCDragonkai commented Jan 23, 2021

But how do I access these global options inside a subcommand action handler? And will it work if put the option after the subcommand? Our CLI has loads of subcommands.

@shadowspawn
Copy link
Collaborator Author

shadowspawn commented Jan 23, 2021

@CMCDragonkai
The short answer is: you can access the global options on the program command with program.opts() or cmd.parent.opts(), they are not passed into the action handler directly. The default behaviour is that options are not positional and global options can come before or after subcommands.

Please open a new issue if you want a fuller explanation. If I understood your questions correctly, they do not seem to be about this Pull Request but about global options in general.

@ruscon
Copy link

ruscon commented Feb 19, 2021

@shadowspawn
command.parent does not exists in types. Can you fix it?
v7.1

@shadowspawn
Copy link
Collaborator Author

shadowspawn commented Feb 19, 2021

@ruscon
Ah right, last time it came up we were refactoring and I was not sure if parent could be null or undefined so didn't add it at the time (#1184). The typings are stricter in v7 too, previously parent would have not generated a warning since it could have been an option value.

If you don't mind, would you please open a new issue to track this? (I have added it to my private backlog in any case.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants