diff options
| author | 魏曹先生 <1992414357@qq.com> | 2026-05-21 15:12:58 +0800 |
|---|---|---|
| committer | 魏曹先生 <1992414357@qq.com> | 2026-05-21 15:21:37 +0800 |
| commit | 74b5a80475e2230c0a494beac5ec86a985c2974f (patch) | |
| tree | 18892e7b6c0a0c6b4a3ac65fb497d7a55d5ae16f /mingling/src/setups | |
| parent | 4704f6d54108bcc8f9b2fb7f4b3c4e224b4a7809 (diff) | |
Refactor REPL hooks into modular setups and add new hook types
Diffstat (limited to 'mingling/src/setups')
| -rw-r--r-- | mingling/src/setups/repl_basic.rs | 86 |
1 files changed, 86 insertions, 0 deletions
diff --git a/mingling/src/setups/repl_basic.rs b/mingling/src/setups/repl_basic.rs new file mode 100644 index 0000000..5884489 --- /dev/null +++ b/mingling/src/setups/repl_basic.rs @@ -0,0 +1,86 @@ +use std::io::Write; + +use mingling_core::{Program, ProgramCollect, hook::ProgramHook, setup::ProgramSetup}; + +/// Provides basic Readline capability for the REPL. +pub struct BasicREPLReadlineSetup; +impl<C> ProgramSetup<C> for BasicREPLReadlineSetup +where + C: ProgramCollect<Enum = C>, +{ + fn setup(&mut self, program: &mut Program<C>) { + program.with_hook(ProgramHook::empty().on_repl_readline(|| readline().ok())); + } +} + +/// A basic REPL prompt that displays a prompt string and reads input from the user. +/// +/// **Note:** This setup uses static [`OnceLock`](std::sync::OnceLock) internally, +/// meaning only the last configured instance will take effect globally. +/// Do not configure multiple prompts with different values — only one will be used. +pub enum BasicREPLPromptSetup { + Prompt(String), + Func(fn() -> String), +} + +impl BasicREPLPromptSetup { + /// Creates a new [`BasicREPLPrompt`] with the given prompt string. + pub fn simple(prompt: impl Into<String>) -> Self { + Self::Prompt(prompt.into()) + } + + /// Creates a new [`BasicREPLPrompt`] with the given function. + pub fn func(func: fn() -> String) -> Self { + Self::Func(func) + } +} + +impl<C> ProgramSetup<C> for BasicREPLPromptSetup +where + C: ProgramCollect<Enum = C>, +{ + fn setup(&mut self, program: &mut Program<C>) { + match self { + BasicREPLPromptSetup::Prompt(prompt) => { + static PROMPT: std::sync::OnceLock<String> = std::sync::OnceLock::new(); + let _ = PROMPT.set(prompt.clone()); + fn print_prompt() { + print!("{}", PROMPT.get().unwrap()); + let _ = std::io::stdout().flush(); + } + program.with_hook(ProgramHook::empty().on_repl_pre_readline(print_prompt)); + } + BasicREPLPromptSetup::Func(f) => { + static FUNC: std::sync::OnceLock<fn() -> String> = std::sync::OnceLock::new(); + let _ = FUNC.set(*f); + fn print_func_prompt() { + print!("{}", FUNC.get().unwrap()()); + let _ = std::io::stdout().flush(); + } + program.with_hook(ProgramHook::empty().on_repl_pre_readline(print_func_prompt)); + } + } + } +} + +/// Prints the result of each REPL command to stdout. +pub struct BasicREPLOutputSetup; +impl<C> ProgramSetup<C> for BasicREPLOutputSetup +where + C: ProgramCollect<Enum = C>, +{ + fn setup(&mut self, program: &mut Program<C>) { + program.with_hook(ProgramHook::empty().on_repl_receive_result(|r| { + if !r.is_empty() { + println!("{}", r.trim()) + } + })); + } +} + +fn readline() -> Result<String, std::io::Error> { + let mut input = String::new(); + std::io::stdout().flush()?; + std::io::stdin().read_line(&mut input)?; + Ok(input.trim().to_string()) +} |
