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

feat: allow strict mode to be applied globally #734

Closed
wants to merge 1 commit into from

Conversation

nexdrew
Copy link
Member

@nexdrew nexdrew commented Dec 16, 2016

While recently working on a yargs-based Slackbot with several nested commands, I wanted to apply .strict() mode at each level so that when an invalid command/subcommand is given (e.g. mistyped) it would return help text (with an error message) instead of not running/returning anything. Since there is currently no way to apply strict mode globally in yargs, I ended up having to call .strict() in each command's builder function at every nested level. Ugh.

This PR augments the .strict() API so that it can accept a boolean value to either (a) apply globally when passed true or (b) be disabled when passed false (to allow a command to override a global strict mode). The method maintains backwards-compatibility with the previous API of enabling strict mode in a non-global way when called without any arguments.

It might be slightly odd interpreting a boolean value in two different ways based on its value, but I think it's acceptable since it provides for all use-cases:

  1. enable strict mode for the current level only: .strict()
  2. enable strict mode globally (for the current level and its sub-levels): .strict(true)
  3. disable strict mode for the current level: .strict(false)

Note that strict mode defaults to "globally" disabled, so not calling the method at all satisfies that use-case.

@bcoe
Copy link
Member

bcoe commented Dec 17, 2016

@nexdrew one question for you, would it be more intuitive for to default to strict being applied globally; might be worth a major if it makes for a more elegant API.

If this was a brand new feature being added, do you think you'd opt for this API surface? If so, I'm sold 👍

Copy link
Member

@maxrimue maxrimue left a comment

Choose a reason for hiding this comment

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

LGTM 👍 Do we want to consider making it global by default in the next major? I like the backwards compatibility this PR maintains but a default global makes more sense I think and would also play in line with automatically globally options we wanted to introduce at some point

@nexdrew
Copy link
Member Author

nexdrew commented Dec 19, 2016

@bcoe @maxrimue If I were adding this as a new feature, I'd probably apply .strict() globally by default. However, if that were the case, I'd still want a way to disable it per command, in which case I'd still probably use .strict(false) or perhaps introduce a new API method for disabling, e.g. .notStrict() or .lenient().

A new API method would allow us to use method name and boolean argument to represent the 2 main decisions concerning strict mode: (a) do you want to enable or disable it and (b) do you want to do so globally or not, satisfying the 4 use-cases I am aware of. Here's a table comparing the API proposed by this PR with two theoretical possibilities (for illustrative purposes only):

Enabled? Global? With this PR Enable via method, global as boolean Global via method, enabled as boolean
🚫 (default) No explicit API .notStrict(true) or .notStrict() .strict(false)
.strict(true) .strict(true) or .strict() .strict(true) or .strict()
🚫 🚫 .strict(false) .notStrict(false) .strictLocal(false)
🚫 .strict() .strict(false) .strictLocal(true)

We could, of course, also just accept an object that allows an author to define enabled or global params as boolean properties, but I'm not sure that would make things simpler for CLI authors.

In practical terms, I think we could get away with assuming global and just allow authors to enable and disable it as necessary via .strict() and .strict(false) / .notStrict().

The current API being what it is, though, I'd rather avoid a major bump just for this. If it were coupled with a few other breaking changes, it'd be fine, but I'd like to avoid too many potentially unwarranted (meaning we could have introduced the change in a non-breaking way) major version bumps.

@maxrimue
Copy link
Member

@nexdrew I, too, think we should avoid a major bump just for this. This is why I would propose to land backwards compatible changes like you made them now and make a defaults change when we're about to land the next major bump which focuses on other major changes.

I was also thinking about the object approach ({enabled: ..., global: ...}), and of course it would be more to write, but I think this is the easiest and most expressive solution. No need to look up .strict() in the docs if you forgot what the boolean stands for (which will happen I'm afraid). Of course just one boolean value is shorter, but we should carefully question whether that is worth sacrificing expressiveness, which is what yargs enabled for argv processing in the first place.

@nexdrew
Copy link
Member Author

nexdrew commented Dec 19, 2016

@maxrimue Very good points! I agree with your proposal.

I think, when it comes to the most ideal API, yargs should make doing the "right" thing (i.e. the most prominent use-case, which should align with the user's intentions most of the time) as easy as possible. In this case, it sounds like we're all agreed that .strict() should enable strict mode globally, so that's what we can shoot for in the next major release.

In the meantime, should I update the docs to clarify what .strict(true) and .strict(false) actually do?

@bcoe
Copy link
Member

bcoe commented Dec 26, 2016

@nexdrew @maxrimue let's add some docs and lands this 👍

@nexdrew
Copy link
Member Author

nexdrew commented Dec 31, 2016

To avoid introducing an API consistency between 6.x and 7.x, perhaps we should just go ahead and change it to "global by default" (as bcoe originally implied) and allow it to be disabled per command via .strict(false) (which might be unlikely but seems like a good idea to me). Then we could just include this in the 7.x major bump.

@bcoe
Copy link
Member

bcoe commented Jan 2, 2017

@nexdrew I approve of this message, I think we have enough things queued up for a really solid 7.x; one thing comes to mind, maybe we should just be making all options default to global?

@maxrimue
Copy link
Member

maxrimue commented Jan 2, 2017

@bcoe Definitely for making options global by default 👍

@bcoe
Copy link
Member

bcoe commented Jan 16, 2017

@nexdrew 👍 let's make this one of the first things we land on a 7.x branch.

@bcoe
Copy link
Member

bcoe commented Jan 20, 2017

@nexdrew once you dust this off, perhaps you can re-submit the pull against a 7.x branch, I think we're starting to collect up some goals for that release.

@bcoe
Copy link
Member

bcoe commented Jan 22, 2017

@nexdrew I am going to pull this into #766.

@nexdrew nexdrew deleted the strict-global branch February 27, 2017 16:24
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.

None yet

3 participants