use std::path::PathBuf;
use clap::{
builder::{
styling::{AnsiColor, Effects},
Styles,
},
Parser,
};
use clap_complete::Shell;
use url::Url;
use crate::{context::Verbosity, util};
pub const ENV_CONFIG_DIR: &str = "RPK_CONFIG_DIR";
pub const ENV_DATA_DIR: &str = "RPK_DATA_DIR";
pub const ENV_CACHE_DIR: &str = "RPK_CACHE_DIR";
pub const ENV_BIN_DIR: &str = "RPK_BIN_DIR";
#[derive(Debug, PartialEq, Eq, Parser)]
#[clap(author, about)]
#[clap(version = util::CRATE_VERSION)]
#[clap(long_version = util::CRATE_LONG_VERSION)]
#[clap(
styles(Styles::styled()
.header(AnsiColor::Yellow.on_default() | Effects::BOLD)
.usage(AnsiColor::Yellow.on_default() | Effects::BOLD)
.literal(AnsiColor::Green.on_default() | Effects::BOLD)
.placeholder(AnsiColor::Cyan.on_default())
)
)]
pub struct Opt {
#[clap(long, short, global = true)]
pub quiet: bool,
#[clap(long, short, global = true)]
pub verbose: bool,
#[clap(long, value_name = "PATH", env = ENV_CONFIG_DIR)]
pub config_dir: Option<PathBuf>,
#[clap(long, value_name = "PATH", env = ENV_DATA_DIR)]
pub data_dir: Option<PathBuf>,
#[clap(long, value_name = "PATH", env = ENV_CACHE_DIR)]
pub cache_dir: Option<PathBuf>,
#[clap(long, value_name = "PATH", env = ENV_BIN_DIR)]
pub bin_dir: Option<PathBuf>,
#[clap(subcommand)]
pub command: SubCommand,
}
#[derive(Debug, PartialEq, Eq, Parser)]
pub enum SubCommand {
Init {
#[clap(short, long, value_name = "URL")]
from: Option<Url>,
},
List,
Sync,
Add {
#[clap(value_name = "REPO")]
#[arg(value_parser = repo_parser)]
repo: (String, String),
#[clap(long, value_name = "NAME")]
name: Option<String>,
#[clap(long, value_name = "BIN", num_args = 0..)]
binary: Vec<String>,
#[clap(long, value_name = "VERSION")]
version: Option<String>,
#[clap(long, value_name = "DESC", long)]
desc: Option<String>,
},
Restore {
#[clap(value_name = "PKG")]
package: Option<String>,
},
Update {
#[clap(value_name = "PKG")]
package: Option<String>,
},
Search {
#[clap(value_name = "QUERY")]
query: String,
#[clap(long, value_name = "NUM", default_value = "10")]
top: u8,
},
Cleanup {
#[clap(long)]
cache: bool,
},
Env,
Completions {
#[clap(value_name = "SHELL", value_enum, required_unless_present = "list")]
shell: Option<Shell>,
#[clap(short, long, value_name = "DIR")]
dir: Option<PathBuf>,
#[clap(short, long, exclusive = true)]
list: bool,
},
Version,
}
impl Opt {
pub fn verbosity(&self) -> Verbosity {
if self.quiet {
Verbosity::Quiet
} else if self.verbose {
Verbosity::Verbose
} else {
Verbosity::Normal
}
}
}
fn repo_parser(repo: &str) -> Result<(String, String), String> {
match repo.split_once('/') {
Some((owner, repo)) => Ok((owner.to_owned(), repo.to_owned())),
None => Err("invalid repo format, should be: 'owner/repo'".into()),
}
}