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}