mod paths;
pub(crate) mod start_time;
use crate::opts::paths::TempDir;
use crate::opts::start_time::StartTime;
use camino::Utf8PathBuf;
use clap::Parser;
use clap::ValueEnum;
use clap::ValueHint;
use clap::builder::styling::AnsiColor;
use clap::builder::styling::Styles;
use clap_complete::Shell;
use serde_derive::Deserialize;
use serde_derive::Serialize;
use std::ffi::OsString;
pub(crate) const FALLBACK_CONFIG_PATH: &str = "dotfiles/.config/up/up.yaml";
pub(crate) const LATEST_RELEASE_URL: &str =
"https://api.github.com/repos/gibfahn/up/releases/latest";
#[cfg(target_os = "linux")]
pub(crate) const SELF_UPDATE_URL: &str =
"https://github.com/gibfahn/up/releases/latest/download/up-linux";
#[cfg(target_os = "macos")]
pub(crate) const SELF_UPDATE_URL: &str =
"https://github.com/gibfahn/up/releases/latest/download/up-darwin";
const STYLES: Styles = Styles::styled()
.header(AnsiColor::Green.on_default().bold())
.usage(AnsiColor::Green.on_default().bold())
.literal(AnsiColor::Blue.on_default().bold())
.placeholder(AnsiColor::Cyan.on_default());
#[must_use]
pub fn parse() -> Opts {
Opts::parse()
}
#[allow(clippy::doc_markdown, rustdoc::bare_urls)]
#[derive(Debug, Clone, Parser)]
#[clap(version, styles = STYLES)]
pub struct Opts {
#[clap(
long,
short = 'l',
default_value = "up=info",
env = "RUST_LOG",
alias = "log-level"
)]
pub log: String,
#[clap(long, env = "UP_TEMP_DIR", default_value_t, value_hint = ValueHint::DirPath, alias = "up-dir")]
pub temp_dir: TempDir,
#[clap(long, default_value = "trace", env = "FILE_RUST_LOG")]
pub file_log_level: String,
#[clap(long, default_value = "auto", ignore_case = true, value_enum)]
pub color: Color,
#[clap(long, short = 'c', default_value = "$XDG_CONFIG_HOME/up/up.yaml", value_hint = ValueHint::FilePath)]
pub(crate) config: String,
#[clap(long, hide(true), default_value_t)]
pub start_time: StartTime,
#[clap(subcommand)]
pub(crate) cmd: Option<SubCommand>,
}
#[derive(Debug, ValueEnum, Clone)]
pub enum Color {
Auto,
Always,
Never,
}
#[derive(Debug, Clone, Parser)]
pub(crate) enum SubCommand {
Run(RunOptions),
Link(LinkOptions),
Git(GitOptions),
Defaults(DefaultsOptions),
Generate(GenerateOptions),
Self_(UpdateSelfOptions),
Doc(DocOptions),
List(RunOptions),
Faketty(FakettyOptions),
}
#[derive(Debug, Clone, Parser, Default)]
pub(crate) struct RunOptions {
#[clap(short, long)]
pub(crate) bootstrap: bool,
#[clap(short, long)]
pub(crate) keep_going: bool,
#[clap(short = 'f', long, value_hint = ValueHint::Url)]
pub(crate) fallback_url: Option<String>,
#[clap(
short = 'p',
long,
default_value = FALLBACK_CONFIG_PATH,
value_hint = ValueHint::FilePath
)]
pub(crate) fallback_path: Utf8PathBuf,
#[clap(short = 't', long, value_delimiter = ',')]
pub(crate) tasks: Option<Vec<String>>,
#[clap(long)]
pub(crate) console: Option<bool>,
#[clap(long, value_delimiter = ',')]
pub(crate) exclude_tasks: Option<Vec<String>>,
}
#[derive(Debug, Clone, Parser, Default, Serialize, Deserialize)]
pub(crate) struct LinkOptions {
#[clap(short = 'f', long = "from", default_value = "~/code/dotfiles", value_hint = ValueHint::DirPath)]
pub(crate) from_dir: String,
#[clap(short = 't', long = "to", default_value = "~", value_hint = ValueHint::DirPath)]
pub(crate) to_dir: String,
}
#[derive(Debug, Clone, Default, Parser)]
pub struct GitOptions {
#[clap(long, value_hint = ValueHint::Url)]
pub git_url: String,
#[clap(long, value_hint = ValueHint::DirPath)]
pub git_path: Utf8PathBuf,
#[clap(long, default_value = crate::tasks::git::DEFAULT_REMOTE_NAME)]
pub remote: String,
#[clap(long)]
pub branch: Option<String>,
#[clap(long)]
pub prune: bool,
}
#[derive(Debug, Clone, Parser)]
pub(crate) struct GenerateOptions {
#[clap(subcommand)]
pub(crate) lib: Option<GenerateLib>,
}
#[derive(Debug, Clone, Parser)]
pub(crate) struct SchemaOptions {
pub(crate) path: Option<Utf8PathBuf>,
}
#[derive(Debug, Clone, Parser)]
pub struct ManpagesOptions {
#[clap(long, value_hint = ValueHint::DirPath)]
pub(crate) output_dir: Utf8PathBuf,
}
#[derive(Debug, Clone, Parser, Serialize, Deserialize)]
pub(crate) struct UpdateSelfOptions {
#[clap(long, default_value = SELF_UPDATE_URL, value_hint = ValueHint::Url)]
pub(crate) url: String,
#[clap(long)]
pub(crate) always_update: bool,
}
#[derive(Debug, Clone, Parser)]
pub(crate) struct DocOptions {
#[clap(subcommand)]
pub(crate) subcmd: DocSubcommand,
}
#[derive(Debug, Clone, Parser)]
pub(crate) enum DocSubcommand {
Completions(CompletionsOptions),
Schema(SchemaOptions),
#[clap(visible_alias = "man")]
Manpages(ManpagesOptions),
Markdown,
}
#[derive(Debug, Clone, Parser)]
pub(crate) struct CompletionsOptions {
#[clap(value_enum)]
pub(crate) shell: Shell,
}
impl Default for UpdateSelfOptions {
fn default() -> Self {
Self {
url: SELF_UPDATE_URL.to_owned(),
always_update: false,
}
}
}
#[derive(Debug, Clone, Parser)]
pub(crate) enum GenerateLib {
Git(GenerateGitConfig),
Defaults(GenerateDefaultsConfig),
}
#[derive(Debug, Clone, Parser, Serialize, Deserialize)]
pub struct GenerateGitConfig {
#[clap(long, value_hint = ValueHint::FilePath)]
pub(crate) path: Utf8PathBuf,
#[clap(long, default_value = "~", value_hint = ValueHint::DirPath)]
pub(crate) search_paths: Vec<Utf8PathBuf>,
#[clap(long)]
pub(crate) excludes: Option<Vec<String>>,
#[clap(long)]
pub(crate) prune: bool,
#[clap(long)]
pub(crate) remote_order: Vec<String>,
}
#[derive(Debug, Clone, Parser, Serialize, Deserialize)]
pub struct GenerateDefaultsConfig {
#[clap(long, value_hint = ValueHint::FilePath)]
pub(crate) path: Utf8PathBuf,
}
#[derive(Debug, Clone, Parser, Serialize, Deserialize)]
pub struct DefaultsOptions {
#[clap(long = "currentHost")]
pub(crate) current_host: bool,
#[clap(subcommand)]
pub(crate) subcommand: DefaultsSubcommand,
}
#[derive(Debug, Clone, Parser, Serialize, Deserialize)]
pub enum DefaultsSubcommand {
Read(DefaultsReadOptions),
Write(DefaultsWriteOptions),
}
#[derive(Debug, Clone, Parser, Serialize, Deserialize)]
pub struct DefaultsReadOptions {
#[clap(short = 'g', long = "globalDomain")]
pub(crate) global_domain: bool,
pub(crate) domain: Option<String>,
pub(crate) key: Option<String>,
}
#[derive(Debug, Clone, Parser, Serialize, Deserialize)]
pub struct DefaultsWriteOptions {
#[clap(short = 'g', long = "globalDomain")]
pub(crate) global_domain: bool,
pub(crate) domain: String,
pub(crate) key: String,
pub(crate) value: Option<String>,
}
#[derive(Debug, Parser, Default, Clone)]
pub struct FakettyOptions {
#[clap(
num_args(1..),
value_parser(clap::builder::OsStringValueParser::new()),
trailing_var_arg(true),
)]
pub(crate) program: Vec<OsString>,
}