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#[derive(Clone, Debug, Default, Parser)]
15#[command(
16 display_order = 1,
17 after_help = "Run `cargo help run` for more detailed information.\nTo pass `--help` to the specified binary, use `-- --help`."
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 #[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 #[arg(
33 short = 'r',
34 long,
35 conflicts_with = "profile",
36 help_heading = heading::COMPILATION_OPTIONS,
37 )]
38 #[cfg_attr(feature = "serde", serde(default))]
39 pub release: bool,
40
41 #[arg(long, help_heading = heading::MANIFEST_OPTIONS)]
43 #[cfg_attr(feature = "serde", serde(default))]
44 pub ignore_rust_version: bool,
45
46 #[arg(long, help_heading = heading::COMPILATION_OPTIONS)]
48 #[cfg_attr(feature = "serde", serde(default))]
49 pub unit_graph: bool,
50
51 #[arg(
53 short = 'p',
54 long = "package",
55 value_name = "SPEC",
56 action = ArgAction::Append,
57 num_args=0..=1,
58 help_heading = heading::PACKAGE_SELECTION,
59 )]
60 #[cfg_attr(feature = "serde", serde(default))]
61 pub packages: Vec<String>,
62
63 #[arg(
65 long,
66 value_name = "NAME",
67 action = ArgAction::Append,
68 num_args=0..=1,
69 help_heading = heading::TARGET_SELECTION,
70 )]
71 #[cfg_attr(feature = "serde", serde(default))]
72 pub bin: Vec<String>,
73
74 #[arg(
76 long,
77 value_name = "NAME",
78 action = ArgAction::Append,
79 num_args=0..=1,
80 help_heading = heading::TARGET_SELECTION,
81 )]
82 #[cfg_attr(feature = "serde", serde(default))]
83 pub example: Vec<String>,
84
85 #[arg(value_name = "ARGS", trailing_var_arg = true, num_args = 0..)]
87 #[cfg_attr(feature = "serde", serde(default))]
88 pub args: Vec<String>,
89}
90
91impl Run {
92 pub fn command(&self) -> Command {
94 let mut cmd = CommonOptions::cargo_command();
95 cmd.arg("run");
96
97 self.common.apply(&mut cmd);
98
99 if let Some(path) = self.manifest_path.as_ref() {
100 cmd.arg("--manifest-path").arg(path);
101 }
102 if self.release {
103 cmd.arg("--release");
104 }
105 if self.ignore_rust_version {
106 cmd.arg("--ignore-rust-version");
107 }
108 if self.unit_graph {
109 cmd.arg("--unit-graph");
110 }
111 for pkg in &self.packages {
112 cmd.arg("--package").arg(pkg);
113 }
114 for bin in &self.bin {
115 cmd.arg("--bin").arg(bin);
116 }
117 for example in &self.example {
118 cmd.arg("--example").arg(example);
119 }
120 if !self.args.is_empty() {
121 cmd.arg("--");
122 cmd.args(&self.args);
123 }
124
125 cmd
126 }
127}
128
129impl Deref for Run {
130 type Target = CommonOptions;
131
132 fn deref(&self) -> &Self::Target {
133 &self.common
134 }
135}
136
137impl DerefMut for Run {
138 fn deref_mut(&mut self) -> &mut Self::Target {
139 &mut self.common
140 }
141}
142
143#[cfg(test)]
144mod test {
145 use super::Run;
146 use clap::CommandFactory;
147
148 #[test]
149 fn verify_cli() {
150 <Run as CommandFactory>::command().debug_assert()
151 }
152}