#subcommand #clap #command #cli-command #cli

macro clap-dispatch

Ergonomically dispatch CLI subcommands

2 releases

0.1.1 Jan 25, 2025
0.1.0 Jan 25, 2025

#2364 in Parser implementations

Download history 99/week @ 2025-01-19 109/week @ 2025-01-26 31/week @ 2025-02-02

239 downloads per month

MIT license

11KB
118 lines

clap-dispatch

Ergonomic way to dispatch CLI subcommands in Rust.

Useful when your CLI defines subcommands, all of which should do the same kind of action, just in a different way. I.e., when the subcommands are variants of running a certain action.

See the documentation.


lib.rs:

Ergonomic way to dispatch CLI subcommands.

Useful when your CLI defines subcommands, all of which should do the same kind of action, just in a different way.
I.e., when the subcommands are variants of running a certain action.

It becomes especially useful when you have nested subcommands. In this case you can dispatch all the way down to the leaves of your command tree!

Example

Suppose you implement a CLI for sorting numbers.
You have two algorithms, Quick Sort and Merge Sort, and they have their own subcommand, respectively.

#[derive(Parser)]
enum Cli {
    Quick(QuickArgs),
    Merge(MergeArgs),
}

Now the point is, both algorithms will essentially just implement some sort(...) function with the same signature. You could model this as both QuickArgs and MergeArgs implementing a function like:

fn sort(self, nums: Vec<i32>) -> Vec<i32>

(The self is there so that they can make use of the special arguments passed for the respective algorithm.)
So you could put such a function into a trait, and then implement the trait for both QuickArgs and MergeArgs.

The annoying part is, to dispatch the sort(...) function, you then have to do a match over your Cli enum and call sort(...) on every variant. That's boilerplate.

This crate is doing the boilerplate for you.

In this case, you would do the following macro invocation:

#[derive(Parser)]
#[clap_dispatch(fn sort(self, nums: Vec<i32>) -> Vec<i32>)] // macro call
enum Cli {
    Quick(QuickArgs),
    Merge(MergeArgs),
}

This defines a trait Sort which contains the sort(...) function, and it also implements Sort for Cli, where the implementation just dispatches to the variants. So what's left to you is only:

  • implement Sort for QuickArgs and MergeArgs (i.e. implement the algorithms)
  • call cli.sort(...)

Usage

A minimal explanation is in the definition of the [macro@clap_dispatch] macro.

The full code for the above example can be found in the example/ folder. (latest GitHub version)

Dependencies

~255–700KB
~17K SLoC