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(short = 'r', long, help_heading = heading::COMPILATION_OPTIONS)]
167 #[cfg_attr(feature = "serde", serde(default))]
168 pub release: bool,
169
170 #[arg(long)]
172 #[cfg_attr(feature = "serde", serde(default))]
173 pub ignore_rust_version: bool,
174
175 #[arg(long, help_heading = heading::COMPILATION_OPTIONS)]
177 #[cfg_attr(feature = "serde", serde(default))]
178 pub unit_graph: bool,
179}
180
181impl Doc {
182 pub fn command(&self) -> Command {
184 let mut cmd = CommonOptions::cargo_command();
185 cmd.arg("doc");
186
187 self.common.apply(&mut cmd);
188 self.doc.apply(&mut cmd);
189
190 if let Some(path) = self.manifest_path.as_ref() {
191 cmd.arg("--manifest-path").arg(path);
192 }
193 if self.release {
194 cmd.arg("--release");
195 }
196 if self.ignore_rust_version {
197 cmd.arg("--ignore-rust-version");
198 }
199 if self.unit_graph {
200 cmd.arg("--unit-graph");
201 }
202
203 cmd
204 }
205}
206
207impl Deref for Doc {
208 type Target = CommonOptions;
209
210 fn deref(&self) -> &Self::Target {
211 &self.common
212 }
213}
214
215impl DerefMut for Doc {
216 fn deref_mut(&mut self) -> &mut Self::Target {
217 &mut self.common
218 }
219}
220
221#[cfg(test)]
222mod test {
223 use super::Doc;
224 use clap::CommandFactory;
225
226 #[test]
227 fn verify_cli() {
228 <Doc as CommandFactory>::command().debug_assert()
229 }
230}