75lb / command-line-args

A mature, feature-complete library to parse command-line options.
MIT License
679 stars 107 forks source link

Support for negated flags #108

Closed ematipico closed 4 years ago

ematipico commented 4 years ago

Would it be possible to support negated flags out of the box? Or with an opt-in option?

75lb commented 4 years ago

Hi, I need more detail. Could you give me an exampe of the use case you want to support.

elyobo commented 4 years ago

If you have a Boolean option with a default true value, then it's nice to be able to negate it in the standard way, e.g. if you have --dev with a default of true, then --no-dev would generally set it to false. Built in support for this is relatively common in command line argument processors.

75lb commented 4 years ago

Having a Boolean option defined with a defaultValue of true effectively makes the option useless.

Take this example:

const commandLineArgs = require('command-line-args')
const optionDefinitions = [
  { name: 'dev', type: Boolean, defaultValue: true }
]

const options = commandLineArgs(optionDefinitions)
console.log(options)

Whether you set --dev or not makes no difference, effectively making the option pointless.

$ node example.js --dev
{ dev: true }

$ node example.js
{ dev: true }

I'm not sure this is good option design. Would this definition make more sense? It has two meaningful states - true and false, where true means "prod" and false means "dev".

const optionDefinitions = [
  { name: 'prod' type: Boolean }
]
75lb commented 4 years ago

In the case you do have a Boolean flag permenantly set to true, here's an example of how to implement a negating flag:

const commandLineArgs = require('command-line-args')
const optionDefinitions = [
  { name: 'dev', type: Boolean, defaultValue: true },
  { name: 'no-dev', type: Boolean }
]

const options = commandLineArgs(optionDefinitions)
const dev = options.dev && !options['no-dev']
console.log(`dev: ${dev}`)

Usage:

$ node example.js
dev: true

$ node example.js --dev
dev: true

$ node example.js --dev --no-dev
dev: false

$ node example.js --no-dev
dev: false
75lb commented 4 years ago

I've added an example and explaination to the wiki. Does this help?

https://github.com/75lb/command-line-args/wiki/How-to-implement-a-negating-flag

elyobo commented 4 years ago

Having a Boolean option defined with a defaultValue of true effectively makes the option useless.

Yes, that's the exact point of the issue :)

In the case you do have a Boolean flag permenantly set to true, here's an example of how to implement a negating flag:

Yes, that's pretty much how I worked around it too. It would also make printing out help text based on the options a bit of a pain, but I'm not doing that so I don't know for sure.

The suggestion is that the lib should automatically support negated booleans, such that if you define a dev with a boolean type then it should also automatically handle the no-dev without having to manually parse it.

Negating boolean flags with a no- prefix is a common pattern for command line arguments, and also a common pattern to support in command line argument parsing libraries, but this lib is nice and simple, so possibly too out of scope?

75lb commented 4 years ago

It would also make printing out help text based on the options a bit of a pain

I've added an example of how to hide --no-* options to the wiki.

The suggestion is that the lib should automatically support negated booleans

The problem is that it's an opinionated domain. Yes, the lib could follow a convention and automatically prepend no- to option names but, instead of --no-dev what if users wanted --нет-дев? Opinions and conventions differ, and change over time. I have withdrawn opinions from this lib in the past.

elyobo commented 4 years ago

That's a fair position to take 👍

On Fri, 27 Mar 2020, 21:10 Lloyd Brookes, notifications@github.com wrote:

It would also make printing out help text based on the options a bit of a pain

I've added an example of how to hide --no-* options to the wiki https://github.com/75lb/command-line-args/wiki/How-to-implement-a-negating-flag .

The suggestion is that the lib should automatically support negated booleans

The problem is that it's an opinionated domain. Yes, the lib could follow a convention and automatically prepend no- to option names but, instead of --no-dev what if users wanted --нет-дев? Opinions and conventions differ, and change over time. I have withdrawn opinions from this lib in the past https://github.com/75lb/command-line-args/wiki/Validation#why-is-validation-not-built-into-the-module .

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/75lb/command-line-args/issues/108#issuecomment-604918923, or unsubscribe https://github.com/notifications/unsubscribe-auth/AADDR7X7KG7DOQBTZ3XBKWTRJR3TBANCNFSM4KZ2XWIA .