Skip to main content

cargo_ff/
cli.rs

1use crate::types::Config;
2use clap::{Args, Parser};
3use std::num::NonZeroUsize;
4use std::path::PathBuf;
5
6#[derive(Debug, Parser)]
7#[command(
8    name = "cargo-ff",
9    bin_name = "cargo ff",
10    about = "Fast Format is a fast drop-in replacement for cargo fmt",
11    version
12)]
13pub struct Cli {
14    /// Run rustfmt in --check mode (exit non-zero if any file would change).
15    #[arg(long)]
16    pub check: bool,
17
18    /// Format every workspace member, regardless of which package
19    /// `--manifest-path` (or the current directory) implicitly selects.
20    /// Mirrors `cargo fmt --all`.
21    #[arg(long)]
22    pub all: bool,
23
24    /// Format only the given workspace member(s). Can be repeated.
25    #[arg(short = 'p', long = "package")]
26    pub packages: Vec<String>,
27
28    /// Path to the workspace's Cargo.toml (forwarded to `cargo metadata`).
29    #[arg(long)]
30    pub manifest_path: Option<PathBuf>,
31
32    /// Extra arguments forwarded to rustfmt (after `--`).
33    #[arg(last = true)]
34    pub rustfmt_args: Vec<String>,
35
36    #[command(flatten)]
37    pub ff: FfArgs,
38}
39
40/// cargo-ff-specific flags. All long names are prefixed `--ff-*` so they
41/// can never collide with a flag added upstream by `cargo fmt`.
42#[derive(Debug, Args)]
43pub struct FfArgs {
44    /// Number of worker threads. Defaults to available_parallelism().
45    #[arg(long = "ff-workers")]
46    pub workers: Option<NonZeroUsize>,
47
48    /// Bounded-channel capacity. Default 512. Hidden — benchmarking knob.
49    #[arg(long = "ff-channel-capacity", hide = true)]
50    pub channel_capacity: Option<usize>,
51
52    /// Crates per rustfmt invocation. Higher amortizes spawn cost; lower
53    /// gives finer scheduling granularity. Hidden — benchmarking knob.
54    #[arg(long = "ff-batch-size", hide = true)]
55    pub batch_size: Option<usize>,
56
57    /// Experimental: skip rustfmt for crates whose `*.rs` mtimes match
58    /// the prior successful run. May produce stale results if files
59    /// outside `manifest_dir` are pulled in via `#[path]`.
60    #[arg(long = "ff-experimental-cache", hide = true)]
61    pub experimental_cache: bool,
62
63    /// Emit advisory warnings to stderr (off by default).
64    #[arg(long = "ff-warnings")]
65    pub warnings: bool,
66}
67
68impl Cli {
69    /// Parse argv, stripping the cargo-subcommand `argv[1] == "ff"` if present.
70    pub fn parse_argv() -> Self {
71        let mut args: Vec<std::ffi::OsString> = std::env::args_os().collect();
72        if args.len() >= 2 && args[1] == "ff" {
73            args.remove(1);
74        }
75        Cli::parse_from(args)
76    }
77
78    pub fn into_config(self) -> Config {
79        Config {
80            manifest_path: self.manifest_path,
81            packages: self.packages,
82            all: self.all,
83            check: self.check,
84            rustfmt_args: self.rustfmt_args,
85            workers: self.ff.workers.map(NonZeroUsize::get),
86            channel_capacity: self.ff.channel_capacity,
87            batch_size: self.ff.batch_size,
88            experimental_cache: self.ff.experimental_cache,
89            warnings: self.ff.warnings,
90        }
91    }
92}