use std::path::PathBuf;
use clap::{command, Parser, Subcommand, ValueEnum};
use crate::{
config::{Configuration, FilePattern},
extra_keys::ExtraKey,
};
#[derive(Parser, Debug, Clone)]
#[command(author, version, about, long_about = None)]
pub struct Cli {
#[arg(long, hide = true)]
pub markdown_help: bool,
#[command(subcommand)]
pub command: Commands,
}
#[allow(clippy::struct_excessive_bools)]
#[derive(Parser, Debug, Clone)]
pub struct CommonArgs {
#[arg(long, short)]
pub config: Option<PathBuf>,
#[arg(long, conflicts_with = "config")]
pub isolated: bool,
#[arg(long)]
pub allow_no_notebooks: bool,
#[arg(long, value_delimiter = ',')]
pub extra_keys: Option<Vec<ExtraKey>>,
#[arg(long, overrides_with("keep_empty_cells"))]
pub drop_empty_cells: bool,
#[arg(long, overrides_with("drop_empty_cells"), hide = true)]
pub keep_empty_cells: bool,
#[arg(long, overrides_with("drop_output"))]
pub keep_output: bool,
#[arg(long, overrides_with("keep_output"), hide = true)]
pub drop_output: bool,
#[arg(long, overrides_with("drop_count"))]
pub keep_count: bool,
#[arg(long, overrides_with("keep_count"), hide = true)]
pub drop_count: bool,
#[arg(long, overrides_with("keep_id"))]
pub drop_id: bool,
#[arg(long, overrides_with("drop_id"), hide = true)]
pub keep_id: bool,
#[arg(long, overrides_with("keep_init_cell"))]
pub strip_init_cell: bool,
#[arg(long, overrides_with("strip_init_cell"), hide = true)]
pub keep_init_cell: bool,
#[arg(long, overrides_with("keep_kernel_info"))]
pub strip_kernel_info: bool,
#[arg(long, overrides_with("strip_kernel_info"), hide = true)]
pub keep_kernel_info: bool,
#[arg(long, value_delimiter = ',')]
pub drop_tagged_cells: Option<Vec<String>>,
#[arg(long, value_delimiter = ',')]
pub keep_keys: Option<Vec<ExtraKey>>,
#[arg(long, value_delimiter = ',')]
pub exclude: Option<Vec<FilePattern>>,
#[arg(long, value_delimiter = ',')]
pub extend_exclude: Option<Vec<FilePattern>>,
}
#[derive(Subcommand, Debug, Clone)]
pub enum Commands {
Install(InstallCommand),
CleanAll(CleanAllCommand),
Check(CheckCommand),
Clean(CleanCommand),
Uninstall(UninstallCommand),
CheckInstall(CheckInstallCommand),
ShowConfig(ShowConfigCommand),
Record(RecordCommand),
#[clap(hide(true))]
Smudge(SmudgeCommand),
#[command(subcommand)]
Hook(HookCommands),
}
#[derive(Subcommand, Debug, Clone)]
pub enum HookCommands {
CheckLargeFiles(CheckLargeFilesCommand),
}
#[derive(Clone, Debug, Parser)]
pub struct CheckLargeFilesCommand {
pub filenames: Vec<PathBuf>,
#[arg(long, action)]
pub enforce_all: bool,
#[arg(long("maxkb"))]
pub maxkb: Option<u64>,
#[arg(long, short)]
pub config: Option<PathBuf>,
#[arg(long, conflicts_with = "config")]
pub isolated: bool,
}
#[derive(Clone, Debug, Parser)]
pub struct ShowConfigCommand {
#[arg(long, overrides_with("no_show_defaults"))]
pub show_all: bool,
#[arg(long, overrides_with("show_all"), hide = true)]
pub no_show_defaults: bool,
#[clap(flatten)]
pub common: CommonArgs,
}
#[derive(Clone, Debug, Parser)]
pub struct CheckCommand {
pub files: Vec<PathBuf>,
#[arg(long, short)]
pub output_format: Option<OutputFormat>,
#[clap(flatten)]
pub common: CommonArgs,
}
#[derive(Clone, Debug, Parser)]
pub struct CleanCommand {
pub file: PathBuf,
#[arg(long, short)]
pub textconv: bool,
#[clap(flatten)]
pub common: CommonArgs,
}
#[derive(Clone, Debug, Parser)]
pub struct CleanAllCommand {
pub files: Vec<PathBuf>,
#[arg(long, short)]
pub dry_run: bool,
#[arg(long, short)]
pub yes: bool,
#[clap(flatten)]
pub common: CommonArgs,
}
#[derive(Clone, Debug, ValueEnum, Copy, Default)]
pub enum OutputFormat {
#[default]
Text,
Json,
}
#[derive(Clone, Debug, Parser)]
pub struct InstallCommand {
#[clap(value_enum)]
pub config_type: GitConfigType,
#[arg(long, short)]
pub git_config_file: Option<PathBuf>,
#[arg(long, short)]
pub attribute_file: Option<PathBuf>,
}
#[derive(Clone, Debug, Parser)]
pub struct UninstallCommand {
#[clap(value_enum)]
pub config_type: GitConfigType,
#[arg(long, short)]
pub git_config_file: Option<PathBuf>,
#[arg(long, short)]
pub attribute_file: Option<PathBuf>,
}
#[derive(Clone, Debug, Parser)]
pub struct RecordCommand {
pub path: Option<PathBuf>,
#[arg(long)]
pub remove: Vec<PathBuf>,
#[arg(long)]
pub clear: bool,
#[arg(long)]
pub sync: bool,
#[clap(flatten)]
pub common: CommonArgs,
}
#[derive(Clone, Debug, Parser)]
pub struct CheckInstallCommand {
#[arg(long)]
pub exit_zero: bool,
#[clap(value_enum)]
pub config_type: Option<GitConfigType>,
}
#[derive(Clone, Debug, Parser)]
pub struct SmudgeCommand {
pub path: String,
}
#[derive(Clone, Debug, ValueEnum, Copy)]
pub enum GitConfigType {
System,
Global,
Local,
}
#[derive(Clone, Debug, Default)]
pub struct ConfigOverrides {
pub strip_kernel_info: Option<bool>,
pub extra_keys: Option<Vec<ExtraKey>>,
pub drop_empty_cells: Option<bool>,
pub drop_output: Option<bool>,
pub drop_count: Option<bool>,
pub drop_id: Option<bool>,
pub strip_init_cell: Option<bool>,
pub drop_tagged_cells: Option<Vec<String>>,
pub keep_keys: Option<Vec<ExtraKey>>,
pub exclude: Option<Vec<FilePattern>>,
pub extend_exclude: Option<Vec<FilePattern>>,
}
pub struct Args {
pub config: Option<PathBuf>,
pub isolated: bool,
pub allow_no_notebooks: bool,
}
pub fn resolve_bool_arg(yes: bool, no: bool) -> Option<bool> {
match (yes, no) {
(true, false) => Some(true),
(false, true) => Some(false),
(false, false) => None,
(..) => unreachable!("Clap should make this impossible"),
}
}
impl CommonArgs {
pub fn partition(self) -> (Args, ConfigOverrides) {
(
Args {
config: self.config,
allow_no_notebooks: self.allow_no_notebooks,
isolated: self.isolated,
},
ConfigOverrides {
extra_keys: self.extra_keys,
drop_empty_cells: resolve_bool_arg(self.drop_empty_cells, self.keep_empty_cells),
drop_output: resolve_bool_arg(self.drop_output, self.keep_output),
drop_count: resolve_bool_arg(self.drop_count, self.keep_count),
drop_id: resolve_bool_arg(self.drop_id, self.keep_id),
drop_tagged_cells: self.drop_tagged_cells,
strip_init_cell: resolve_bool_arg(self.strip_init_cell, self.keep_init_cell),
keep_keys: self.keep_keys,
extend_exclude: self.extend_exclude,
exclude: self.exclude,
strip_kernel_info: resolve_bool_arg(self.strip_kernel_info, self.keep_kernel_info),
},
)
}
}
impl ConfigOverrides {
pub fn override_config(&self, mut config: Configuration) -> Configuration {
if let Some(extra_keys) = &self.extra_keys {
config.extra_keys = Some(extra_keys.clone());
}
if let Some(drop_count) = &self.drop_count {
config.drop_count = Some(*drop_count);
}
if let Some(drop_empty_cells) = &self.drop_empty_cells {
config.drop_empty_cells = Some(*drop_empty_cells);
}
if let Some(drop_id) = &self.drop_id {
config.drop_id = Some(*drop_id);
}
if let Some(drop_output) = &self.drop_output {
config.drop_output = Some(*drop_output);
}
if let Some(drop_tagged_cells) = &self.drop_tagged_cells {
config.drop_tagged_cells = Some(drop_tagged_cells.clone());
}
if let Some(strip_init_cell) = &self.strip_init_cell {
config.strip_init_cell = Some(*strip_init_cell);
}
if let Some(keep_keys) = &self.keep_keys {
config.keep_keys = Some(keep_keys.clone());
}
if let Some(exclude) = &self.exclude {
config.exclude = Some(exclude.clone());
}
if let Some(extend_exclude) = &self.extend_exclude {
config.extend_exclude.extend(extend_exclude.clone());
}
if let Some(strip_kernel_info) = &self.strip_kernel_info {
config.strip_kernel_info = Some(*strip_kernel_info);
}
config
}
}