diff options
Diffstat (limited to 'mingling/src/program')
| -rw-r--r-- | mingling/src/program/config.rs | 33 | ||||
| -rw-r--r-- | mingling/src/program/flag.rs | 115 | ||||
| -rw-r--r-- | mingling/src/program/setup.rs | 15 | ||||
| -rw-r--r-- | mingling/src/program/setup/basic.rs | 25 |
4 files changed, 188 insertions, 0 deletions
diff --git a/mingling/src/program/config.rs b/mingling/src/program/config.rs new file mode 100644 index 0000000..93507e7 --- /dev/null +++ b/mingling/src/program/config.rs @@ -0,0 +1,33 @@ +pub struct ProgramStdoutSetting { + /// Output error messages + pub error_output: bool, + + /// Render results and output + pub render_output: bool, +} + +impl Default for ProgramStdoutSetting { + fn default() -> Self { + ProgramStdoutSetting { + error_output: true, + render_output: true, + } + } +} + +pub struct ProgramUserContext { + /// View help information instead of running the command + pub help: bool, + + /// Skip user confirmation step + pub confirm: bool, +} + +impl Default for ProgramUserContext { + fn default() -> Self { + ProgramUserContext { + help: false, + confirm: false, + } + } +} diff --git a/mingling/src/program/flag.rs b/mingling/src/program/flag.rs new file mode 100644 index 0000000..0178ebe --- /dev/null +++ b/mingling/src/program/flag.rs @@ -0,0 +1,115 @@ +use crate::Program; + +pub struct Flag { + vec: Vec<&'static str>, +} + +impl From<&'static str> for Flag { + fn from(s: &'static str) -> Self { + Flag { vec: vec![s] } + } +} + +impl From<&'static [&'static str]> for Flag { + fn from(slice: &'static [&'static str]) -> Self { + Flag { + vec: slice.to_vec(), + } + } +} + +impl<const N: usize> From<[&'static str; N]> for Flag { + fn from(slice: [&'static str; N]) -> Self { + Flag { + vec: slice.to_vec(), + } + } +} + +impl<const N: usize> From<&'static [&'static str; N]> for Flag { + fn from(slice: &'static [&'static str; N]) -> Self { + Flag { + vec: slice.to_vec(), + } + } +} + +impl AsRef<[&'static str]> for Flag { + fn as_ref(&self) -> &[&'static str] { + &self.vec + } +} + +impl std::ops::Deref for Flag { + type Target = [&'static str]; + + fn deref(&self) -> &Self::Target { + &self.vec + } +} + +macro_rules! special_flag { + ($args:expr, $flag:expr) => {{ + let flag = $flag; + let found = $args.iter().any(|arg| arg == flag); + $args.retain(|arg| arg != flag); + found + }}; +} + +macro_rules! special_argument { + ($args:expr, $flag:expr) => {{ + let flag = $flag; + let mut value: Option<String> = None; + let mut i = 0; + while i < $args.len() { + if &$args[i] == flag { + if i + 1 < $args.len() { + value = Some($args[i + 1].clone()); + $args.remove(i + 1); + $args.remove(i); + } else { + value = None; + $args.remove(i); + } + break; + } + i += 1; + } + value + }}; +} + +impl Program { + /// Registers a global argument (with value) and its handler. + pub fn global_argument<F, A>(&mut self, arguments: A, do_fn: F) + where + F: Fn(&mut Program, String), + A: Into<Flag>, + { + let flag = arguments.into(); + for argument in flag.iter() { + let value = special_argument!(self.args, argument); + if let Some(value) = value { + do_fn(self, value); + return; + } + } + } + + /// Registers a global flag (boolean) and its handler. + pub fn global_flag<F, A>(&mut self, flag: A, do_fn: F) + where + F: Fn(&mut Program), + A: Into<Flag>, + { + let flag = flag.into(); + for argument in flag.iter() { + let enabled = special_flag!(self.args, argument); + if enabled { + do_fn(self); + return; + } + } + } +} diff --git a/mingling/src/program/setup.rs b/mingling/src/program/setup.rs new file mode 100644 index 0000000..fdf7b04 --- /dev/null +++ b/mingling/src/program/setup.rs @@ -0,0 +1,15 @@ +use crate::program::Program; + +mod basic; +pub use basic::*; + +pub trait ProgramSetup { + fn setup(program: &mut Program); +} + +impl Program { + /// Load and execute init logic + pub fn with_setup<S: ProgramSetup + 'static>(&mut self, _setup: S) { + S::setup(self); + } +} diff --git a/mingling/src/program/setup/basic.rs b/mingling/src/program/setup/basic.rs new file mode 100644 index 0000000..0ea72a6 --- /dev/null +++ b/mingling/src/program/setup/basic.rs @@ -0,0 +1,25 @@ +use crate::program::{Program, setup::ProgramSetup}; + +/// Performs basic program initialization: +/// +/// - Collects `--quiet` flag to control message rendering +/// - Collects `--help` flag to enable help mode +/// - Collects `--confirm` flag to skip user confirmation +pub struct BasicProgramSetup; + +impl ProgramSetup for BasicProgramSetup { + fn setup(program: &mut Program) { + program.global_flag(["--quiet", "-q"], |p| { + p.stdout_setting.render_output = false; + p.stdout_setting.error_output = false; + }); + + program.global_flag(["--help", "-h"], |p| { + p.user_context.help = true; + }); + + program.global_flag(["--confirm", "-C"], |p| { + p.user_context.confirm = true; + }); + } +} |
