cli_xtask/
command.rs

1use crate::{args::Verbosity, config::Config, Result, Run};
2
3#[cfg(feature = "main")]
4#[cfg_attr(docsrs, doc(cfg(feature = "main")))]
5mod main;
6
7/// Command line interface definition for cargo xtask command.
8#[cfg_attr(doc, doc = include_str!("../doc/cargo-xtask.md"))]
9///
10/// # Examples
11///
12/// Use the premade entry point function with default configuration (`main`
13/// feature is required):
14///
15/// ```rust
16/// # #[cfg(feature = "main")]
17/// # {
18/// use cli_xtask::{Result, Xtask};
19///
20/// fn main() -> Result<()> {
21///     <Xtask>::main()
22/// }
23/// # }
24/// ```
25///
26/// Use the premade entry point function and custom configuration (`main`
27/// feature is required):
28///
29/// ```rust
30/// # #[cfg(feature = "main")]
31/// # {
32/// use cli_xtask::{config::Config, Result, Xtask};
33///
34/// fn main() -> Result<()> {
35///     <Xtask>::main_with_config(|| Ok(Config::new()))
36/// }
37/// # }
38/// ```
39///
40/// If you don't want to use the `main` feature, write the main function as
41/// follows:
42///
43/// ```rust
44/// # #[cfg(all(feature = "error-handler", feature = "logger"))]
45/// # {
46/// use cli_xtask::{clap::Parser, config::Config, error_handler, logger, Result, Xtask};
47///
48/// fn main() -> Result<()> {
49///     // Parse command line arguments
50///     let command = <Xtask>::parse();
51///
52///     // Setup error handler and logger
53///     error_handler::install()?; // `error-handler` feature is required
54///     logger::install(command.verbosity.get())?; // `logger` feature is required
55///
56///     // Run the subcommand specified by the command line arguments
57///     command.run(&Config::new())?;
58///
59///     Ok(())
60/// }
61/// # }
62/// ```
63///
64/// If you want to define your own subcommands, declare the type that implements
65/// [`clap::Subcommand`] and [`Run`], then use `Xtask<YourOwnSubcommand>`
66/// instead of `Xtask`.
67///
68/// ```rust
69/// # #[cfg(feature = "main")]
70/// # {
71/// use cli_xtask::{
72///     clap::{self, Parser},
73///     config::Config,
74///     subcommand, Result, Run, Xtask,
75/// };
76///
77/// // Define your own subcommand arguments
78/// #[derive(Debug, clap::Subcommand)]
79/// enum YourOwnSubcommand {
80///     #[clap(flatten)]
81///     Predefined(subcommand::Subcommand),
82///     /// Run foo function.
83///     Foo,
84///     /// Run bar function
85///     Bar,
86/// }
87///
88/// impl Run for YourOwnSubcommand {
89///     fn run(&self, config: &Config) -> Result<()> {
90///         match self {
91///             Self::Predefined(subcommand) => subcommand.run(config)?,
92///             Self::Foo => println!("foo!"),
93///             Self::Bar => println!("bar!"),
94///         }
95///         Ok(())
96///     }
97///
98///     fn into_any(self: Box<Self>) -> Box<dyn std::any::Any> {
99///         self
100///     }
101///
102///     fn as_any(&self) -> &dyn std::any::Any {
103///         self
104///     }
105///
106///     fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
107///         self
108///     }
109/// }
110///
111/// fn main() -> Result<()> {
112///     Xtask::<YourOwnSubcommand>::main()
113/// }
114/// # }
115/// ```
116#[derive(Debug, Clone, Default, clap::Parser)]
117#[non_exhaustive]
118#[clap(
119    bin_name = "cargo xtask",
120    about = "Rust project automation command",
121    long_about = None,
122    styles = clap_cargo::style::CLAP_STYLING
123)]
124pub struct Xtask<Subcommand = crate::subcommand::Subcommand>
125where
126    Subcommand: clap::Subcommand,
127{
128    /// Verbosity level
129    #[clap(flatten)]
130    pub verbosity: Verbosity,
131
132    /// Subcommand to run
133    #[clap(subcommand)]
134    pub subcommand: Option<Subcommand>,
135}
136
137impl<Subcommand> Xtask<Subcommand>
138where
139    Subcommand: clap::Subcommand,
140{
141    /// Runs the subcommand specified by the command line arguments.
142    ///
143    /// # Examples
144    ///
145    /// ```rust
146    /// # #[cfg(all(feature = "error-handler", feature = "logger"))]
147    /// # {
148    /// use cli_xtask::{clap::Parser, config::Config, error_handler, logger, Result, Xtask};
149    ///
150    /// fn main() -> Result<()> {
151    ///     // Parse command line arguments
152    ///     let command = <Xtask>::parse();
153    ///
154    ///     // Setup error handler and logger
155    ///     error_handler::install()?; // `error-handler` feature is required
156    ///     logger::install(command.verbosity.get())?; // `logger` feature is required
157    ///
158    ///     // Run the subcommand specified by the command line arguments
159    ///     command.run(&Config::new())?;
160    ///
161    ///     Ok(())
162    /// }
163    /// # }
164    /// ```
165    pub fn run(&self, config: &Config) -> Result<()>
166    where
167        Subcommand: Run,
168    {
169        let _config = config; // suppress unused-var warnings
170
171        match &self.subcommand {
172            Some(command) => command.run(config)?,
173            None => <Self as clap::CommandFactory>::command().print_help()?,
174        }
175
176        Ok(())
177    }
178}