#[derive(Debug, Clone, Default, clap::Args)]
pub struct BackupOpts {
#[arg(long, action = clap::ArgAction::SetTrue, conflicts_with = "no_backup", help_heading = "Backup")]
pub backup: Option<bool>,
#[arg(long, action = clap::ArgAction::SetTrue, help_heading = "Backup")]
pub no_backup: bool,
#[arg(long, action = clap::ArgAction::SetTrue, help_heading = "Backup")]
pub keep_backup: bool,
#[arg(long, help_heading = "Backup")]
pub retention: Option<u8>,
}
#[derive(Args, Debug)]
pub struct CountArgs {
#[arg(default_value = ".", value_hint = ValueHint::AnyPath)]
pub paths: Vec<PathBuf>,
#[arg(long, help = "Group counts by file extension", action = clap::ArgAction::SetTrue)]
pub by_extension: bool,
#[arg(long, help = "Sort by file size (top N)", action = clap::ArgAction::SetTrue)]
pub by_size: bool,
#[arg(long, default_value_t = crate::constants::DEFAULT_QUERY_TOP, help = "Number of top results (default constants::DEFAULT_QUERY_TOP)")]
pub top: usize,
#[arg(short = 'g', long, action = clap::ArgAction::Append, help = "Include files matching glob")]
pub include: Vec<String>,
#[arg(long, action = clap::ArgAction::Append, help = "Exclude files matching glob")]
pub exclude: Vec<String>,
}
#[derive(Debug, Clone, Copy, ValueEnum)]
pub enum DiffAlgorithm {
Myers,
Patience,
Lcs,
}
#[derive(Args, Debug)]
pub struct CopyArgs {
#[arg(value_hint = ValueHint::AnyPath)]
pub source: PathBuf,
#[arg(value_hint = ValueHint::AnyPath)]
pub target: PathBuf,
#[command(flatten)]
pub backup_opts: BackupOpts,
#[arg(short, long, help = "Overwrite destination if it exists", action = clap::ArgAction::SetTrue)]
pub force: bool,
#[arg(short, long, help = "Copy directories recursively", action = clap::ArgAction::SetTrue)]
pub recursive: bool,
#[arg(long, help = "Preserve timestamps and permissions", action = clap::ArgAction::SetTrue)]
pub preserve: bool,
#[arg(long, help = "Show what would be done without copying", action = clap::ArgAction::SetTrue)]
pub dry_run: bool,
#[arg(long, help = "Disable reflink optimization; force full byte copy", action = clap::ArgAction::SetTrue)]
pub no_reflink: bool,
#[arg(long, help = "Preserve extended attributes (xattr) on copy", action = clap::ArgAction::SetTrue)]
pub preserve_xattr: bool,
}
#[derive(Debug, Clone, Copy, ValueEnum, Default, PartialEq, Eq)]
pub enum DurabilityCli {
Full,
Fast,
#[default]
Auto,
}
impl From<DurabilityCli> for crate::platform::Durability {
fn from(v: DurabilityCli) -> Self {
match v {
DurabilityCli::Full => crate::platform::Durability::Full,
DurabilityCli::Fast => crate::platform::Durability::Fast,
DurabilityCli::Auto => crate::platform::Durability::Auto,
}
}
}
#[derive(Args, Debug)]
pub struct EditArgs {
#[arg(value_hint = ValueHint::FilePath)]
pub path: PathBuf,
#[arg(
long,
conflicts_with_all = ["old", "new", "old_file", "new_file"],
help = "Insert content from stdin after line N"
)]
pub after_line: Option<usize>,
#[arg(
long,
conflicts_with_all = ["old", "new", "old_file", "new_file"],
help = "Insert content from stdin before line N"
)]
pub before_line: Option<usize>,
#[arg(
long,
conflicts_with_all = ["old", "new", "old_file", "new_file"],
help = "Replace line range N:M with stdin content"
)]
pub range: Option<String>,
#[arg(long, help = "Delete line range N:M")]
pub delete_range: Option<String>,
#[arg(
long,
allow_hyphen_values = true,
conflicts_with_all = ["old", "new", "old_file", "new_file"],
help = "Insert stdin content after first match of text"
)]
pub after_match: Option<String>,
#[arg(
long,
allow_hyphen_values = true,
conflicts_with_all = ["old", "new", "old_file", "new_file"],
help = "Insert stdin content before first match of text"
)]
pub before_match: Option<String>,
#[arg(
long,
num_args = 2,
allow_hyphen_values = true,
conflicts_with_all = ["old", "new", "old_file", "new_file"],
help = "Replace content between two markers with stdin"
)]
pub between: Option<Vec<String>>,
#[arg(long, allow_hyphen_values = true, action = clap::ArgAction::Append, help = "Exact text to find (repeatable; for content >1KB or with special chars, prefer --old-file)")]
pub old: Vec<String>,
#[arg(long, allow_hyphen_values = true, action = clap::ArgAction::Append, help = "Replacement text for --old (repeatable; for content >1KB or with special chars, prefer --new-file)")]
pub new: Vec<String>,
#[arg(long, conflicts_with = "old", action = clap::ArgAction::Append,
help = "Read match text from file (repeatable; alternative to --old for large content)")]
#[arg(value_hint = ValueHint::AnyPath)]
pub old_file: Vec<PathBuf>,
#[arg(long, conflicts_with = "new", action = clap::ArgAction::Append,
help = "Read replacement text from file (repeatable; alternative to --new for large content)")]
#[arg(value_hint = ValueHint::AnyPath)]
pub new_file: Vec<PathBuf>,
#[arg(
long,
value_enum,
default_value_t = FuzzyMode::Auto,
help = "Fuzzy match mode: auto (default, mandatory) or aggressive; off is rejected since v0.1.30"
)]
pub fuzzy: FuzzyMode,
#[arg(
long,
conflicts_with_all = ["old", "new", "old_file", "new_file"],
help = "Read multiple edit operations as NDJSON from stdin (inherits --fuzzy mode)",
action = clap::ArgAction::SetTrue
)]
pub multi: bool,
#[arg(long, help = "Only edit if current checksum matches (optimistic lock)")]
pub expect_checksum: Option<String>,
#[arg(
long,
value_enum,
default_value_t = crate::line_endings::LineEnding::Auto,
help = "Normalize line endings: lf, crlf, cr, auto (preserve original)"
)]
pub line_ending: crate::line_endings::LineEnding,
#[arg(long, help = "Show what would be done without writing", action = clap::ArgAction::SetTrue)]
pub dry_run: bool,
#[arg(long, help = "Preserve original mtime (default: update mtime to now)", action = clap::ArgAction::SetTrue)]
pub preserve_timestamps: bool,
#[arg(
long,
help = "Apply matching --old/--new pairs and report the rest (default: all-or-nothing)",
action = clap::ArgAction::SetTrue
)]
pub partial: bool,
#[arg(long, help = "Override fuzzy similarity threshold (0.0-1.0)")]
pub fuzzy_threshold: Option<f64>,
#[arg(
long,
help = "Replace all occurrences of --old (default: fail if match is not unique)",
action = clap::ArgAction::SetTrue
)]
pub replace_all: bool,
#[arg(
long,
value_enum,
default_value_t = crate::wal::WalPolicy::Auto,
help = "WAL sidecar policy: auto (default), always, never (G119 L1)"
)]
pub wal_policy: crate::wal::WalPolicy,
#[command(flatten)]
pub backup_opts: BackupOpts,
#[arg(
long,
help = "Accept STATE_DRIFT between sequential edits (default: reject). For agent pipelines that chain edits.",
action = clap::ArgAction::SetTrue
)]
pub allow_sequential_drift: bool,
}
#[derive(Args, Debug)]
pub struct ListArgs {
#[arg(default_value = ".", value_hint = ValueHint::AnyPath)]
pub paths: Vec<PathBuf>,
#[arg(short = 'd', long, help = "Maximum directory depth")]
pub depth: Option<usize>,
#[arg(short = 'l', long, help = "Show size and modification time", action = clap::ArgAction::SetTrue)]
pub long: bool,
#[arg(long, help = "Group file counts by extension", action = clap::ArgAction::SetTrue)]
pub count_by_ext: bool,
#[arg(long, help = "Show all files including hidden", action = clap::ArgAction::SetTrue)]
pub all: bool,
#[arg(short = 'g', long, action = clap::ArgAction::Append, help = "Include files matching glob")]
pub include: Vec<String>,
#[arg(long, action = clap::ArgAction::Append, help = "Exclude files matching glob")]
pub exclude: Vec<String>,
}
#[derive(Args, Debug)]
pub struct RegexArgs {
#[arg(help = "Example strings (use -- before hyphenated examples)")]
pub examples: Vec<String>,
#[arg(long, help = "Read examples from stdin (one per line)", action = clap::ArgAction::SetTrue)]
pub stdin: bool,
#[arg(short = 'd', long, help = "Convert digits to \\d", action = clap::ArgAction::SetTrue)]
pub digits: bool,
#[arg(short = 'w', long, help = "Convert words to \\w", action = clap::ArgAction::SetTrue)]
pub words: bool,
#[arg(short = 's', long, help = "Convert whitespace to \\s", action = clap::ArgAction::SetTrue)]
pub spaces: bool,
#[arg(short = 'r', long, help = "Detect repetitions", action = clap::ArgAction::SetTrue)]
pub repetitions: bool,
#[arg(short = 'i', long, help = "Case-insensitive matching", action = clap::ArgAction::SetTrue)]
pub case_insensitive: bool,
#[arg(long, help = "Remove anchors (^ and $)", action = clap::ArgAction::SetTrue)]
pub no_anchors: bool,
}
#[derive(Args, Debug)]
pub struct BatchArgs {
#[arg(long, help = "Show what would be done without executing", action = clap::ArgAction::SetTrue)]
pub dry_run: bool,
#[arg(long, help = "Read manifest from file instead of stdin", value_hint = ValueHint::FilePath)]
pub file: Option<PathBuf>,
#[arg(
long,
help = "All-or-nothing: rollback all changes if any operation fails",
action = clap::ArgAction::SetTrue
)]
pub transaction: bool,
#[arg(long, help = "Print JSON Schema for the batch input manifest", action = clap::ArgAction::SetTrue)]
pub input_schema: bool,
#[arg(
long,
default_value_t = crate::constants::DEFAULT_LIST_LIMIT,
help = "Operations to buffer before emitting the summary line (default constants::DEFAULT_LIST_LIMIT)"
)]
pub batch_size: usize,
#[command(flatten)]
pub backup_opts: BackupOpts,
}
#[derive(Debug, Clone, Copy, ValueEnum, Default)]
pub enum PatchFormat {
#[default]
Auto,
Unified,
SearchReplace,
Full,
Markdown,
}
#[derive(Args, Debug)]
pub struct SetArgs {
#[arg(value_hint = ValueHint::FilePath)]
pub path: PathBuf,
pub key_path: String,
pub value: String,
#[command(flatten)]
pub backup_opts: BackupOpts,
#[arg(long, help = "Preserve original mtime/atime", action = clap::ArgAction::SetTrue)]
pub preserve_timestamps: bool,
}
#[derive(Args, Debug)]
pub struct CaseArgs {
#[arg(value_hint = ValueHint::AnyPath)]
pub paths: Vec<PathBuf>,
#[arg(
long = "subvert",
num_args = 2,
value_name = "OLD NEW",
required = true,
help = "Old and new identifier (repeat for multiple pairs; required — no global scan)"
)]
pub subvert: Vec<String>,
#[arg(long, value_enum, default_value_t = IdentifierCase::Snake, help = "Target case style")]
pub to: IdentifierCase,
#[command(flatten)]
pub backup_opts: BackupOpts,
#[arg(long, help = "Preserve original mtime/atime", action = clap::ArgAction::SetTrue)]
pub preserve_timestamps: bool,
#[arg(long, help = "Show what would be changed without writing", action = clap::ArgAction::SetTrue)]
pub dry_run: bool,
}
#[derive(Args, Debug)]
pub struct WalStatsArgs {
#[arg(long, help = "Show what would be done without scanning", action = clap::ArgAction::SetTrue)]
pub dry_run: bool,
}