Skip to main content

lunar_lib/
prompts.rs

1use std::{
2    fmt::{Arguments, Debug},
3    sync::OnceLock,
4};
5
6mod cli_prompter;
7pub use cli_prompter::*;
8
9static PROMPTER: OnceLock<&'static dyn Prompter> = OnceLock::new();
10pub fn set_prompter(prompter: &'static dyn Prompter) -> Result<(), &'static dyn Prompter> {
11    PROMPTER.set(prompter)
12}
13pub fn get_prompter() -> Option<&'static dyn Prompter> {
14    PROMPTER.get().copied()
15}
16
17pub trait Prompter: Sync + Debug {
18    /// Tells the prompter to start an "Okay" prompt
19    ///
20    /// This prompt just requires user input for a confirmation something happend.
21    /// An example usage is "Press any key to continue..."
22    fn okay(&self, msg: Arguments);
23
24    /// Tells the prompter to start a "Yes/No" prompt
25    ///
26    /// This prompt just requires user input for a confirmation if they want to do something.
27    /// An example usage is "Are you sure you want to do this? \[Y/n\]"
28    ///
29    /// This function should return [`None`] if the result couldn't be parsed
30    fn ask(&self, msg: Arguments, default: bool) -> Option<bool>;
31}
32
33/// Requests an "Okay" prompt to the current prompter lazily using format args
34///
35/// If no prompter is set, the args will not be parsed
36#[macro_export]
37macro_rules! okay {
38    ($($arg:tt)*) => {{
39        if let Some(prompter) = $crate::prompts::get_prompter() {
40            prompter.okay(format_args!($($arg)*));
41        }
42    }};
43}
44
45/// Requests an "Ask" or "Yes/No" prompt to the current prompter lazily using format args
46///
47/// If no prompter is set, the args will not be parsed
48#[macro_export]
49macro_rules! ask {
50    ($default:expr, $($arg:tt)*) => {{
51        if let Some(prompter) = $crate::prompts::get_prompter() {
52            prompter.ask(format_args!($($arg)*), $default)
53        } else {
54            None
55        }
56    }};
57}