Skip to main content

toggle/
cli.rs

1// Command-line interface for the Toggle CLI
2
3use clap::Parser;
4use clap_complete::Shell;
5use std::path::PathBuf;
6
7#[derive(Parser)]
8#[command(author, version, about)]
9pub struct Cli {
10    /// File or directory paths to process
11    pub paths: Vec<PathBuf>,
12
13    /// Line range in format <start_line>:<end_line> or <start_line>:+<count> (repeatable)
14    #[arg(short = 'l', long = "line", action = clap::ArgAction::Append)]
15    pub lines: Vec<String>,
16
17    /// Section ID to toggle. Use `group:variant` (e.g. `db:postgres`) for variant ops:
18    /// `-S group` flips a 2-variant pair; `-S group:variant` activates one variant
19    /// and comments siblings; `-S group --force on/off` applies to every variant.
20    #[arg(short = 'S', long = "section", action = clap::ArgAction::Append)]
21    pub sections: Vec<String>,
22
23    /// Recursively walk directories
24    #[arg(short = 'R', long = "recursive")]
25    pub recursive: bool,
26
27    /// List all section IDs found in files (discovery mode, no toggling)
28    #[arg(long = "list-sections")]
29    pub list_sections: bool,
30
31    /// Force toggle state (on/off/invert)
32    #[arg(short = 'f', long = "force", visible_short_alias = 'F')]
33    pub force: Option<String>,
34
35    /// Comment mode (auto/single/multi)
36    #[arg(short = 'm', long = "mode", default_value = "auto")]
37    pub mode: String,
38
39    /// Human-readable log lines to stderr
40    #[arg(short = 'v', long = "verbose")]
41    pub verbose: bool,
42
43    /// Machine-readable single-line JSON to stdout
44    #[arg(long = "json")]
45    pub json: bool,
46
47    /// Extension for atomic temp file
48    #[arg(short = 't', long = "temp-suffix")]
49    pub temp_suffix: Option<String>,
50
51    /// Override file codec (UTF-8 only in Phase 0)
52    #[arg(short = 'e', long = "encoding", default_value = "utf-8")]
53    pub encoding: String,
54
55    /// Error if target is not .py
56    #[arg(long = "strict-ext")]
57    pub strict_ext: bool,
58
59    /// Operate on symlink itself instead of target
60    #[arg(short = 'N', long = "no-dereference")]
61    pub no_dereference: bool,
62
63    /// EOL normalization: preserve, lf, or crlf
64    #[arg(long = "eol", default_value = "preserve")]
65    pub eol: String,
66
67    /// Map exit codes to sysexits.h values
68    #[arg(short = 'x', long = "posix-exit")]
69    pub posix_exit: bool,
70
71    /// Override comment style: SINGLE [MULTI_START MULTI_END]
72    #[arg(long = "comment-style", num_args = 1..=3, value_names = ["SINGLE", "MULTI_START", "MULTI_END"])]
73    pub comment_style: Vec<String>,
74
75    /// Prompt before modifying each file
76    #[arg(short = 'i', long = "interactive")]
77    pub interactive: bool,
78
79    /// Show diff of changes without writing files
80    #[arg(long = "dry-run")]
81    pub dry_run: bool,
82
83    /// Create backup with given extension before modifying (e.g. --backup .bak)
84    #[arg(long = "backup")]
85    pub backup: Option<String>,
86
87    /// Extend the last --line range to the end of file
88    #[arg(long = "to-end")]
89    pub to_end: bool,
90
91    /// Scan for section IDs without modifying files
92    #[arg(long = "scan")]
93    pub scan: bool,
94
95    /// Validate section integrity without modifying files. Requires --scan.
96    #[arg(long = "check")]
97    pub check: bool,
98
99    /// Enforce exactly 2 variants in the targeted group; error otherwise.
100    /// Pre-execution check — no file modifications occur on failure.
101    #[arg(long = "pair")]
102    pub pair: bool,
103
104    /// Path to .toggleConfig TOML file
105    #[arg(long = "config")]
106    pub config: Option<PathBuf>,
107
108    /// Enable atomic multi-file mode: all files succeed or none are modified.
109    /// Implies --backup unless --no-backup is explicitly passed.
110    #[arg(long = "atomic")]
111    pub atomic: bool,
112
113    /// Disable backup creation in atomic mode. Only valid with --atomic.
114    /// WARNING: Without backups, rollback is not possible if the rename phase fails.
115    #[arg(long = "no-backup")]
116    pub no_backup: bool,
117
118    /// Recover from an interrupted atomic operation. Default: rollback.
119    #[arg(long = "recover")]
120    pub recover: bool,
121
122    /// Complete an interrupted atomic commit instead of rolling back.
123    /// Must be combined with --recover.
124    #[arg(long = "recover-forward")]
125    pub recover_forward: bool,
126
127    /// Generate shell completions for the given shell to stdout.
128    /// Example: `toggle --completions bash > /etc/bash_completion.d/toggle`
129    #[arg(long = "completions", value_name = "SHELL")]
130    pub completions: Option<Shell>,
131
132    /// Generate a roff-formatted man page to stdout.
133    /// Example: `toggle --man > toggle.1 && man ./toggle.1`
134    #[arg(long = "man")]
135    pub man: bool,
136}