garnix-io/garn

garn.shell argparsing helper

Opened this issue · 0 comments

I was thinking a bit more about garn.shell, and how it ideally should be a great script-writing helper like just. It is unfortunate that:

  1. Shell completion breaks for arguments to the underlying executable
  2. The help for the underlying executable is poorly integrated into the garn help
  3. It's harder to deal with arguments than it is in, say, a just recipe
  4. (Arguably,) it'd be nice to not need --.

And it occurred to me we can solve all 3 (or 4 if we wish) by allowing the run command to be a function, and then have a little description/validator for it (a lot like yargs. E.g.:

// These just do overloading to figure out how many arguments are necessary. Useful for one-off, simple scripts
garn.shell("my command", ([arg1, arg2]) => `echo "Got arguments ${arg1} and ${arg}`")

// This, with the third argument, is more "production-grade". We do more validation, and can have more informative help and completion
garn.shell("my command", (args) => `echo "Running on port ${args.port}`"), {
  args:  {
    port: {
      kind: "positional"
      type: "integer"
      default: 8000
      description: "The output port"
    }
    ...
  }
}

How would this work? Well, the idea is that args would become not the eventual value passed, but a (list of/record of/individual) shell variable (e.g. $GARN_ARG_PORT) that gets interpolated statically in the shell script. Then, we wrap the shell script in something that does shell processing and sets those variables accordingly.