What does everyone suggest for command-line options parsing? This seems to be missing from the gemset and I've never found any of the existing solutions to be very intuitive.
The choice of not writing options parser was very deliberate. As much as it is a tempting proposition I believe there are already great tools around. TTY attempts to provide glue to stitch a lot of scripting needs together without opinionated view on how they should be structured - for now at least ;-)
In my scripting experience I tend to gravitate towards two solutions. If my script is fairly small, e.i. in a single file, with no much complexity I tend to use Ruby standard library optparse. However, if my needs get a bit more complex and I need, for example, subcommands I use thor. Thor gives me a better way to structure my application logic. These two solutions so far have covered all my needs.
My recommendation before using other libraries would be to really give optparse a good spin so that you can figure out why the other options are more suitable.
To add to the wonderful options already stated here, I wrote a gem once upon a time called "bales" (https://github.com/YellowApple/bales) that provides a reasonably-nice DSL to declaratively define command-line applications (including subcommands up to arbitrary nesting levels) without the complexity of more fully-featured command-line app libraries like Thor and Boson. I haven't done as good of a job at maintaining it as I would've liked, but it works reasonably well and I've used it for quite a few quick-and-dirty command-line programs.
But hand rolling is also hard and annoying to support if you want to support long-name options and short name optionals, out of order with potential spaces in odd places that still work as most users will expect them to along with reasonable usage-instruction documetantation.
Never do this. There are a basket of edge-cases and weirdness that you'll miss in your three-minute re-implementation that aren't worth that pain you'll have using or debugging later on.
There's a better alternative: don't have complex usage in the first place. You can get all the functionality you want by having multiple executables calling a common library.
Consider netcat. You read the man page, and try to do something following its advice. Often enough, it just doesn't work. Because it's trying to cover a range of unrelated usages through a single entrypoint.
It's easy to set up multiple exes cleanly. Have a non-executable module that contains the functions that your application requires (e.g. call it lib.rb). For each distinct usage, create a separate executable script that imports lib.rb, extracts a, b and c from the for just that usage and then call lib.usage(a, b, c).
Users will find this easy to discover. You will find it easy to maintain, even compared to dedicated parsing DSLs.
We don't special-case functions to do multiple things based on complex argument cases. We just create well-defined functions. We should think of executables in the same terms.
There are really only edge cases in usage models - I've found option libraries all fairly poor, because they expose a global view of the options, rather than an iterator view, for the most part.
If args are in a structure that can be peeked and shifted, you're in a good place for context sensitive options. It's just a lexer.
My tools tend towards this syntax:
cmd [<global opt>...] subcommand [<local opt>...]
Composing the data structure for this with option libraries is often more work than iterating over a peekable stream of words.
As always this depends. In principle I agree for example I wrote pastel-cli(https://github.com/piotrmurach/pastel-cli) that doesn't use any parser to figure out arguments. However, it's super basic, for anything more complex I would look for more powerful parsers. Lexing command input as much as it is fun can be very thorny issue.