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."
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(short = 'r', long, help_heading = heading::COMPILATION_OPTIONS)]
33 #[cfg_attr(feature = "serde", serde(default))]
34 pub release: bool,
35
36 #[arg(long)]
38 #[cfg_attr(feature = "serde", serde(default))]
39 pub ignore_rust_version: bool,
40
41 #[arg(long, help_heading = heading::COMPILATION_OPTIONS)]
43 #[cfg_attr(feature = "serde", serde(default))]
44 pub unit_graph: bool,
45
46 #[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 #[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 #[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 #[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 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}