use anyhow::{bail, Result};
use clap::Parser;
use directories::BaseDirs;
use std::path::PathBuf;
pub const VERSION: &str = env!("CARGO_PKG_VERSION");
#[derive(Parser)]
#[command(author = "John-John Tedro <udoprog@tedro.se>")]
pub struct Opts {
#[arg(long, name = "dir")]
pub root: Option<PathBuf>,
#[arg(long, name = "url")]
pub init: Option<String>,
#[arg(long)]
pub paths: bool,
#[arg(long)]
pub force: bool,
#[arg(long)]
pub debug: bool,
#[arg(long)]
pub non_interactive: bool,
#[arg(long)]
pub updates_only: bool,
}
pub fn opts() -> Result<Opts> {
let opts = Opts::try_parse()?;
Ok(opts)
}
impl Opts {
pub fn root(&self, base_dirs: Option<&BaseDirs>) -> Result<PathBuf> {
match self.root.as_ref() {
Some(root) => Ok(root.to_owned()),
None => match base_dirs {
Some(base_dirs) => Ok(base_dirs.config_dir().join("quickcfg")),
None => bail!("No base directories available"),
},
}
}
pub fn prompt(&self, question: &str, default: bool) -> Result<bool> {
use std::io::{self, Write};
if self.non_interactive {
return Ok(default);
}
let stdin = io::stdin();
let mut stdout = io::stdout();
let mut input = String::new();
let p = if default { "[Y/n]" } else { "[y/N]" };
loop {
write!(stdout, "{} {} ", question, p)?;
stdout.flush()?;
input.clear();
stdin.read_line(&mut input)?;
match input.to_lowercase().as_str().trim() {
"" => return Ok(default),
"y" | "ye" | "yes" => return Ok(true),
"n" | "no" => return Ok(false),
_ => {
writeln!(stdout, "Please response with 'yes' or 'no' (or 'y' or 'n')")?;
}
}
}
}
pub fn input(&self, prompt: &str) -> Result<Option<String>> {
use std::io::{self, Write};
if self.non_interactive {
return Ok(None);
}
let stdin = io::stdin();
let mut stdout = io::stdout();
write!(stdout, "{} ", prompt)?;
stdout.flush()?;
let mut input = String::new();
stdin.read_line(&mut input)?;
Ok(Some(input.trim().to_string()))
}
}