Crate Clap

    Source: https://docs.rs/clap/latest/clap/

    Setup Steps 🔗

    An example of project where this was used is zola_chrono but I want to stop including the logging level as part of it and defer to using environment variables as already supported by env_logger.

    • Add dependency
      cargo add clap -F derive,cargo,wrap_help
      
    • Copy cli.rs and add and remove as needed
    • Copy from main.rs as needed
    • Testing
      #[cfg(test)]
      mod tests {
      
          #[test]
          fn verify_cli() {
              // Source: https://docs.rs/clap/latest/clap/_derive/_tutorial/index.html#testing
              // My understanding it reports most development errors without additional effort
              use clap::CommandFactory;
              super::Cli::command().debug_assert()
          }
      }
      

    Example of cargo subcommand 🔗

    https://github.com/rust-practice/cargo-leet/

    Example of using clap derive 🔗

    Full details can be found in the clap docs. This is just an short example showing features I use more frequently.

    #!/usr/bin/env -S cargo +nightly -Zscript
    ---cargo
    package.edition = "2021" # Desirable to stop warning but not needed
    [dependencies]
    version-control-clean-check = { version = "0.1.4", features = ["clap"] }
    anyhow = "1.0.94"
    clap = { version = "4.5.23", features = ["derive", "wrap_help"] }
    ---
    
    use clap::{Parser, ValueEnum};
    use std::path::PathBuf;
    use version_control_clean_check::{check_version_control, CheckOptions};
    
    /// Short about text goes here
    ///
    /// This part is only included in the long about text that shows when using --help
    #[derive(Parser, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Default)]
    #[command(author, version, about)]
    struct Cli {
        /// Specify the root directory or uses current directory if not provided
        #[arg(value_name = "FOLDER", default_value = ".")]
        root: PathBuf,
    
        #[clap(flatten)]
        check_version_control: CheckOptions,
    
        /// A boolean flag that is set to true if the argument is provided
        ///
        /// This line only shows in the long help mode and
        /// if you do not include `long` or `short` (both used below) on the argument
        /// then it becomes positional
        #[arg(long, short)]
        optional_flag: bool,
    
        /// Included to give an example for an enum
        #[arg(value_enum, long, default_value_t)]
        mode: Animal,
    }
    
    #[derive(ValueEnum, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Default)]
    enum Animal {
        Bird,
        #[default]
        Cat,
        Dog,
    }
    
    fn main() -> anyhow::Result<()> {
        let cli = Cli::parse();
        dbg!(&cli);
        let path = cli.root.canonicalize()?;
        dbg!(&path);
        check_version_control(path, &cli.check_version_control)?;
        println!("Program Ended");
        Ok(())
    }
    

    Example output:

    % ./single_file_script.rs -h
        Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.04s
         Running `/home/one/.cargo/target/b1/bdd0db958a601c/debug/single_file_script -h`
    Short about text goes here
    
    Usage: single_file_script [OPTIONS] [FOLDER]
    
    Arguments:
      [FOLDER]  Specify the root directory or uses current directory if not provided [default: .]
    
    Options:
          --allow-dirty    Does not return an error for dirty files nor generate the list of said files
          --allow-no-vcs   This option basically disables checking. If true no checks are done. (Not even if the `path`
                           exists)
          --allow-staged   Does not return an error for staged files nor generate the list of said files
      -o, --optional-flag  A boolean flag that is set to true if the argument is provided
          --mode <MODE>    Included to give an example for an enum [default: cat] [possible values: bird, cat, dog]
      -h, --help           Print help (see more with '--help')
      -V, --version        Print version