opts icon indicating copy to clipboard operation
opts copied to clipboard

Low-level parser API

Open jpillora opened this issue 3 years ago • 2 comments

Some features, like JSON config, would be nice to do a double sweep - first sweep to grab the JSON file path, use the file to define opts defaults, then another sweep to execute the current opts parse.

This is a low level API would replace usage of standard library flags.

No type parsing at this layer, just strings. Here's the API I was thinking:

// Parse given args and return Results in parse-order
func Parse(args []string) ([]Result, error)
func ParseWith(args []string, options Options) ([]Result, error)

type Options struct {
  Flags []string //explicit white-list flags
  Values []string //explicit white-list values
  MultiShort bool //enable multi-short parsing
  SingleDash bool //enable flags with a single dash (go default, but non-standard)
  // other parsing styles...
}

type Result struct {
  Name string
  Value string
}

func (r Result) IsFlag() bool {
  return r.Name != "" && r.Value == ""
}

func (r Result) IsValue() bool {
  return r.Name != "" && r.Value != ""
}

func (r Result) IsArg() bool {
  return r.Name == "" && r.Value != ""
}
  • given ps -aux (multi-shorts) or ps -a -u -x (normal shorts)
    • results [{"value": "ps"}, {"name":"a"}, {"name":"u"}, {"name":"x"}]
  • given cmd --foo --bar (normal flags)
    • results [{"name":"foo"}, {"name":"foo"}]
  • given cmd --foo 42 (normal value) or cmd --foo=42 (force value)
    • results [{"name":"foo", "value": "42"}]

jpillora avatar Sep 15 '21 03:09 jpillora

Oh hm, interesting idea. But what about more complex things like subcommands? Also flags that can be repeated? With subcommands you might run into the issue I described in https://github.com/anacrolix/args/issues/1 where your definition of parser, and its resulting data have to be separated, and then the final consumer of the parse has to dig back through the tree of data all over again (even if it's nice strings and stuff, there's still going to be things like switch Result.Subcommand.Name { case "some arbitrary literal that accidentally differ from the one that was in Options before parsing" }.

anacrolix avatar Sep 15 '21 13:09 anacrolix

Ahh yeah true, —foo could be a bool in one sub command and an int (need to pair with next token) in another. Needs staged parsing, ParseUntil(subcmds []string) ([]Result, rest []string) and you keep calling as you parse each

On Wed, 15 Sep 2021 at 11:20 pm Matt Joiner @.***> wrote:

Oh hm, interesting idea. But what about more complex things like subcommands? Also flags that can be repeated? With subcommands you might run into the issue I described in anacrolix/args#1 https://github.com/anacrolix/args/issues/1 where your definition of parser, and its resulting data have to be separated, and then the final consumer of the parse has to dig back through the tree of data all over again (even if it's nice strings and stuff, there's still going to be things like switch Result.Subcommand.Name { case "some arbitrary literal that accidentally differ from the one that was in Options before parsing" } .

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/jpillora/opts/issues/31#issuecomment-920012737, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAE2X4ZKMNWELCW3S43F7NLUCCMSHANCNFSM5EBPRWPQ .

jpillora avatar Sep 15 '21 13:09 jpillora