1use crate::CommandWrap;
2use appsettings::*;
3use clap::Command;
4use serde::{
5 de::{DeserializeSeed, Error, Visitor},
6 Deserialize,
7};
8
9mod appsettings;
10#[cfg(feature = "color")]
11mod color;
12
13const TMP_APP_NAME: &str = "__tmp__deserialize__name__";
14impl<'de> Deserialize<'de> for CommandWrap<'de> {
15 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
16 where
17 D: serde::Deserializer<'de>,
18 {
19 deserializer
20 .deserialize_map(CommandVisitor(Command::new(TMP_APP_NAME)))
21 .and_then(|r| {
23 if r.app.get_name() != TMP_APP_NAME {
24 Ok(r)
25 } else {
26 Err(<D::Error>::missing_field("name"))
27 }
28 })
29 }
30}
31
32struct CommandVisitor<'a>(Command<'a>);
33
34impl<'a> Visitor<'a> for CommandVisitor<'a> {
35 type Value = CommandWrap<'a>;
36
37 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
38 formatter.write_str("Command Map")
39 }
40
41 fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
42 where
43 A: serde::de::MapAccess<'a>,
44 {
45 let mut app = self.0;
46 while let Some(key) = map.next_key::<&str>()? {
49 app = parse_value!(key, app, map, Command, {
50 (about, &str),
51 (after_help, &str),
52 (after_long_help, &str),
53 (alias, &str),
54 ref (aliases, Vec<&str>),
55 (allow_external_subcommands, bool),
56 (allow_hyphen_values, bool),
57 (allow_invalid_utf8_for_external_subcommands, bool),
58 (allow_missing_positional, bool),
59 (allow_negative_numbers, bool),
60 (arg_required_else_help, bool),
63 (args_conflicts_with_subcommands, bool),
64 (args_override_self, bool),
65 (author, &str),
66 (before_help, &str),
67 (before_long_help, &str),
68 (bin_name, &str),
69 (disable_colored_help, bool),
71 (disable_help_flag, bool),
72 (disable_help_subcommand, bool),
73 (disable_version_flag, bool),
74 (display_name, &str),
75 (display_order, usize),
76 (dont_collapse_args_in_usage, bool),
77 (dont_delimit_trailing_values, bool),
78 (help_expected, bool),
83 (help_template, &str),
84 (hide, bool),
85 (hide_possible_values, bool),
86 (ignore_errors, bool),
87 (infer_long_args, bool),
88 (infer_subcommands, bool),
89 (long_about, &str),
90 (long_flag, &str),
91 (long_flag_alias, &str),
92 ref (long_flag_aliases, Vec<&str>),
93 (long_version, &str),
94 (max_term_width, usize),
95 (multicall, bool),
96 (name, &str),
97 (next_display_order, Option<usize>),
98 (next_help_heading, Option<&str>),
99 (next_line_help, bool),
100 (no_binary_name, bool),
101 (override_help, &str),
102 (override_usage, &str),
103 (propagate_version, bool),
104 (short_flag, char),
107 (short_flag_alias, char),
108 ref (short_flag_aliases, Vec<char>),
109 (subcommand_help_heading, &str),
112 (subcommand_negates_reqs, bool),
113 (subcommand_required, bool),
114 (subcommand_value_name, &str),
115 (propagate_version, bool),
116 (term_width, usize),
117 (trailing_var_arg, bool),
118 (version, &str),
119 (visible_alias, &str),
120 ref (visible_aliases, Vec<&str>),
121 (visible_long_flag_alias, &str),
122 ref (visible_long_flag_aliases, Vec<&str>),
123 (visible_short_flag_alias, char),
124 ref (visible_short_flag_aliases, Vec<char>),
125 },
126 deprecated: [
127 "help_message",
128 "version_message",
129 ]{
130 "help_heading" => "next_help_heading",
131 },
132 not_supported: {
133 "arg" => "Use args instead",
134 "group" => "Use groups instead",
135 },
136 specialize:
137 [
138 "args" => map.next_value_seed(super::arg::Args::<true>(app))?
139 "args_map" => map.next_value_seed(super::arg::Args::<false>(app))?
140 "color" => {
141 #[cfg(color)] {
142 app.color(map.next_value_seed(ColorChoiceSeed)?)
143 }
144 #[cfg(not(color))] { return Err(Error::custom("color feature disabled"))}}
145 "subcommands" => map.next_value_seed(SubCommands::<true>(app))?
146 "subcommands_map" => map.next_value_seed(SubCommands::<false>(app))?
147 "groups" => map.next_value_seed(super::group::Groups(app))?
148 "setting" => app.setting(map.next_value_seed(AppSettingSeed)?)
149 "settings" => app.setting(map.next_value_seed(AppSettingsSeed)?)
150 "global_setting" => app.global_setting(map.next_value_seed(AppSettingSeed)?)
151 "global_settings" => {
152 let sets = map.next_value::<Vec<AppSetting1>>()?.into_iter().map(|s|s.into());
153 for s in sets{
154 app = app.global_setting(s);
155 }
156 app
157 }
158 ]);
159 }
160
161 Ok(CommandWrap { app })
162 }
163}
164
165pub struct NameSeed<'a>(&'a str);
166
167impl<'de> DeserializeSeed<'de> for NameSeed<'de> {
168 type Value = CommandWrap<'de>;
169
170 fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
171 where
172 D: serde::Deserializer<'de>,
173 {
174 deserializer.deserialize_map(CommandVisitor(Command::new(self.0)))
175 }
176}
177
178impl<'de> DeserializeSeed<'de> for CommandWrap<'de> {
179 type Value = CommandWrap<'de>;
180
181 fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
182 where
183 D: serde::Deserializer<'de>,
184 {
185 deserializer.deserialize_map(CommandVisitor(self.app))
186 }
187}
188
189struct SubCommands<'a, const KV_ARRAY: bool>(Command<'a>);
190impl<'de, const KV_ARRAY: bool> DeserializeSeed<'de> for SubCommands<'de, KV_ARRAY> {
191 type Value = Command<'de>;
192
193 fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
194 where
195 D: serde::Deserializer<'de>,
196 {
197 if KV_ARRAY {
198 deserializer.deserialize_seq(self)
199 } else {
200 deserializer.deserialize_map(self)
201 }
202 }
203}
204
205impl<'de, const KV_ARRAY: bool> Visitor<'de> for SubCommands<'de, KV_ARRAY> {
206 type Value = Command<'de>;
207
208 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
209 formatter.write_str("Subcommand")
210 }
211
212 fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
213 where
214 A: serde::de::MapAccess<'de>,
215 {
216 let mut app = self.0;
217 while let Some(name) = map.next_key::<&str>()? {
218 let sub = map.next_value_seed(NameSeed(name))?;
219 app = app.subcommand(sub);
220 }
221 Ok(app)
222 }
223
224 fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
225 where
226 A: serde::de::SeqAccess<'de>,
227 {
228 let mut app = self.0;
229 while let Some(sub) = seq.next_element_seed(InnerSubCommand)? {
230 app = app.subcommand(sub)
231 }
232 Ok(app)
233 }
234}
235
236pub struct InnerSubCommand;
237impl<'de> Visitor<'de> for InnerSubCommand {
238 type Value = Command<'de>;
239
240 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
241 formatter.write_str("Subcommand Inner")
242 }
243
244 fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
245 where
246 A: serde::de::MapAccess<'de>,
247 {
248 let k = map
249 .next_key()?
250 .ok_or_else(|| A::Error::invalid_length(0, &"missing command in subcommand"))?;
251 let com = map.next_value_seed(NameSeed(k))?;
252 Ok(com.into())
253 }
254}
255
256impl<'de> DeserializeSeed<'de> for InnerSubCommand {
257 type Value = Command<'de>;
258
259 fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
260 where
261 D: serde::Deserializer<'de>,
262 {
263 deserializer.deserialize_map(self)
264 }
265}