Coding TypeGym: A Rust Terminal Typing Trainer | Part 6: Command Line Arguments

Published on

In Part 6 (the final episode of this mini series) we turn TypeGym from a hard coded demo into a proper command line tool.

Up to this point many settings lived in source code: which text source we used, how much text we generated, how wide paragraphs were, etc. Now we move all of that into a clean CLI interface powered by clap.


What We Covered


Design Insights

Clap works best when you lean into types

Instead of parsing strings manually in main(), we let clap do the heavy lifting:

That makes the “front door” of the application clean and it scales nicely as we add more options.

Reflow is a usability feature, not just formatting

Generated text often has awkward line breaks (or none at all). A terminal typing trainer feels much nicer when lines:

So we add optional reflow that wraps words into lines up to --width.


Implementation Highlights

1) Config becomes a real CLI parser

Config is now the single source of truth for configuration and clap derives it:

#[derive(Debug, Parser)]
pub struct Config {
    #[arg(long, default_value_t = 1)]
    pub fg_miss: u8,

    #[arg(long, default_value_t = 8)]
    pub fg_empty: u8,

    #[arg(long, default_value_t = 1)]
    pub fg_results: u8,

    #[arg(
        long,
        default_value = "markov:data/markov.txt",
        value_name = "SOURCE",
        help = "Text source: static, nonsense, weighted, file:<path> or markov:<path>"
    )]
    pub text_source: TextSource,

    #[arg(long, default_value_t = 100)]
    pub max_words: usize,

    #[arg(long, default_value_t = 80, requires = "reflow")]
    pub width: usize,

    #[arg(long, default_value_t = false)]
    pub reflow: bool,
}

And in main we simply do:

let config = Config::parse();

No more Config::new(), no more TODOs.

2) Parsing TextSource from --text-source

To make clap understand TextSource we implement FromStr:

This gives us a nice user facing syntax without needing separate flags for every source.

3) Make text generation configurable (max_words)

Previously, generators hard coded 100 words. Now:

Everything respects --max-words making the tool much more flexible.

4) Optional text wrapping (--reflow, --width)

When reflow is enabled we:

  1. split the generated text into words
  2. pack words into lines up to width
  3. join lines with \n

This is intentionally simple but it works well and makes practice text look consistently formatted across terminal sizes.


Usage Examples

Here are a few ways to run TypeGym now:

# Default settings (Markov chain from data/markov.txt)
typegym

# Classic random word nonsense
typegym --text-source nonsense

# Weighted nonsense (more natural distribution)
typegym --text-source weighted --max-words 150

# Read a random slice from a file
typegym --text-source file:data/words.txt

# Markov chain from custom text, wrapped to 60 columns
typegym --text-source markov:data/markov.txt --max-words 120 --reflow --width 60

Wrapping Up the Series

At this point TypeGym is a complete little terminal app:


Project Code

You will find the complete source code here: typegym