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

Feature Request: ability to hide options #1106

Closed
Tbhesswebber opened this issue Nov 23, 2019 · 12 comments
Closed

Feature Request: ability to hide options #1106

Tbhesswebber opened this issue Nov 23, 2019 · 12 comments
Milestone

Comments

@Tbhesswebber
Copy link

Tbhesswebber commented Nov 23, 2019

Ask:

Provide a .noHelp() command for an option to opt-out of the default help generation or update the .allowUnknownOptions command to take a list of accepted "unknown" options and store any of those which are passed somewhere within the program for access.

const commander = require('../');
const program = new commander.Command();

// unknown options
program.allowUnknownOptions(['--super-special-pizza']);

program
  .option('-h, --hawaiian', 'Create a sad pizza')
	// noHelp
  .noHelp();

Context:

Currently, there is no ability to hide options other than to manually parse process.argv in search of the specific options that you want and then strip those out of what you pass to program.parse.

I am working on an internally open-sourced CLI that takes advantage of feature flags to determine whether a command is in development, beta, production, or deprecated. The CLI is dynamically populated with the available commands depending on the user's self-declared "level" in a configuration file.

Use 1

In order to make our testing more robust, we'd like to be able to pass --[dev|beta|prod] in on the command line that will override that configuration file, making it so that we need fewer configuration files in order to run integration and e2e tests on the full suite.

Use 2:

Once we integrate with the API that is in development, we will want to pass a --test [endpoint] flag to the code during e2e tests to inform it that it needs to use that specific endpoint for the test-session and the test-specific headers that are required for a test session.

@shadowspawn
Copy link
Collaborator

A challenge with additions to .option() is that we don't have an options parameter to easily specify custom behaviour. I suggested .optionEx in #1038 but it was not popular, at least for that case.

The issue I have with the .noHelp() chain call is that it is actually being called on a command object rather than on an option object, and feels a bit fragile. (There was a similar suggestion for a chain call for mandatory options too.)

A different idea, but a bit clumsy, is a separate call to supply the extra settings:

.markOption('--hawaiian', { noHelp: true }):

Similar past issue: #811

@shadowspawn
Copy link
Collaborator

Exploring a couple of builder patterns for extending functionality, which might fit in with Commander chaining style.

Inline builder:

program
  .option('--one', 'description 1')
  .buildOption('--test <endpoint>')
    .noHelp()
    .build()
  .option('--two', 'description 2');

And a more conventional builder which returns an Option:

program
  .option('--one', 'description 1')
  .addOption(OptionBuilder('--test <endpoint>')
    .noHelp()
    .build()))
  .option('--two', 'description 2');

@Tbhesswebber
Copy link
Author

I think the builder patterns provide a distinctly extensible direction that commander could go in in the future, making it a more valuable immediate path, potentially.

I think it could tie into your "clumsy" suggestion as an "under the hood" kind of thing for the time being and then there could be a full release that uses chainable builders both under the hood or explicitly for more future control

@shadowspawn
Copy link
Collaborator

Still exploring interface ideas. A simple way to expose a low-level extensible interface for less common use cases might be:

program
   .buildOption({ flags: '--super-special-pizza', noHelp: true });

@Tbhesswebber
Copy link
Author

Tbhesswebber commented Nov 25, 2019

I think that the more conventional builder would be the most flexible and allow for people to get as creative as possible while staying SOLID. The conventional pattern helps separate concerns because the exported option manages its own logic.

// option.js

export default OptionBuilder("--super-special-pizza")
  .boolean()
  .default({
    size: getConfig().size
  })
  .noHelp()
  .build();

@shadowspawn
Copy link
Collaborator

Good comment about separation of concerns. I have been thinking too much about the Command end, but there is already an Option which may be sufficient without a separate builder.

program
   .addOption(new Option('--super-special-pizza').noHelp());

(And the new could be optional.)

@Tbhesswebber
Copy link
Author

Sorry for the major delay! The holidays and work travel have made things crazy.

I like that! (Although, I think that optional news sometimes make things more confusing because you don't always know what cases should require a new and what cases shouldn't.)

@benoitlamarche
Copy link

I also would really love this feature.
My 2 cents: maybe it would make sense that an option that has no description is hidden? I remember seeing an API like that, I'm not sure where.

@shadowspawn
Copy link
Collaborator

maybe it would make sense that an option that has no description is hidden?

Not a bad idea @benoitlamarche , but the option description is not required and for simple cases quite reasonable to omit. That would be a breaking change in behaviour.

@shadowspawn
Copy link
Collaborator

Experimenting with Option approach in #1331:

program
   .addOption(new Option('-s, --secret').hideHelp())

@shadowspawn shadowspawn added the pending release Merged into a branch for a future release, but not released yet label Sep 14, 2020
@shadowspawn shadowspawn added this to the v7.0.0 milestone Sep 14, 2020
@shadowspawn shadowspawn removed their assignment Sep 14, 2020
@shadowspawn
Copy link
Collaborator

Included in v7.0.0 pre-release #1386

@shadowspawn shadowspawn removed the pending release Merged into a branch for a future release, but not released yet label Jan 15, 2021
@shadowspawn
Copy link
Collaborator

Included in Commander 7.0.0.

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

No branches or pull requests

3 participants