1use std::borrow::Cow;
2use std::ffi::OsStr;
3use std::fmt::Display;
4
5use crate::args::Args;
6use crate::opt::Style;
7use crate::parser::Action;
8use crate::str::display_of_osstr;
9use crate::str::display_of_str;
10use crate::value::RawValParser;
11use crate::Error;
12use crate::Uid;
13
14#[derive(Debug, Clone, Default)]
15pub struct InnerCtx<'a> {
16 uid: Uid,
17
18 name: Option<Cow<'a, str>>,
19
20 style: Style,
21
22 arg: Option<Cow<'a, OsStr>>,
23
24 index: usize,
25
26 total: usize,
27}
28
29impl<'a> InnerCtx<'a> {
30 pub fn with_uid(mut self, uid: Uid) -> Self {
31 self.uid = uid;
32 self
33 }
34
35 pub fn with_idx(mut self, index: usize) -> Self {
36 self.index = index;
37 self
38 }
39
40 pub fn with_total(mut self, total: usize) -> Self {
41 self.total = total;
42 self
43 }
44
45 pub fn with_name(mut self, name: Option<Cow<'a, str>>) -> Self {
46 self.name = name;
47 self
48 }
49
50 pub fn with_style(mut self, style: Style) -> Self {
51 self.style = style;
52 self
53 }
54
55 pub fn with_arg(mut self, arg: Option<Cow<'a, OsStr>>) -> Self {
56 self.arg = arg;
57 self
58 }
59
60 pub fn uid(&self) -> Uid {
62 self.uid
63 }
64
65 pub fn idx(&self) -> usize {
67 self.index
68 }
69
70 pub fn total(&self) -> usize {
72 self.total
73 }
74
75 pub fn name(&self) -> Option<&Cow<'a, str>> {
79 self.name.as_ref()
80 }
81
82 pub fn style(&self) -> Style {
84 self.style
85 }
86
87 pub fn arg(&self) -> Option<&Cow<'a, OsStr>> {
89 self.arg.as_ref()
90 }
91
92 pub fn set_uid(&mut self, uid: Uid) -> &mut Self {
93 self.uid = uid;
94 self
95 }
96
97 pub fn set_index(&mut self, index: usize) -> &mut Self {
99 self.index = index;
100 self
101 }
102
103 pub fn set_total(&mut self, total: usize) -> &mut Self {
105 self.total = total;
106 self
107 }
108
109 pub fn set_name(&mut self, name: Option<Cow<'a, str>>) -> &mut Self {
110 self.name = name;
111 self
112 }
113
114 pub fn set_style(&mut self, style: Style) -> &mut Self {
115 self.style = style;
116 self
117 }
118
119 pub fn set_arg(&mut self, arg: Option<Cow<'a, OsStr>>) -> &mut Self {
120 self.arg = arg;
121 self
122 }
123}
124
125impl Display for InnerCtx<'_> {
126 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
127 write!(
128 f,
129 "InnerCtx {{ uid: {}, name: {}, style: {}, arg: {}, index: {}, total: {} }}",
130 self.uid,
131 display_of_str(self.name.as_deref()),
132 self.style,
133 display_of_osstr(self.arg.as_deref()),
134 self.index,
135 self.total,
136 )
137 }
138}
139
140#[derive(Debug, Default)]
143pub struct Ctx<'a> {
144 pub orig: Args,
145
146 pub args: Vec<&'a OsStr>,
147
148 pub inner_ctx: Option<InnerCtx<'a>>,
149
150 #[cfg(not(feature = "sync"))]
151 action: std::cell::RefCell<Action>,
152
153 #[cfg(feature = "sync")]
154 action: std::sync::Mutex<Action>,
155}
156
157impl Clone for Ctx<'_> {
158 fn clone(&self) -> Self {
159 Self {
160 orig: self.orig.clone(),
161 args: self.args.clone(),
162 inner_ctx: self.inner_ctx.clone(),
163 #[cfg(not(feature = "sync"))]
164 action: self.action.clone(),
165 #[cfg(feature = "sync")]
166 action: std::sync::Mutex::new(*self.action.lock().unwrap()),
167 }
168 }
169}
170
171impl<'a> Ctx<'a> {
172 pub fn with_args(mut self, args: Vec<&'a OsStr>) -> Self {
173 self.args = args;
174 self
175 }
176
177 pub fn with_orig(mut self, orig_args: Args) -> Self {
178 self.orig = orig_args;
179 self
180 }
181
182 pub fn with_inner_ctx(mut self, inner_ctx: InnerCtx<'a>) -> Self {
183 self.inner_ctx = Some(inner_ctx);
184 self
185 }
186}
187
188impl<'a> Ctx<'a> {
189 pub fn uid(&self) -> Result<Uid, Error> {
191 Ok(self.inner_ctx()?.uid())
192 }
193
194 pub fn idx(&self) -> Result<usize, Error> {
196 Ok(self.inner_ctx()?.idx())
197 }
198
199 pub fn total(&self) -> Result<usize, Error> {
201 Ok(self.inner_ctx()?.total())
202 }
203
204 pub fn name(&self) -> Result<Option<&Cow<'a, str>>, Error> {
208 Ok(self.inner_ctx()?.name())
209 }
210
211 pub fn style(&self) -> Result<Style, Error> {
213 Ok(self.inner_ctx()?.style())
214 }
215
216 pub fn args(&self) -> &[&'a OsStr] {
219 &self.args
220 }
221
222 pub fn arg(&self) -> Result<Option<&Cow<'a, OsStr>>, Error> {
224 Ok(self.inner_ctx()?.arg())
225 }
226
227 pub fn inner_ctx(&self) -> Result<&InnerCtx<'a>, Error> {
228 self.inner_ctx
229 .as_ref()
230 .ok_or_else(|| crate::error!("InnerCtx not exist, try create a new one"))
231 }
232
233 pub fn inner_ctx_mut(&mut self) -> Result<&mut InnerCtx<'a>, Error> {
234 self.inner_ctx
235 .as_mut()
236 .ok_or_else(|| crate::error!("InnerCtx(mutable) not exist, try create a new one"))
237 }
238
239 pub fn orig(&self) -> &Args {
241 &self.orig
242 }
243
244 pub fn arg_at(&self, idx: usize) -> Result<Option<&'a OsStr>, Error> {
246 Ok(self.args.get(idx).copied())
247 }
248
249 pub fn take_args(&mut self) -> Vec<&OsStr> {
250 std::mem::take(&mut self.args)
251 }
252
253 pub fn take_orig_args(&mut self) -> Args {
254 std::mem::take(&mut self.orig)
255 }
256}
257
258impl<'a> Ctx<'a> {
259 pub fn set_uid(&mut self, uid: Uid) -> Result<&mut Self, Error> {
260 self.inner_ctx_mut()?.set_uid(uid);
261 Ok(self)
262 }
263
264 pub fn set_index(&mut self, index: usize) -> Result<&mut Self, Error> {
266 self.inner_ctx_mut()?.set_index(index);
267 Ok(self)
268 }
269
270 pub fn set_total(&mut self, total: usize) -> Result<&mut Self, Error> {
272 self.inner_ctx_mut()?.set_total(total);
273 Ok(self)
274 }
275
276 pub fn set_args(&mut self, args: Vec<&'a OsStr>) -> &mut Self {
277 self.args = args;
278 self
279 }
280
281 pub fn set_name(&mut self, name: Option<Cow<'a, str>>) -> Result<&mut Self, Error> {
282 self.inner_ctx_mut()?.set_name(name);
283 Ok(self)
284 }
285
286 pub fn set_style(&mut self, style: Style) -> Result<&mut Self, Error> {
287 self.inner_ctx_mut()?.set_style(style);
288 Ok(self)
289 }
290
291 pub fn set_arg(&mut self, arg: Option<Cow<'a, OsStr>>) -> Result<&mut Self, Error> {
292 self.inner_ctx_mut()?.set_arg(arg);
293 Ok(self)
294 }
295
296 pub fn set_orig_args(&mut self, orig_args: Args) -> &mut Self {
297 self.orig = orig_args;
298 self
299 }
300
301 pub fn set_inner_ctx(&mut self, inner_ctx: Option<InnerCtx<'a>>) -> &mut Self {
302 crate::trace!("switching InnerCtx to {:?}", inner_ctx);
303 self.inner_ctx = inner_ctx;
304 self
305 }
306}
307
308impl Ctx<'_> {
309 #[cfg(not(feature = "sync"))]
310 pub fn policy_act(&self) -> Action {
311 *self.action.borrow()
312 }
313
314 #[cfg(feature = "sync")]
315 pub fn policy_act(&self) -> Action {
316 *self.action.lock().unwrap()
317 }
318
319 #[cfg(not(feature = "sync"))]
320 pub fn set_policy_act(&self, act: Action) {
321 *self.action.borrow_mut() = act;
322 }
323
324 #[cfg(feature = "sync")]
325 pub fn set_policy_act(&self, act: Action) {
326 *self.action.lock().unwrap() = act;
327 }
328
329 #[cfg(not(feature = "sync"))]
330 pub fn reset_policy_act(&self) {
331 *self.action.borrow_mut() = Action::Null;
332 }
333
334 #[cfg(feature = "sync")]
335 pub fn reset_policy_act(&self) {
336 *self.action.lock().unwrap() = Action::Null;
337 }
338}
339
340impl Ctx<'_> {
341 pub fn value<T: RawValParser>(&self) -> Result<T, Error> {
342 let arg = self.arg()?.map(|v| v.as_ref());
343 let uid = self.uid()?;
344
345 T::parse(arg, self).map_err(|e| e.into().with_uid(uid))
346 }
347}