I had an older post about ruby and slop but that’s with Slop 3 which is basically locked to Ruby 1.9.
No doubt, this post will bitrot too so please pay attention to the post date. The current ruby
is about 2.3.0, slop 4.3 is current, it’s 2016 and the US election cycle is awful.
I think the most confusing thing about slop is that it has great examples and documentation but
when you try to break this apart in a real app with small methods and single responsibilities
some things sort of get weird. I think this is because of exception handling as logic control
but I’m not sure enough to say slop is doing something wrong that makes this weird. In
my example
I refer back to MY OWN BLOG quite often for slop examples so it’s ok that you need help.
Slop’s example
Let’s look at the example from the README.
I disagree with -h here for hosts. I think -h should always be help. This is especially true
when switching contexts. When I switch to java or node or go or python, I have no idea
what those communities’ standards are. I rely on what unix expects: dash aitch.
I disagree also with this example because figuring out how to handle -h for help
is the most confusing thing about using slop because you have to use exceptions
as flow control (sort of an anti-pattern).
A real example
Let’s write a wrapper program called What the Fi? for our Internet connection.
When Internet things get wonky there are a few sites and tools I use to see is it just me?.
This wrapper will combine all those things into a CLI. We’ll use Slop 4.3 to parse
the CLI options. We’ll even write tests!
The main structure of this program is subcommand based. It’s a particular type
of CLI example similar to git where there are branches of main commands. After the
main branching logic, you could have options on each of the subcommands but I’ll leave that as an
exercise to you. I’d also recommend thor if you want to
build a complicated CLI with subcommands. What I mean to say is, the following
is just a CLI example that happens to follow this subcommand pattern.
Here’s how you use it.
The relevant Slop options are in this bit.
Notice that the rescue Slop::UnknownOption needed for Slop parsing is inside of a method called parse_arguments.
On many tools/projects I’ve done this isn’t enough to handle all cases. Then, what I’ll do
is roll a custom error class and throw that instead. You could also instead just not
begin;rescue;end here and do it higher up in the main. If you find yourself losing
data/context, it means you are at the wrong level of method calls. In the slop examples, this isn’t
explicitly mentioned but I find this way to be the most unixy. It print help on an unknown option
and it prints help if you don’t define -h or --help. If you have a -h option you want to use
then use the on '--help' example Slop mentions.
Full Example
I hesitate to post the whole script here because it is very long. But here it is anyway. If you prefer
a git repo to puruse like a sane and reasonable person then here it is.
If you look at main and validate_arguments, you’ll see that --ip being a boolean and not
a string caused special logic to spew everywhere. It’s because it’s a switch and not a parameter with
a string value (it’s not --ip=1.2.3.4, it’s just --ip or nothing). Because of this, we have
to treat this option differently. Sometimes we need to know if it’s been set but because Slop
will set an unset boolean to false, we can’t check for nil like all the other flags.
I hope this post helps the googlers write their CLIs. My
older post about slop had
bit-rotted and at the same time gotten high up on the google rankings. I hope
I have avenged myself (against myself?). All hail the bit rot.