Skip to main content

#
pacman/
pacman.rs

    1use clap::{Arg, ArgAction, Command};
    2
    3fn cli() -> Command {
    4    Command::new("pacman")
    5        .about("package manager utility")
    6        .version("5.2.1")
    7        .subcommand_required(true)
    8        .arg_required_else_help(true)
    9        // Query subcommand
    10        //
    11        // Only a few of its arguments are implemented below.
    12        .subcommand(
    13            Command::new("query")
    14                .short_flag('Q')
    15                .long_flag("query")
    16                .about("Query the package database.")
    17                .arg(
    18                    Arg::new("search")
    19                        .short('s')
    20                        .long("search")
    21                        .help("search locally installed packages for matching strings")
    22                        .conflicts_with("info")
    23                        .action(ArgAction::Set)
    24                        .num_args(1..),
    25                )
    26                .arg(
    27                    Arg::new("info")
    28                        .long("info")
    29                        .short('i')
    30                        .conflicts_with("search")
    31                        .help("view package information")
    32                        .action(ArgAction::Set)
    33                        .num_args(1..),
    34                ),
    35        )
    36        // Sync subcommand
    37        //
    38        // Only a few of its arguments are implemented below.
    39        .subcommand(
    40            Command::new("sync")
    41                .short_flag('S')
    42                .long_flag("sync")
    43                .about("Synchronize packages.")
    44                .arg(
    45                    Arg::new("search")
    46                        .short('s')
    47                        .long("search")
    48                        .conflicts_with("info")
    49                        .action(ArgAction::Set)
    50                        .num_args(1..)
    51                        .help("search remote repositories for matching strings"),
    52                )
    53                .arg(
    54                    Arg::new("info")
    55                        .long("info")
    56                        .conflicts_with("search")
    57                        .short('i')
    58                        .action(ArgAction::SetTrue)
    59                        .help("view package information"),
    60                )
    61                .arg(
    62                    Arg::new("package")
    63                        .help("packages")
    64                        .required_unless_present("search")
    65                        .action(ArgAction::Set)
    66                        .num_args(1..),
    67                ),
    68        )
    69}
    70
    71fn main() {
    72    let matches = cli().get_matches();
    73
    74    match matches.subcommand() {
    75        Some(("sync", sync_matches)) => {
    76            if sync_matches.contains_id("search") {
    77                let packages: Vec<_> = sync_matches
    78                    .get_many::<String>("search")
    79                    .expect("contains_id")
    80                    .map(|s| s.as_str())
    81                    .collect();
    82                let values = packages.join(", ");
    83                println!("Searching for {values}...");
    84                return;
    85            }
    86
    87            let packages: Vec<_> = sync_matches
    88                .get_many::<String>("package")
    89                .expect("is present")
    90                .map(|s| s.as_str())
    91                .collect();
    92            let values = packages.join(", ");
    93
    94            if sync_matches.get_flag("info") {
    95                println!("Retrieving info for {values}...");
    96            } else {
    97                println!("Installing {values}...");
    98            }
    99        }
    100        Some(("query", query_matches)) => {
    101            if let Some(packages) = query_matches.get_many::<String>("info") {
    102                let comma_sep = packages.map(|s| s.as_str()).collect::<Vec<_>>().join(", ");
    103                println!("Retrieving info for {comma_sep}...");
    104            } else if let Some(queries) = query_matches.get_many::<String>("search") {
    105                let comma_sep = queries.map(|s| s.as_str()).collect::<Vec<_>>().join(", ");
    106                println!("Searching Locally for {comma_sep}...");
    107            } else {
    108                println!("Displaying all locally installed packages...");
    109            }
    110        }
    111        _ => unreachable!(), // If all subcommands are defined above, anything else is unreachable
    112    }
    113}
    114
    115#[cfg(all(test, feature = "help", feature = "usage"))]
    116mod tests {
    117    use super::*;
    118
    119    #[test]
    120    fn help_output_is_stable() {
    121        snapbox::assert_data_eq!(
    122            render_reference(cli()),
    123            snapbox::file!["snapshots/pacman.txt"].raw()
    124        );
    125    }
    126
    127    fn render_reference(mut command: Command) -> String {
    128        command = command.term_width(0);
    129        command.build();
    130
    131        let mut buffer = String::new();
    132        write_help(&mut buffer, &mut command, String::new());
    133
    134        buffer
    135    }
    136
    137    fn write_help(buffer: &mut String, cmd: &mut Command, mut path: String) {
    138        let header = if path.is_empty() { "#" } else { "##" };
    139        path.push(' ');
    140        path.push_str(cmd.get_name());
    141
    142        buffer.push_str(header);
    143        buffer.push_str(&path);
    144        buffer.push_str("\n\n");
    145        buffer.push_str(&cmd.render_long_help().to_string());
    146
    147        let has_generated_help = !cmd.is_disable_help_subcommand_set();
    148        for subcommand in cmd.get_subcommands_mut() {
    149            // Generated `help` nodes proxy other commands.
    150            if has_generated_help && subcommand.get_name() == "help" {
    151                continue;
    152            }
    153
    154            buffer.push('\n');
    155            write_help(buffer, subcommand, path.clone());
    156        }
    157    }
    158}