Skip to main content

Maintain/Eliminate/
CLI.rs

1//=============================================================================//
2// File Path: Element/Maintain/Source/Eliminate/CLI.rs
3//=============================================================================//
4// Module: CLI - Command-line interface for the Eliminate module
5//
6// Usage:
7//   cargo run --bin Maintain -- eliminate --path ./Source --glob "**/*.rs"
8//   cargo run --bin Maintain -- eliminate --path ./Source/Foo.rs --dry-run
9//=============================================================================//
10
11use std::path::PathBuf;
12
13use clap::Parser;
14
15use super::{Constant, Definition, Error, Process};
16
17/// Inline single-use Rust `let` bindings across one file or a directory tree.
18#[derive(Parser, Debug, Clone)]
19#[clap(
20	name = "eliminate",
21	about = "Inline single-use Rust let-bindings (non-mutated, non-closure-captured)"
22)]
23pub struct Cli {
24	/// File or directory to process.
25	#[clap(long, short = 'p', default_value = ".")]
26	pub Path:PathBuf,
27
28	/// Glob pattern relative to Path for selecting files.
29	#[clap(long, short = 'g', default_value = Constant::DefaultGlob)]
30	pub Glob:String,
31
32	/// Preview changes without writing any files.
33	#[clap(long, short = 'd')]
34	pub DryRun:bool,
35
36	/// Maximum AST node count for an inlinable initialiser.
37	/// Expressions with more nodes are left as-is.
38	#[clap(long, default_value_t = Constant::DefaultMaxSize)]
39	pub MaxSize:usize,
40
41	/// Also inline bindings that carry leading doc-comments or attributes.
42	/// Default: skip commented bindings.
43	#[clap(long)]
44	pub InlineComments:bool,
45
46	/// Print a line for every binding that is inlined.
47	#[clap(long, short = 'v')]
48	pub Verbose:bool,
49
50	/// Reformat the entire file with prettyplease after inlining.
51	/// Default: only the inlined binding sites are rewritten; comments,
52	/// blank lines, and indentation are preserved verbatim.
53	#[clap(long, short = 'r')]
54	pub Reformat:bool,
55}
56
57impl Cli {
58	pub fn execute(&self) -> Error::Result<()> {
59		let Options = Definition::Options {
60			MaxSize:self.MaxSize,
61
62			InlineComments:self.InlineComments,
63
64			DryRun:self.DryRun,
65
66			Verbose:self.Verbose,
67
68			Reformat:self.Reformat,
69		};
70
71		let Stats = Process::Process(&self.Path, &self.Glob, &Options)?;
72
73		if self.Verbose || self.DryRun {
74			println!(
75				"Eliminate: {} file(s) scanned, {} modified, {} binding(s) inlined{}",
76				Stats.FilesProcessed,
77				Stats.FilesModified,
78				Stats.BindingsInlined,
79				if self.DryRun { " [dry-run]" } else { "" }
80			);
81		}
82
83		Ok(())
84	}
85}