Pattern Matching CLI commands with Rust
I’m building a CLI tool using Rust, and I ran into some difficulties figuring out the best way to work with the structopts crate using subcommands to break out my logic into separate functions. I suspect this is because I am new to Rust, but I felt it was worth documenting the challenge and solution.
I’ll use a fake tool to demonstrate the pattern I used. Let’s say the tool is called
it is used to print two different kinds of messages: hellos and goodbyes. So you might
ecko hello World
and expect to see an output like
Hello, World. Additionally there is a global option of
-p, for “punctuation”
to allow the user to add any punctuation to the end of any command, such as
ecko goodbye -p '!' "cruel world" to
Goodbye, cruel world!. The project implementing this example can be found on GitHub.
So the first step is to define the CLI application, which the structopt docs describe well.
ecko application will look something like this:
When building out CLI applications with subcommands, I like to write one function per subcommand. I
feel it keeps the logic easy to reason about and read. So the plan is to have two functions,
goodbye that accept two arguments, one for the subcommand’s struct and another for the overall
command’s struct. This allows us to typehint everything properly and get autocompletion in our function.
Finally is the part I had trouble figuring out, and that is how to best match on the type of the
subcommand such that it can be known when calling the functions. I think the trouble was really just
in my being new to the language, so the Rust-compentent out there probably already know this.
However, once you call
cli.cmd you can
match on it and pull out the inner struct, converting
it into a variable of its own. So bringing it all together, the
main function will be