<!DOCTYPE html>
<html lang="en">
    <head>
        <meta content="width=device-width, initial-scale=1" charset="utf-8" />
        <title>Using `clap`</title>
        <link href="/style.css" type="text/css" rel="stylesheet" />
        <link href="/prism.css" type="text/css" rel="stylesheet" />
    </head>
    <body class="line-numbers">
        <h1 id="using-clap">Using <code>clap</code></h1>
        <p>Clap stands for Command Line Argument Parser, and put simply,
        it's a great library for making command-line stuff with Rust.
        Even Cargo, Rust's package manager, depends on it
        (<em>Cargo/cargo.toml at master</em>), and it's been downloaded
        over 300 million times (<em>Clap - Crates.io: Rust package
        registry</em>).</p>
        <p>Rather than going over everything clap can do, I'll go over
        how I've used it in my <code>disk-read-benchmark</code> program
        I'll be using in my next blog post.</p>
        <h2 id="basics">Basics</h2>
        <p>First off, we need to install <code>clap</code>; make sure to
        enable its <code>derive</code> feature as that's what we'll be
        using.</p>
        <div class="sourceCode" id="cb1"><pre
        class="language-sh"><code class="language-bash"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="ex">cargo</span> add clap <span class="at">--features</span> derive</span></code></pre></div>
        <p>First off, we need to get a bit of code just to start
        off:</p>
        <div class="sourceCode" id="cb2"><pre
        class="language-rust"><code class="language-rust"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="kw">use</span> <span class="pp">clap::</span><span class="op">{</span>Parser<span class="op">,</span> Subcommand<span class="op">};</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a><span class="at">#[</span>derive<span class="at">(</span>Parser<span class="at">)]</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a><span class="at">#[</span>command<span class="at">(</span>version<span class="op">,</span> about<span class="op">,</span> long_about <span class="op">=</span> <span class="cn">None</span><span class="at">)]</span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a><span class="kw">pub</span> <span class="kw">struct</span> Cli <span class="op">{</span></span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a>    <span class="at">#[</span>command<span class="at">(</span>subcommand<span class="at">)]</span></span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a>    <span class="kw">pub</span> command<span class="op">:</span> Commands<span class="op">,</span></span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
        <p>This has the built-in "version" and "about" options, with the
        long "about" option disabled.</p>
        <p>Next, we need to list all out commands we'll have:</p>
        <div class="sourceCode" id="cb3"><pre
        class="language-rust"><code class="language-rust"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="at">#[</span>derive<span class="at">(</span>Subcommand<span class="at">)]</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a><span class="kw">pub</span> <span class="kw">enum</span> Commands <span class="op">{</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a>    <span class="co">///Run this thing</span></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a>    Run<span class="op">,</span></span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a>    <span class="co">///Delete the stuff that thing does</span></span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a>    Delete<span class="op">,</span></span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
        <p>The documentation comments (<code>///</code>) should
        <em>not</em> have a space after the slashes, as otherwise the
        program will have an extra space where it shouldn't.</p>
        <p>Finally, we create the <code>main()</code> function. First it
        parses everything, then checks what command was run and runs the
        relevant code.</p>
        <div class="sourceCode" id="cb4"><pre
        class="language-rust"><code class="language-rust"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="kw">fn</span> main() <span class="op">{</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">let</span> cli <span class="op">=</span> <span class="pp">Cli::</span>parse()<span class="op">;</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a>    <span class="cf">match</span> cli<span class="op">.</span>command <span class="op">{</span></span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a>        <span class="pp">Commands::</span>Run <span class="op">{</span></span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a>            run()<span class="op">;</span></span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb4-8"><a href="#cb4-8" aria-hidden="true" tabindex="-1"></a>        <span class="pp">Commands::</span>Delete <span class="op">{</span></span>
<span id="cb4-9"><a href="#cb4-9" aria-hidden="true" tabindex="-1"></a>            delete()<span class="op">;</span></span>
<span id="cb4-10"><a href="#cb4-10" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb4-11"><a href="#cb4-11" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb4-12"><a href="#cb4-12" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
        <p>That's all you need to know to use <code>clap</code> at a
        very basic level; for more details, check out the docs (<em>clap
        Documentation</em>). But, you probably don't want to have to
        type in the entire command automatically, autocomplete would be
        nice. So I'll also go over how to use <code>clap_complete</code>
        as well.</p>
        <h2 id="clap_complete"><code>clap_complete</code></h2>
        <p>Searching through the documentation (<em>Clap_complete
        Documentation</em>), you'll notice that the docs don't cover how
        to use it with clap's derive at all. Instead, after some
        Googling, I found an example script in <em>clap</em>'s
        repository (<em>completion-derive.rs at master</em>), which I
        then adapted and played around with a bit until I got it figured
        out.</p>
        <p>Anyways, again, we need to install <code>clap_complete</code>
        first:</p>
        <div class="sourceCode" id="cb5"><pre
        class="language-sh"><code class="language-bash"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="ex">cargo</span> add clap_complete</span></code></pre></div>
        <p>Then, add the relevant imports. We'll just being doing it for
        the fish shell since that's what I use, so we'll only import
        <code>Fish</code>; Bash, Zsh, PowerShell, and Elvish are also
        supported.</p>
        <div class="sourceCode" id="cb6"><pre
        class="language-rust"><code class="language-rust"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="kw">use</span> <span class="pp">clap_complete::aot::</span><span class="op">{</span>generate<span class="op">,</span> Fish<span class="op">};</span></span></code></pre></div>
        <p>Then, we need to add a command to generate the
        completion:</p>
        <div class="sourceCode" id="cb7"><pre
        class="language-rust"><code class="language-rust"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="at">#[</span>derive<span class="at">(</span>Subcommand<span class="at">)]</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a><span class="kw">pub</span> <span class="kw">enum</span> Commands <span class="op">{</span></span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a>    <span class="co">///Run this thing</span></span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a>    Run<span class="op">,</span></span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a>    <span class="co">///Delete the stuff that thing does</span></span>
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true" tabindex="-1"></a>    Delete<span class="op">,</span></span>
<span id="cb7-7"><a href="#cb7-7" aria-hidden="true" tabindex="-1"></a>    <span class="co">///Generate fish completions</span></span>
<span id="cb7-8"><a href="#cb7-8" aria-hidden="true" tabindex="-1"></a>    FishCompletions<span class="op">,</span></span>
<span id="cb7-9"><a href="#cb7-9" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
        <p>Next, we actually generate the completion, adding it like
        it's another command:</p>
        <div class="sourceCode" id="cb8"><pre
        class="language-rust"><code class="language-rust"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a>    <span class="cf">match</span> cli<span class="op">.</span>command <span class="op">{</span></span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a>        <span class="pp">Commands::</span>Run <span class="op">{</span></span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a>            run()<span class="op">;</span></span>
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb8-5"><a href="#cb8-5" aria-hidden="true" tabindex="-1"></a>        <span class="pp">Commands::</span>Delete <span class="op">{</span></span>
<span id="cb8-6"><a href="#cb8-6" aria-hidden="true" tabindex="-1"></a>            delete()<span class="op">;</span></span>
<span id="cb8-7"><a href="#cb8-7" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb8-8"><a href="#cb8-8" aria-hidden="true" tabindex="-1"></a>        <span class="pp">Commands::</span>GenerateFishCompletions <span class="op">=&gt;</span> <span class="op">{</span></span>
<span id="cb8-9"><a href="#cb8-9" aria-hidden="true" tabindex="-1"></a>            generate(</span>
<span id="cb8-10"><a href="#cb8-10" aria-hidden="true" tabindex="-1"></a>                Fish<span class="op">,</span></span>
<span id="cb8-11"><a href="#cb8-11" aria-hidden="true" tabindex="-1"></a>                <span class="op">&amp;</span><span class="kw">mut</span> <span class="pp">Cli::</span>command()<span class="op">,</span></span>
<span id="cb8-12"><a href="#cb8-12" aria-hidden="true" tabindex="-1"></a>                <span class="st">&quot;example-program&quot;</span><span class="op">,</span></span>
<span id="cb8-13"><a href="#cb8-13" aria-hidden="true" tabindex="-1"></a>                <span class="op">&amp;</span><span class="kw">mut</span> stdout()<span class="op">,</span></span>
<span id="cb8-14"><a href="#cb8-14" aria-hidden="true" tabindex="-1"></a>            )<span class="op">;</span></span>
<span id="cb8-15"><a href="#cb8-15" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb8-16"><a href="#cb8-16" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span></code></pre></div>
        <p>To explain the options for <code>generate()</code>:</p>
        <ul>
        <li><code>Fish</code>: The shell we're using.</li>
        <li><code>&amp;mut Cli::command()</code>: I don't actually know
        what this does, but understanding ths library fully this is
        beyond my pay grade, especially given the somewhat lacking
        docs.</li>
        <li><code>"example-program"</code>: The name of our program</li>
        <li><code>&amp;mut stdout()</code>: <code>stdout</code>, so that
        it can print the completions. Why does it do it this way? I
        don't know, it doesn't make sense to me. Why doesn't it just
        return it as a String? I don't know. But it works, I
        suppose.</li>
        </ul>
        <p>As an example of all this, here's my
        <code>disk-read-benchmark</code> program, running using all
        this. The commands have formatting I can't do, so it looks even
        better than I can even show here.</p>
        <div class="sourceCode" id="cb9"><pre
        class="language-txt"><code class="language-default"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a>~&gt; disk-read-benchmark</span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a>Usage: disk-read-benchmark &lt;COMMAND&gt;</span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a>Commands:</span>
<span id="cb9-5"><a href="#cb9-5" aria-hidden="true" tabindex="-1"></a>  generate-bash-completions  Generate bash completions</span>
<span id="cb9-6"><a href="#cb9-6" aria-hidden="true" tabindex="-1"></a>  generate-zsh-completions   Generate zsh completions</span>
<span id="cb9-7"><a href="#cb9-7" aria-hidden="true" tabindex="-1"></a>  generate-fish-completions  Generate fish completions</span>
<span id="cb9-8"><a href="#cb9-8" aria-hidden="true" tabindex="-1"></a>  grab-data                  Grabs the datasets used for benchmarking</span>
<span id="cb9-9"><a href="#cb9-9" aria-hidden="true" tabindex="-1"></a>  benchmark                  Runs the benchmark</span>
<span id="cb9-10"><a href="#cb9-10" aria-hidden="true" tabindex="-1"></a>  prep-dirs                  Prepares the directories so other programs can prepare their datasets</span>
<span id="cb9-11"><a href="#cb9-11" aria-hidden="true" tabindex="-1"></a>  run                        Runs it all</span>
<span id="cb9-12"><a href="#cb9-12" aria-hidden="true" tabindex="-1"></a>  help                       Print this message or the help of the given subcommand(s)</span>
<span id="cb9-13"><a href="#cb9-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-14"><a href="#cb9-14" aria-hidden="true" tabindex="-1"></a>Options:</span>
<span id="cb9-15"><a href="#cb9-15" aria-hidden="true" tabindex="-1"></a>  -h, --help     Print help</span>
<span id="cb9-16"><a href="#cb9-16" aria-hidden="true" tabindex="-1"></a>  -V, --version  Print version</span>
<span id="cb9-17"><a href="#cb9-17" aria-hidden="true" tabindex="-1"></a>~&gt; disk-read-benchmark generate-fish-completions | source</span>
<span id="cb9-18"><a href="#cb9-18" aria-hidden="true" tabindex="-1"></a>~&gt; disk-read-benchmark benchmark --help</span>
<span id="cb9-19"><a href="#cb9-19" aria-hidden="true" tabindex="-1"></a>Runs the benchmark</span>
<span id="cb9-20"><a href="#cb9-20" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-21"><a href="#cb9-21" aria-hidden="true" tabindex="-1"></a>Usage: disk-read-benchmark benchmark</span>
<span id="cb9-22"><a href="#cb9-22" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-23"><a href="#cb9-23" aria-hidden="true" tabindex="-1"></a>Options:</span>
<span id="cb9-24"><a href="#cb9-24" aria-hidden="true" tabindex="-1"></a>  -h, --help  Print help</span></code></pre></div>
        <p>To better see how great it looks, here's a screenshot:</p>
        <img src="/assets/using-clap/1.png"
        title="The same output, but with very nice formatting - underlining and bolding for headers and the tables" alt="The same output, but with very nice formatting - underlining and bolding for headers and the tables" />
        <p>Pressing tab twice after entering
        <code>disk-read-benchmark</code> displays the completions, which
        I can select and use like any other program's.</p>
        <div class="sourceCode" id="cb10"><pre
        class="language-txt"><code class="language-default"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a>~&gt; disk-read-benchmark</span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a>benchmark                         (Runs the benchmark)  grab-data                               (Grabs the datasets used for benchmarking)</span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a>generate-bash-completions  (Generate bash completions)  help                   (Print this message or the help of the given subcommand(s))</span>
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a>generate-fish-completions  (Generate fish completions)  prep-dirs  (Prepares the directories so other programs can prepare their datasets)</span>
<span id="cb10-5"><a href="#cb10-5" aria-hidden="true" tabindex="-1"></a>generate-zsh-completions    (Generate zsh completions)  run                                                                  (Runs it all)</span></code></pre></div>
        <h2 id="sources">Sources</h2>
        <p> - clap contributors. “clap Documentation.” Clap - Rust, <a
        href="https://docs.rs/clap/latest/clap/">docs.rs/clap/latest/clap/</a>.
        Accessed 12 Nov. 2024.<br />
         - clap_complete contributors. “Clap_complete Documentation.”
        Clap_complete - Rust, <a
        href="https://docs.rs/clap_complete/latest/clap_complete">docs.rs/clap_complete/latest/clap_complete</a>.
        Accessed 12 Nov. 2024.<br />
         - clap contributors.
        “clap/clap_complete/examples/completion-derive.rs at master ·
        Clap-Rs/Clap.” GitHub, <a
        href="https://github.com/clap-rs/clap/blob/master/clap_complete/examples/completion-derive.rs">github.com/clap-rs/clap/blob/master/clap_complete/examples/completion-derive.rs</a>.
        Accessed 12 Nov. 2024.<br />
         - cargo contributors. “cargo/Cargo.Toml at master ·
        rust-lang/cargo.” GitHub, <a
        href="https://github.com/rust-lang/cargo/blob/master/Cargo.toml">github.com/rust-lang/cargo/blob/master/Cargo.toml</a>.
        Accessed 12 Nov. 2024.<br />
         - “Clap - Crates.io: Rust Package Registry.” crates.io,
        crates.io/crates/clap. Accessed 12 Nov. 2024.</p>
        <iframe src="https://john.citrons.xyz/embed?ref=askiiart.net" style="margin-left:auto;display:block;margin-right:auto;max-width:732px;width:100%;height:94px;border:none;"></iframe>
        <script src="/prism.js"></script>
    </body>
    <footer>
        <p><a href="https://git.askiiart.net/askiiart/engl-2311-blog">Source code</a>&ensp;|&ensp;<a href="/feed.xml">RSS</a>&ensp;|&ensp;<a href="/glossary.html">Glossary</a>&ensp;|&ensp;<a href="/about.html">About</a></p>
        <small>Image captions are the same as the alt text; assuming you're sighted, you can most likely ignore them.</small>
    </footer>
</html>