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#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
16pub struct DocOptions {
17 #[arg(
19 short = 'p',
20 long = "package",
21 value_name = "SPEC",
22 action = ArgAction::Append,
23 num_args=0..=1,
24 help_heading = heading::PACKAGE_SELECTION,
25 )]
26 #[cfg_attr(feature = "serde", serde(default))]
27 pub packages: Vec<String>,
28
29 #[arg(long, help_heading = heading::PACKAGE_SELECTION)]
31 #[cfg_attr(feature = "serde", serde(default))]
32 pub workspace: bool,
33
34 #[arg(
36 long,
37 value_name = "SPEC",
38 action = ArgAction::Append,
39 help_heading = heading::PACKAGE_SELECTION,
40 )]
41 #[cfg_attr(feature = "serde", serde(default))]
42 pub exclude: Vec<String>,
43
44 #[arg(long, help_heading = heading::PACKAGE_SELECTION,)]
46 #[cfg_attr(feature = "serde", serde(default))]
47 pub all: bool,
48
49 #[arg(long, help_heading = heading::TARGET_SELECTION)]
51 #[cfg_attr(feature = "serde", serde(default))]
52 pub lib: bool,
53
54 #[arg(
56 long,
57 value_name = "NAME",
58 action = ArgAction::Append,
59 num_args=0..=1,
60 help_heading = heading::TARGET_SELECTION,
61 )]
62 #[cfg_attr(feature = "serde", serde(default))]
63 pub bin: Vec<String>,
64
65 #[arg(long, help_heading = heading::TARGET_SELECTION)]
67 #[cfg_attr(feature = "serde", serde(default))]
68 pub bins: bool,
69
70 #[arg(
72 long,
73 value_name = "NAME",
74 action = ArgAction::Append,
75 num_args=0..=1,
76 help_heading = heading::TARGET_SELECTION,
77 )]
78 #[cfg_attr(feature = "serde", serde(default))]
79 pub example: Vec<String>,
80
81 #[arg(long, help_heading = heading::TARGET_SELECTION)]
83 #[cfg_attr(feature = "serde", serde(default))]
84 pub examples: bool,
85
86 #[arg(long)]
88 #[cfg_attr(feature = "serde", serde(default))]
89 pub no_deps: bool,
90
91 #[arg(long)]
93 #[cfg_attr(feature = "serde", serde(default))]
94 pub document_private_items: bool,
95
96 #[arg(long)]
98 #[cfg_attr(feature = "serde", serde(default))]
99 pub open: bool,
100}
101
102impl DocOptions {
103 pub fn apply(&self, cmd: &mut Command) {
104 for pkg in &self.packages {
105 cmd.arg("--package").arg(pkg);
106 }
107 if self.workspace {
108 cmd.arg("--workspace");
109 }
110 for item in &self.exclude {
111 cmd.arg("--exclude").arg(item);
112 }
113 if self.all {
114 cmd.arg("--all");
115 }
116 if self.lib {
117 cmd.arg("--lib");
118 }
119 for bin in &self.bin {
120 cmd.arg("--bin").arg(bin);
121 }
122 if self.bins {
123 cmd.arg("--bins");
124 }
125 for example in &self.example {
126 cmd.arg("--example").arg(example);
127 }
128 if self.examples {
129 cmd.arg("--examples");
130 }
131 if self.no_deps {
132 cmd.arg("--no-deps");
133 }
134 if self.document_private_items {
135 cmd.arg("--document-private-items");
136 }
137 if self.open {
138 cmd.arg("--open");
139 }
140 }
141}
142
143#[derive(Clone, Debug, Default, Parser)]
145#[command(
146 display_order = 1,
147 after_help = "Run `cargo help doc` for more detailed information."
148)]
149#[group(skip)]
150#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
151pub struct Doc {
152 #[command(flatten)]
153 #[cfg_attr(feature = "serde", serde(flatten))]
154 pub common: CommonOptions,
155
156 #[command(flatten)]
157 #[cfg_attr(feature = "serde", serde(flatten))]
158 pub doc: DocOptions,
159
160 #[arg(long, value_name = "PATH", help_heading = heading::MANIFEST_OPTIONS)]
162 #[cfg_attr(feature = "serde", serde(default))]
163 pub manifest_path: Option<PathBuf>,
164
165 #[arg(
167 short = 'r',
168 long,
169 conflicts_with = "profile",
170 help_heading = heading::COMPILATION_OPTIONS,
171 )]
172 #[cfg_attr(feature = "serde", serde(default))]
173 pub release: bool,
174
175 #[arg(long, help_heading = heading::MANIFEST_OPTIONS)]
177 #[cfg_attr(feature = "serde", serde(default))]
178 pub ignore_rust_version: bool,
179
180 #[arg(long, help_heading = heading::COMPILATION_OPTIONS)]
182 #[cfg_attr(feature = "serde", serde(default))]
183 pub unit_graph: bool,
184}
185
186impl Doc {
187 pub fn command(&self) -> Command {
189 let mut cmd = CommonOptions::cargo_command();
190 cmd.arg("doc");
191
192 self.common.apply(&mut cmd);
193 self.doc.apply(&mut cmd);
194
195 if let Some(path) = self.manifest_path.as_ref() {
196 cmd.arg("--manifest-path").arg(path);
197 }
198 if self.release {
199 cmd.arg("--release");
200 }
201 if self.ignore_rust_version {
202 cmd.arg("--ignore-rust-version");
203 }
204 if self.unit_graph {
205 cmd.arg("--unit-graph");
206 }
207
208 cmd
209 }
210}
211
212impl Deref for Doc {
213 type Target = CommonOptions;
214
215 fn deref(&self) -> &Self::Target {
216 &self.common
217 }
218}
219
220impl DerefMut for Doc {
221 fn deref_mut(&mut self) -> &mut Self::Target {
222 &mut self.common
223 }
224}
225
226#[cfg(test)]
227mod test {
228 use super::Doc;
229 use clap::CommandFactory;
230
231 #[test]
232 fn verify_cli() {
233 <Doc as CommandFactory>::command().debug_assert()
234 }
235}