cargo_options/
doc.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/// `cargo doc` options
14#[derive(Clone, Debug, Default, Parser)]
15#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
16pub struct DocOptions {
17    /// Package to document
18    #[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    /// Document all packages in the workspace
30    #[arg(long, help_heading = heading::PACKAGE_SELECTION)]
31    #[cfg_attr(feature = "serde", serde(default))]
32    pub workspace: bool,
33
34    /// Exclude packages from the build
35    #[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    /// Alias for --workspace (deprecated)
45    #[arg(long, help_heading = heading::PACKAGE_SELECTION,)]
46    #[cfg_attr(feature = "serde", serde(default))]
47    pub all: bool,
48
49    /// Document only this package's library
50    #[arg(long, help_heading = heading::TARGET_SELECTION)]
51    #[cfg_attr(feature = "serde", serde(default))]
52    pub lib: bool,
53
54    /// Document only the specified binary
55    #[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    /// Document all binaries
66    #[arg(long, help_heading = heading::TARGET_SELECTION)]
67    #[cfg_attr(feature = "serde", serde(default))]
68    pub bins: bool,
69
70    /// Document only the specified example
71    #[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    /// Document all examples
82    #[arg(long, help_heading = heading::TARGET_SELECTION)]
83    #[cfg_attr(feature = "serde", serde(default))]
84    pub examples: bool,
85
86    /// Don't build documentation for dependencies
87    #[arg(long)]
88    #[cfg_attr(feature = "serde", serde(default))]
89    pub no_deps: bool,
90
91    /// Document private items
92    #[arg(long)]
93    #[cfg_attr(feature = "serde", serde(default))]
94    pub document_private_items: bool,
95
96    /// Opens the docs in a browser after the operation
97    #[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/// Build a package's documentation
144#[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    /// Path to Cargo.toml
161    #[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    /// Build artifacts in release mode, with optimizations
166    #[arg(short = 'r', long, help_heading = heading::COMPILATION_OPTIONS)]
167    #[cfg_attr(feature = "serde", serde(default))]
168    pub release: bool,
169
170    /// Ignore `rust-version` specification in packages
171    #[arg(long)]
172    #[cfg_attr(feature = "serde", serde(default))]
173    pub ignore_rust_version: bool,
174
175    /// Output build graph in JSON (unstable)
176    #[arg(long, help_heading = heading::COMPILATION_OPTIONS)]
177    #[cfg_attr(feature = "serde", serde(default))]
178    pub unit_graph: bool,
179}
180
181impl Doc {
182    /// Build a `cargo doc` command
183    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}