cargo_options/
run.rs

1use std::ops::{Deref, DerefMut};
2use std::path::PathBuf;
3use std::process::Command;
4
5use clap::{ArgAction, Parser};
6
7#[cfg(feature = "serde")]
8use serde::{Deserialize, Serialize};
9
10use crate::common::CommonOptions;
11use crate::heading;
12
13/// Run a binary or example of the local package
14#[derive(Clone, Debug, Default, Parser)]
15#[command(
16    display_order = 1,
17    after_help = "Run `cargo help run` for more detailed information."
18)]
19#[group(skip)]
20#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
21pub struct Run {
22    #[command(flatten)]
23    #[cfg_attr(feature = "serde", serde(flatten))]
24    pub common: CommonOptions,
25
26    /// Path to Cargo.toml
27    #[arg(long, value_name = "PATH", help_heading = heading::MANIFEST_OPTIONS)]
28    #[cfg_attr(feature = "serde", serde(default))]
29    pub manifest_path: Option<PathBuf>,
30
31    /// Build artifacts in release mode, with optimizations
32    #[arg(short = 'r', long, help_heading = heading::COMPILATION_OPTIONS)]
33    #[cfg_attr(feature = "serde", serde(default))]
34    pub release: bool,
35
36    /// Ignore `rust-version` specification in packages
37    #[arg(long)]
38    #[cfg_attr(feature = "serde", serde(default))]
39    pub ignore_rust_version: bool,
40
41    /// Output build graph in JSON (unstable)
42    #[arg(long, help_heading = heading::COMPILATION_OPTIONS)]
43    #[cfg_attr(feature = "serde", serde(default))]
44    pub unit_graph: bool,
45
46    /// Package to run (see `cargo help pkgid`)
47    #[arg(
48        short = 'p',
49        long = "package",
50        value_name = "SPEC",
51        action = ArgAction::Append,
52        num_args=0..=1,
53        help_heading = heading::PACKAGE_SELECTION,
54    )]
55    #[cfg_attr(feature = "serde", serde(default))]
56    pub packages: Vec<String>,
57
58    /// Run the specified binary
59    #[arg(
60        long,
61        value_name = "NAME",
62        action = ArgAction::Append,
63        num_args=0..=1,
64        help_heading = heading::TARGET_SELECTION,
65    )]
66    #[cfg_attr(feature = "serde", serde(default))]
67    pub bin: Vec<String>,
68
69    /// Run the specified example
70    #[arg(
71        long,
72        value_name = "NAME",
73        action = ArgAction::Append,
74        num_args=0..=1,
75        help_heading = heading::TARGET_SELECTION,
76    )]
77    #[cfg_attr(feature = "serde", serde(default))]
78    pub example: Vec<String>,
79
80    /// Arguments for the binary to run
81    #[arg(value_name = "args", trailing_var_arg = true, num_args = 0..)]
82    #[cfg_attr(feature = "serde", serde(default))]
83    pub args: Vec<String>,
84}
85
86impl Run {
87    /// Build a `cargo run` command
88    pub fn command(&self) -> Command {
89        let mut cmd = CommonOptions::cargo_command();
90        cmd.arg("run");
91
92        self.common.apply(&mut cmd);
93
94        if let Some(path) = self.manifest_path.as_ref() {
95            cmd.arg("--manifest-path").arg(path);
96        }
97        if self.release {
98            cmd.arg("--release");
99        }
100        if self.ignore_rust_version {
101            cmd.arg("--ignore-rust-version");
102        }
103        if self.unit_graph {
104            cmd.arg("--unit-graph");
105        }
106        for pkg in &self.packages {
107            cmd.arg("--package").arg(pkg);
108        }
109        for bin in &self.bin {
110            cmd.arg("--bin").arg(bin);
111        }
112        for example in &self.example {
113            cmd.arg("--example").arg(example);
114        }
115        if !self.args.is_empty() {
116            cmd.arg("--");
117            cmd.args(&self.args);
118        }
119
120        cmd
121    }
122}
123
124impl Deref for Run {
125    type Target = CommonOptions;
126
127    fn deref(&self) -> &Self::Target {
128        &self.common
129    }
130}
131
132impl DerefMut for Run {
133    fn deref_mut(&mut self) -> &mut Self::Target {
134        &mut self.common
135    }
136}
137
138#[cfg(test)]
139mod test {
140    use super::Run;
141    use clap::CommandFactory;
142
143    #[test]
144    fn verify_cli() {
145        <Run as CommandFactory>::command().debug_assert()
146    }
147}