1// Std
2use std::ops::BitOr;
3
4// Third party
5use bitflags::bitflags;
6
7#[allow(unused)]
8use crate::Arg;
9
10#[derive(Debug, Clone, Copy, PartialEq, Eq)]
11pub(crate) struct ArgFlags(Flags);
12
13impl Default for ArgFlags {
14    fn default() -> Self {
15        Self::empty()
16    }
17}
18
19/// Various settings that apply to arguments and may be set, unset, and checked via getter/setter
20/// methods [`Arg::setting`], [`Arg::unset_setting`], and [`Arg::is_set`]. This is what the
21/// [`Arg`] methods which accept a `bool` use internally.
22///
23/// [`Arg`]: crate::Arg
24/// [`Arg::setting`]: crate::Arg::setting()
25/// [`Arg::unset_setting`]: crate::Arg::unset_setting()
26/// [`Arg::is_set`]: crate::Arg::is_set()
27#[derive(Debug, PartialEq, Copy, Clone)]
28#[non_exhaustive]
29pub(crate) enum ArgSettings {
30    Required,
31    Global,
32    Hidden,
33    NextLineHelp,
34    HidePossibleValues,
35    AllowHyphenValues,
36    AllowNegativeNumbers,
37    RequireEquals,
38    Last,
39    TrailingVarArg,
40    HideDefaultValue,
41    IgnoreCase,
42    #[cfg(feature = "env")]
43    HideEnv,
44    #[cfg(feature = "env")]
45    HideEnvValues,
46    HiddenShortHelp,
47    HiddenLongHelp,
48    Exclusive,
49}
50
51bitflags! {
52    struct Flags: u32 {
53        const REQUIRED         = 1;
54        const GLOBAL           = 1 << 3;
55        const HIDDEN           = 1 << 4;
56        const TRAILING_VARARG  = 1 << 5;
57        const ALLOW_NEG_NUMS   = 1 << 6;
58        const NEXT_LINE_HELP   = 1 << 7;
59        const DELIM_NOT_SET    = 1 << 10;
60        const HIDE_POS_VALS    = 1 << 11;
61        const ALLOW_TAC_VALS   = 1 << 12;
62        const REQUIRE_EQUALS   = 1 << 13;
63        const LAST             = 1 << 14;
64        const HIDE_DEFAULT_VAL = 1 << 15;
65        const CASE_INSENSITIVE = 1 << 16;
66        #[cfg(feature = "env")]
67        const HIDE_ENV_VALS    = 1 << 17;
68        const HIDDEN_SHORT_H   = 1 << 18;
69        const HIDDEN_LONG_H    = 1 << 19;
70        #[cfg(feature = "env")]
71        const HIDE_ENV         = 1 << 21;
72        const EXCLUSIVE        = 1 << 23;
73        const NO_OP            = 0;
74    }
75}
76
77impl_settings! { ArgSettings, ArgFlags,
78    Required => Flags::REQUIRED,
79    Global => Flags::GLOBAL,
80    Hidden => Flags::HIDDEN,
81    NextLineHelp => Flags::NEXT_LINE_HELP,
82    HidePossibleValues => Flags::HIDE_POS_VALS,
83    AllowHyphenValues => Flags::ALLOW_TAC_VALS,
84    AllowNegativeNumbers => Flags::ALLOW_NEG_NUMS,
85    RequireEquals => Flags::REQUIRE_EQUALS,
86    Last => Flags::LAST,
87    TrailingVarArg => Flags::TRAILING_VARARG,
88    IgnoreCase => Flags::CASE_INSENSITIVE,
89    #[cfg(feature = "env")]
90    HideEnv => Flags::HIDE_ENV,
91    #[cfg(feature = "env")]
92    HideEnvValues => Flags::HIDE_ENV_VALS,
93    HideDefaultValue => Flags::HIDE_DEFAULT_VAL,
94    HiddenShortHelp => Flags::HIDDEN_SHORT_H,
95    HiddenLongHelp => Flags::HIDDEN_LONG_H,
96    Exclusive => Flags::EXCLUSIVE
97}
98
99#[cfg(test)]
100mod test {
101    use super::*;
102    use crate::Arg;
103
104    #[test]
105    fn setting() {
106        let m = Arg::new("setting").setting(ArgSettings::Required);
107        assert!(m.is_required_set());
108    }
109
110    #[test]
111    fn unset_setting() {
112        let m = Arg::new("unset_setting").setting(ArgSettings::Required);
113        assert!(m.is_required_set());
114
115        let m = m.unset_setting(ArgSettings::Required);
116        assert!(!m.is_required_set(), "{m:#?}");
117    }
118
119    #[test]
120    fn setting_bitor() {
121        let m = Arg::new("setting_bitor")
122            .setting(ArgSettings::Required | ArgSettings::Hidden | ArgSettings::Last);
123
124        assert!(m.is_required_set());
125        assert!(m.is_hide_set());
126        assert!(m.is_last_set());
127    }
128
129    #[test]
130    fn unset_setting_bitor() {
131        let m = Arg::new("unset_setting_bitor")
132            .setting(ArgSettings::Required)
133            .setting(ArgSettings::Hidden)
134            .setting(ArgSettings::Last);
135
136        assert!(m.is_required_set());
137        assert!(m.is_hide_set());
138        assert!(m.is_last_set());
139
140        let m = m.unset_setting(ArgSettings::Required | ArgSettings::Hidden | ArgSettings::Last);
141        assert!(!m.is_required_set(), "{m:#?}");
142        assert!(!m.is_hide_set(), "{m:#?}");
143        assert!(!m.is_last_set(), "{m:#?}");
144    }
145}
146