1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
use super::VersionCommand;
use crate::{version::VersionFile, VersionError};
use clap::{
    builder::{styling::AnsiColor, Styles},
    value_parser, Command, CommandFactory, Parser,
};
use clap_complete::{generate, Generator, Shell};
use std::io;

const STYLE: Styles = Styles::styled()
    .header(AnsiColor::Yellow.on_default())
    .error(AnsiColor::Red.on_default())
    .usage(AnsiColor::Green.on_default())
    .literal(AnsiColor::BrightBlue.on_default())
    .placeholder(AnsiColor::Blue.on_default())
    .valid(AnsiColor::Cyan.on_default())
    .invalid(AnsiColor::Magenta.on_default());

#[derive(Parser, Debug, Clone)]
#[command(arg_required_else_help(true), styles = STYLE, name = "version")]
/// A tool for managing the version of a project
pub struct Cli {
    #[command(subcommand)]
    pub command: Option<VersionCommand>,
    #[arg(value_parser = value_parser!(Shell), exclusive = true)]
    /// Generate shell completions
    pub generator: Option<Shell>,
}

impl Cli {
    pub fn run(&self, version: &mut VersionFile) -> Result<(), VersionError> {
        if let Some(generator) = self.generator {
            let mut cmd = Cli::command();
            Self::print_completions(generator, &mut cmd)
        } else if let Some(command) = &self.command {
            command.run(version)
        } else {
            Err(VersionError::NoCommand)
        }
    }

    fn print_completions<G: Generator>(gen: G, cmd: &mut Command) -> Result<(), VersionError> {
        generate(gen, cmd, cmd.get_name().to_string(), &mut io::stdout());
        Ok(())
    }
}