use std::{
env,
ffi::OsString,
path::{Path, PathBuf},
sync::LazyLock,
};
use clap::{ArgAction, Args, Parser, Subcommand};
use clap_verbosity_flag::Verbosity;
#[derive(Debug, Parser)]
#[command(version)]
pub struct Config {
#[clap(flatten)]
pub verbose: Verbosity,
#[arg(
short, long,
default_value_os_t = xdg_config_path("nushell/completions/definitions")
)]
pub output_dir: PathBuf,
#[arg(
short, long,
default_value_os_t = xdg_config_path("nushell/completions/patches")
)]
pub patch_dir: PathBuf,
pub sources: Vec<OsString>,
#[arg(
long = "no-patch",
action = ArgAction::SetFalse,
default_value_t = true,
help = "disable patching phase"
)]
pub patch: bool,
#[arg(
long = "no-convert",
action = ArgAction::SetFalse,
default_value_t = true,
help = "disable conversion phase"
)]
pub convert: bool,
#[arg(
long = "no-update-patches",
action = ArgAction::SetFalse,
default_value_t = true,
help = "skip updating the standard patch-set from github"
)]
pub update_patch_set: bool,
#[command(subcommand)]
pub patches: Option<PatchesCommand>,
#[arg(short, long)]
pub install: bool,
#[arg(long, default_value_os_t = xdg_config_path("nushell/env.nu"))]
pub install_location: PathBuf,
#[arg(long)]
pub fail_fast: bool,
}
#[derive(Debug, Subcommand)]
pub enum PatchesCommand {
Patches(PatchesSubCommand),
}
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Args, Debug)]
pub struct PatchesSubCommand {
#[command(subcommand)]
action: PatchesSubCommandAction,
}
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Subcommand, Debug)]
pub enum PatchesSubCommandAction {
Generate(PatchesGenerateOptions),
}
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Args, Debug)]
pub struct PatchesGenerateOptions {
#[arg(short, long, default_value_os_t = xdg_config_path("nushell/completions/definitions"))]
pub from: PathBuf,
#[arg(short, long, default_value_os_t = xdg_config_path("nushell/completions/patches"))]
pub to: PathBuf,
pub sources: Vec<OsString>,
}
pub static CONFIG: LazyLock<Config> = LazyLock::new(Config::parse);
impl Config {
pub(crate) fn verbose() -> &'static Verbosity {
&CONFIG.verbose
}
pub(crate) fn output_dir() -> &'static Path {
CONFIG.output_dir.as_path()
}
pub(crate) fn sources() -> &'static Vec<OsString> {
&CONFIG.sources
}
pub(crate) fn patch_dir() -> &'static Path {
CONFIG.patch_dir.as_path()
}
pub(crate) fn patch() -> bool {
CONFIG.patch
}
pub(crate) fn convert() -> bool {
CONFIG.convert
}
pub(crate) fn fail_fast() -> bool {
CONFIG.fail_fast
}
pub(crate) fn update_patch_set() -> bool {
CONFIG.update_patch_set
}
pub(crate) fn install() -> Option<&'static Path> {
if CONFIG.install {
Some(&CONFIG.install_location)
} else {
None
}
}
pub(crate) fn generate_patches() -> Option<&'static PatchesGenerateOptions> {
CONFIG.patches.as_ref().map(|arg| {
let PatchesCommand::Patches(arg) = arg;
let PatchesSubCommandAction::Generate(arg) = &arg.action;
arg
})
}
pub(crate) fn imports_location() -> PathBuf {
Self::output_dir()
.parent()
.expect("config output dir has parent")
.join("imports.nu")
}
}
fn xdg_config_path(subpath: impl AsRef<Path>) -> PathBuf {
if let Ok(dir) = env::var("XDG_CONFIG_HOME").map(PathBuf::from) {
dir.join(subpath)
} else {
env::var("HOME")
.map(PathBuf::from)
.expect("$HOME environment variable to be set")
.join(".config")
.join(subpath)
}
}