From dacc35a768548e29487a875ad84749013ec6a7f1 Mon Sep 17 00:00:00 2001 From: 魏曹先生 <1992414357@qq.com> Date: Tue, 7 Apr 2026 08:56:26 +0800 Subject: Add YesOrNo and TrueOrFalse pickable boolean types --- mingling/src/parser/picker.rs | 3 + mingling/src/parser/picker/bools.rs | 140 ++++++++++++++++++++++++++++++++++++ 2 files changed, 143 insertions(+) create mode 100644 mingling/src/parser/picker/bools.rs (limited to 'mingling/src/parser') diff --git a/mingling/src/parser/picker.rs b/mingling/src/parser/picker.rs index 05021a7..c6c2beb 100644 --- a/mingling/src/parser/picker.rs +++ b/mingling/src/parser/picker.rs @@ -6,6 +6,9 @@ use mingling_core::Flag; #[doc(hidden)] pub mod builtin; +#[doc(hidden)] +pub mod bools; + /// A builder for extracting values from command-line arguments. /// /// The `Picker` struct holds parsed arguments and provides a fluent interface diff --git a/mingling/src/parser/picker/bools.rs b/mingling/src/parser/picker/bools.rs new file mode 100644 index 0000000..f0a2622 --- /dev/null +++ b/mingling/src/parser/picker/bools.rs @@ -0,0 +1,140 @@ +use crate::parser::Pickable; + +#[derive(Debug, Default)] +pub enum YesOrNo { + Yes, + #[default] + No, +} + +impl From for YesOrNo { + fn from(b: bool) -> Self { + if b { YesOrNo::Yes } else { YesOrNo::No } + } +} + +impl From for bool { + fn from(val: YesOrNo) -> Self { + match val { + YesOrNo::Yes => true, + YesOrNo::No => false, + } + } +} + +impl std::ops::Deref for YesOrNo { + type Target = bool; + + fn deref(&self) -> &Self::Target { + static TRUE: bool = true; + static FALSE: bool = false; + match self { + YesOrNo::Yes => &TRUE, + YesOrNo::No => &FALSE, + } + } +} + +impl YesOrNo { + pub fn is_yes(&self) -> bool { + matches!(self, YesOrNo::Yes) + } + + pub fn is_no(&self) -> bool { + matches!(self, YesOrNo::No) + } +} + +impl Pickable for YesOrNo { + type Output = YesOrNo; + + fn pick(args: &mut crate::parser::Argument, flag: mingling_core::Flag) -> Option { + let value = pick_bool(args, flag, &["y", "yes"], &["n", "no"]); + Some(value.into()) + } +} + +#[derive(Debug, Default)] +pub enum TrueOrFalse { + True, + #[default] + False, +} + +impl From for TrueOrFalse { + fn from(b: bool) -> Self { + if b { + TrueOrFalse::True + } else { + TrueOrFalse::False + } + } +} + +impl From for bool { + fn from(val: TrueOrFalse) -> Self { + match val { + TrueOrFalse::True => true, + TrueOrFalse::False => false, + } + } +} + +impl std::ops::Deref for TrueOrFalse { + type Target = bool; + + fn deref(&self) -> &Self::Target { + static TRUE: bool = true; + static FALSE: bool = false; + match self { + TrueOrFalse::True => &TRUE, + TrueOrFalse::False => &FALSE, + } + } +} + +impl TrueOrFalse { + pub fn is_true(&self) -> bool { + matches!(self, TrueOrFalse::True) + } + + pub fn is_false(&self) -> bool { + matches!(self, TrueOrFalse::False) + } +} + +impl Pickable for TrueOrFalse { + type Output = TrueOrFalse; + + fn pick(args: &mut crate::parser::Argument, flag: mingling_core::Flag) -> Option { + let value = pick_bool(args, flag, &["true", "t"], &["false", "f"]); + Some(value.into()) + } +} + +fn pick_bool( + args: &mut crate::parser::Argument, + flag: mingling_core::Flag, + positive: &[&str], + negative: &[&str], +) -> bool { + let has_flag = args.pick_flag(flag.clone()); + if !has_flag { + let content = args.pick_argument(flag); + match content { + Some(content) => { + let s = content.as_str(); + if positive.contains(&s) { + true + } else if negative.contains(&s) { + false + } else { + false + } + } + None => false, + } + } else { + true + } +} -- cgit