use std::path::PathBuf;
use clap::{Parser, Subcommand};
use clap_complete::Shell;
/// A small dotfile manager.
#[derive(Debug, Parser, Default, Clone)]
#[clap(author, version, about, long_about = None)]
pub struct Options {
/// Location of the global configuration
#[clap(
short,
long,
value_parser,
default_value = ".dotter/global.toml",
global = true
)]
pub global_config: PathBuf,
/// Location of the local configuration
#[clap(
short,
long,
value_parser,
default_value = ".dotter/local.toml",
global = true
)]
pub local_config: PathBuf,
/// Location of cache file
#[clap(long, value_parser, default_value = ".dotter/cache.toml")]
pub cache_file: PathBuf,
/// Directory to cache into.
#[clap(long, value_parser, default_value = ".dotter/cache")]
pub cache_directory: PathBuf,
/// Location of optional pre-deploy hook
#[clap(long, value_parser, default_value = ".dotter/pre_deploy.sh")]
pub pre_deploy: PathBuf,
/// Location of optional post-deploy hook
#[clap(long, value_parser, default_value = ".dotter/post_deploy.sh")]
pub post_deploy: PathBuf,
/// Location of optional pre-undeploy hook
#[clap(long, value_parser, default_value = ".dotter/pre_undeploy.sh")]
pub pre_undeploy: PathBuf,
/// Location of optional post-undeploy hook
#[clap(long, value_parser, default_value = ".dotter/post_undeploy.sh")]
pub post_undeploy: PathBuf,
/// Dry run - don't do anything, only print information.
/// Implies -v at least once
#[clap(short = 'd', long = "dry-run", parse(from_flag = std::ops::Not::not), global = true)]
pub act: bool,
/// Verbosity level - specify up to 3 times to get more detailed output.
/// Specifying at least once prints the differences between what was before and after Dotter's run
#[clap(short = 'v', long = "verbose", action = clap::ArgAction::Count, global = true)]
pub verbosity: u8,
/// Quiet - only print errors
#[clap(short, long, value_parser, global = true)]
pub quiet: bool,
/// Force - instead of skipping, overwrite target files if their content is unexpected.
/// Overrides --dry-run.
#[clap(short, long, value_parser, global = true)]
pub force: bool,
/// Assume "yes" instead of prompting when removing empty directories
#[clap(short = 'y', long = "noconfirm", parse(from_flag = std::ops::Not::not), global = true)]
pub interactive: bool,
/// Take standard input as an additional files/variables patch, added after evaluating
/// `local.toml`. Assumes --noconfirm flag because all of stdin is taken as the patch.
#[clap(short, long, value_parser, global = true)]
pub patch: bool,
/// Amount of lines that are printed before and after a diff hunk.
#[clap(long, value_parser, default_value = "3")]
pub diff_context_lines: usize,
#[clap(subcommand)]
pub action: Option<Action>,
}
#[derive(Debug, Clone, Copy, Subcommand)]
pub enum Action {
/// Deploy the files to their respective targets. This is the default subcommand.
Deploy,
/// Delete all deployed files from their target locations.
/// Note that this operates on all files that are currently in cache.
Undeploy,
/// Initialize global.toml with a single package containing all the files in the current
/// directory pointing to a dummy value and a local.toml that selects that package.
Init,
/// Run continuously, watching the repository for changes and deploying as soon as they
/// happen. Can be ran with `--dry-run`
Watch,
/// Generate shell completions
GenCompletions {
/// Set the shell for generating completions [values: bash, elvish, fish, powerShell, zsh]
#[clap(long, short)]
shell: Shell,
},
}
impl Default for Action {
fn default() -> Self {
Action::Deploy
}
}
pub fn get_options() -> Options {
let mut opt = Options::parse();
if !opt.act {
opt.verbosity = std::cmp::max(opt.verbosity, 1);
}
opt.verbosity = std::cmp::min(3, opt.verbosity);
if opt.patch {
opt.interactive = false;
}
opt
}