use clap::{Parser, Subcommand, ValueEnum};
use clap_complete::Shell;
use indicatif::MultiProgress;
use std::sync::Arc;
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub enum OutputFormat {
#[default]
Human,
Json,
}
#[derive(Parser)]
#[command(name = "rsbuild")]
#[command(version)]
#[command(about, long_about = None)]
#[command(propagate_version = true)]
pub struct Cli {
#[arg(short, long, global = true)]
pub verbose: bool,
#[arg(short, long, global = true)]
pub quiet: bool,
#[arg(long, global = true)]
pub dry_run: bool,
#[arg(short = 'y', long, global = true)]
pub yes: bool,
#[arg(long, global = true)]
pub json: bool,
#[arg(short = 'j', long, global = true, default_value = "1")]
pub jobs: usize,
#[command(subcommand)]
pub command: Commands,
}
#[derive(Subcommand)]
pub enum Commands {
Build {
#[command(subcommand)]
target: BuildTarget,
},
Pull {
#[command(subcommand)]
target: PullTarget,
},
Run {
service: String,
#[arg(trailing_var_arg = true)]
args: Vec<String>,
},
Clean {
#[arg(long)]
all: bool,
},
Cython {
package: String,
},
Python {
#[command(subcommand)]
action: PythonAction,
},
Glances,
Completions {
#[arg(value_enum)]
shell: Shell,
},
Doctor,
Watch {
#[command(subcommand)]
target: WatchTarget,
#[arg(short, long, default_value = "500")]
debounce: u64,
#[arg(short, long)]
path: Vec<String>,
},
#[command(external_subcommand)]
External(Vec<String>),
}
#[derive(Subcommand)]
pub enum BuildTarget {
Wheel,
All,
Cargo {
#[arg(value_enum, default_value = "release")]
mode: CargoBuildMode,
},
Docker {
service: String,
#[arg(long)]
no_cache: bool,
},
}
#[derive(Clone, Debug, ValueEnum)]
pub enum CargoBuildMode {
Debug,
Release,
}
#[derive(Subcommand)]
pub enum PullTarget {
All,
Service {
name: String,
},
}
#[derive(Subcommand, Clone, Copy, Debug)]
pub enum WatchTarget {
Wheel,
Docker,
Cython,
Cargo,
}
#[derive(Subcommand)]
pub enum PythonAction {
Init {
#[arg(short, long)]
name: Option<String>,
#[arg(long)]
no_tests: bool,
#[arg(long)]
no_devcontainer: bool,
},
SyncVersion,
}
#[derive(Clone)]
pub struct ExecContext {
pub verbose: bool,
pub quiet: bool,
pub dry_run: bool,
pub yes: bool,
pub output_format: OutputFormat,
pub jobs: usize,
pub progress: Option<Arc<MultiProgress>>,
}
impl ExecContext {
pub fn from_cli(cli: &Cli) -> Self {
let output_format = if cli.json {
OutputFormat::Json
} else {
OutputFormat::Human
};
let quiet = cli.quiet || cli.json;
let progress = if !quiet {
Some(Arc::new(MultiProgress::new()))
} else {
None
};
Self {
verbose: cli.verbose,
quiet,
dry_run: cli.dry_run,
yes: cli.yes,
output_format,
jobs: cli.jobs.max(1),
progress,
}
}
pub fn should_print(&self) -> bool {
!self.quiet
}
pub fn is_json(&self) -> bool {
self.output_format == OutputFormat::Json
}
pub fn is_parallel(&self) -> bool {
self.jobs > 1
}
}