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

Optional type and Custom option processing do not work together #1201

Closed
prodigitalson opened this issue Feb 26, 2020 · 5 comments
Closed

Optional type and Custom option processing do not work together #1201

prodigitalson opened this issue Feb 26, 2020 · 5 comments

Comments

@prodigitalson
Copy link

prodigitalson commented Feb 26, 2020

Opening a new issue exactly the same as #984.

I have a use case for a where I would like a flag with an optional value, however instead of the flag being true I want to evaluate it to a default value.

Ideally the following would happpen:

program
  .option('-w, --with-cheese [value]', 'Use something special', 'cheddar');

program.parse(process.argv);

if (program.withCheese) {
  console.log(`You ordered a sandwich with ${program.withCheese} cheese`)
} else {
   console.log(`You ordered a sandwich`);
}
$ sandwich
You ordered a sandwich
$ sandwich --with-cheese
You ordered a sandwich with cheddar cheese
$ sandwhich --with-cheese provolone
You ordered a sandwich with provolone cheese

That seems like it could lead to unexpected and ambiguous results though. So the next best thing, and how i immediately thought to handle it, was with custom option processing:

const defaultIfTrue= (defaultValue) => {
  return (curr, prev) => curr === true ? defaultValue : curr;
}
program
  .option('-w, --with-cheese [value]', 'Use something special', defaultIfTrue('cheddar'));

program.parse(process.argv);

if (program.withCheese) {
  console.log(`You ordered a sandwich with ${program.withCheese} cheese`)
} else {
   console.log(`You ordered a sandwich`);
}

However given the details in #984, this doesn't work either. I'm investigating the event listener, but I can't/don't want to store something outside of the normal options, meaning I need to update the command so that program.withCheese AND program.opts().withCheese reflect the value appropriately. I have yet to figure that out...

@shadowspawn
Copy link
Collaborator

I expect you are looking for a more sophisticated solution, but I'll point out there is a simple manual approach to handling the default value in the README:

if (program.cheese === undefined) console.log('no cheese');
else if (program.cheese === true) console.log('add cheese');
else console.log(`add cheese type ${program.cheese}`);

@shadowspawn
Copy link
Collaborator

(On a historical note the default value in this case is being treated the same way as for an option with a required value, rightly or wrongly, and has been that way since the beginning:

@shadowspawn
Copy link
Collaborator

I had been wondering whether the custom option processing function should be called when there is no value for an optional flag. This would allow more complex handling like in the original post in this thread, but I realised today would break the use of simple coercion routines.

program
  .option('-f, --float [value]', 'coerce value to float', parseFloat)

The current behaviour is calling the program like foo -f will set the value to true. If parseFloat was called it would instead be set to NaN.

@shadowspawn
Copy link
Collaborator

An approach was provided, and no further activity in a month. I have had a look at the code history, and discounted one possible code change. There is not likely to be further action due to this report.

Feel free to open a new issue if it comes up again, with new information and renewed interest.

Thank you for your contributions.

@shadowspawn
Copy link
Collaborator

shadowspawn commented Dec 19, 2021

I discovered recently that options with optional arguments are actually broken when there is a default value, making the requested behaviour difficult to achieve. The option is ignored when supplied without a value.

I have PR #1652 open to fix that, and add .preset(), which works well for the requested behaviour.

program
  .addOption(new Option('-w, --with-cheese [value]', 'Use something special').preset('cheddar'));

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

No branches or pull requests

2 participants