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

Allow defining positional argument #541

Closed
hax opened this Issue Jul 6, 2016 · 14 comments

Comments

Projects
None yet
9 participants
@hax

hax commented Jul 6, 2016

Currently describe/number/string... only apply to option, I expect it would also apply to positional argument.

yargs.command('cmd <arg>')
     .number('arg')
     .choices('arg', [2, 3, 4])

We also need arg/args method like option/options

yargs.command('cmd [arg]')
     .arg('arg', {type: 'string', default: 'ok'})

Here is the list of methods or keys of arg/args opt I think could apply to arguments:

  • boolean
  • choices
  • config
  • configParser
  • default
  • defaultDescription
  • desc/describe/description
  • group
  • nargs
  • normalize
  • number
  • skipValidation (though I don't understand the use case of this method)
  • string
  • type
  • env (missed in current option/options api)
@bcoe

This comment has been minimized.

Member

bcoe commented Jul 7, 2016

hey @hax, we actually already support this with the concept of a builder and a handler for commands (these can even be provided in sub-modules, how cool is that!).

we're in discussion to figure out how to make these features more intuitive, but the current pass is pretty well documented here:

https://github.com/yargs/yargs#commandmodule

Would love to have you join in on the conversation here regarding version 5.x of yargs. We're hoping to make some additional improvements to how commands work.

@bcoe bcoe closed this Jul 7, 2016

@hax

This comment has been minimized.

hax commented Jul 8, 2016

@bcoe You mean the 5.x branch already support refine positional argument like option? I will try it.

@bcoe

This comment has been minimized.

Member

bcoe commented Jul 8, 2016

@hax should be supported in 4.x with builders and handlers 👍

@hax

This comment has been minimized.

hax commented Jul 8, 2016

@bcoe Sorry, I still can not find how to refine the argument. (with version 4.8.0-candidate)

yargs.command('cmd <arg>')
     .number('arg')
     .choices('arg', [2, 3, 4])

As my example in the first comment, I expect to define the the constraint (should be a number, should be in 2, 3, 4) of <arg>, but actually I just defined a --arg option.

@wearhere

This comment has been minimized.

wearhere commented Aug 7, 2016

I'm confused as well, how would you describe <arg>? The examples given in https://github.com/yargs/yargs#commandmodule just talk about describing options.

@hax

This comment has been minimized.

hax commented Aug 8, 2016

@wearhere I confirmed that it only describe options, my question is how to solve the requirements of describing <arg>.

@bcoe

This comment has been minimized.

Member

bcoe commented Aug 8, 2016

@wearhere @hax commands currently only allow for simply positional arguments, but using the commands API you can define options that a command would accept, so:

yargs.command('cmd <foo>')

only allows for simple values to be provided for foo, e.g., ./foo.js cmd fooarg., you can use a builder function to describe arguments that a cmd would accept, e.g.,

yargs.command('cmd', function (yargs) { yargs.option('foo', { string: true, default: 'ok
})
})`

But this would expect the signature, ./foo.js cmd --foo 99

I like the idea of being able to apply the full suite of yargs options to positional arguments, perhaps you could open this as a detailed feature request?

@wearhere

This comment has been minimized.

wearhere commented Aug 8, 2016

@bcoe I like @hax's proposal at the top. He talks about creating an API like options but for positional arguments, with the same sorts of flags. Perhaps you could reopen this issue? Or what would you like to see in a different feature request?

@pluma

This comment has been minimized.

pluma commented Oct 27, 2016

I actually ended up re-implementing the part of showHelp that does the option formatting to add this to the command's builder's usage call (which involves using cliui and window-size directly, sadly).

It would be awesome if we could get an equivalent to yargs.option for documenting arguments (optionally).

@nexdrew

This comment has been minimized.

Member

nexdrew commented Oct 27, 2016

These are all good ideas. Honestly, I too have been annoyed that positional args don't get the same treatment as flagged options. IMO, I wouldn't mind if my CLI accepted either a positional arg or a flagged option for the same value, e.g. something like this:

require('yargs')
  .command('cmd <x> [y]', 'An exemplar command', (yargs) => {
    return yargs
      .option('x', {
        desc: 'This is a required string',
        type: 'string'
      })
      .option('y', {
        desc: 'This is an optional number',
        type: 'number',
        default: 10
      })
  }, (argv) => {
    console.log(`x: ${argv.x}, y: ${argv.y}`)
  })
  .help()
  .wrap(null)
  .argv
$ app help cmd
app cmd <x> [y]

Arguments:
  x  This is a required string  [string]
  y  This is an optional number  [number]

Options:
  --help  Show help  [boolean]

$ app cmd hang
x: hang, y: 10

$ app cmd -x hang
x: hang, y: 10

$ app cmd -y 5 -x high
x: high, y: 5

That way, there's not really any need to modify the API; yargs should be smart enough to know when a configured .option() is already defined as a positional arg.

We could probably hack around this without too much drastic refactoring, but I'm convinced we need to move positional arg parsing down to yargs-parser in order to make positional args a first-class citizen when it comes to configuration, parsing, and validation. As it is, positional arg handling is done in yargs after yargs-parser has already been executed, so we end up duplicating logic for each little nuance/feature we want. Unfortunately, this would be somewhat of a big change for yargs-parser, since it'd have to have some knowledge of configured commands, which it currently doesn't have. Not saying it can't be done - it's just gonna take a bit of work to get it right. When I get time, I'll have to start experimenting with yargs-parser to see how much work this will actually be.

@raijinsetsu

This comment has been minimized.

raijinsetsu commented Nov 16, 2016

Was this closed on purpose? If so, does this mean the feature is not being considered?
I also ran into this where positional arguments make more sense than options.

For example:
app acls add <applicationID> <userID> <access>
makes more sense to me than
app acls add -a applicationID -u userID -acc access

@tkarls

This comment has been minimized.

tkarls commented Feb 22, 2017

I don't understand why this issue was closed when the original problem is not solved nor has a viable workaround.

As far as I understand the builder function @bcoe mentions can be used to describe the -- options to a command. But not the positional arguments.

so, consider the string:
my-app cmd <arg> --option=hello

Here, I can easily specify allowed values on --hello. Assign a coerce function etc. But with arg I cannot do anything like that. Right?

I think this issue deserves to be reopened.

@ruimarinho

This comment has been minimized.

ruimarinho commented Feb 22, 2017

@tkarls right. I'm also looking for the same behaviour (e.g. coercing) for positional arguments.

@jeffijoe

This comment has been minimized.

jeffijoe commented Jun 30, 2017

I think @nexdrew makes perfect sense, and I, too, don't understand why this issue was closed.

@bcoe bcoe referenced this issue Oct 5, 2017

Merged

feat: make positional arguments fully configurable #967

5 of 5 tasks complete
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment