From 74b5a80475e2230c0a494beac5ec86a985c2974f Mon Sep 17 00:00:00 2001 From: 魏曹先生 <1992414357@qq.com> Date: Thu, 21 May 2026 15:12:58 +0800 Subject: Refactor REPL hooks into modular setups and add new hook types --- mingling/src/setups/repl_basic.rs | 86 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 mingling/src/setups/repl_basic.rs (limited to 'mingling/src/setups') 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 ProgramSetup for BasicREPLReadlineSetup +where + C: ProgramCollect, +{ + fn setup(&mut self, program: &mut Program) { + 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) -> Self { + Self::Prompt(prompt.into()) + } + + /// Creates a new [`BasicREPLPrompt`] with the given function. + pub fn func(func: fn() -> String) -> Self { + Self::Func(func) + } +} + +impl ProgramSetup for BasicREPLPromptSetup +where + C: ProgramCollect, +{ + fn setup(&mut self, program: &mut Program) { + match self { + BasicREPLPromptSetup::Prompt(prompt) => { + static PROMPT: std::sync::OnceLock = 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 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 ProgramSetup for BasicREPLOutputSetup +where + C: ProgramCollect, +{ + fn setup(&mut self, program: &mut Program) { + program.with_hook(ProgramHook::empty().on_repl_receive_result(|r| { + if !r.is_empty() { + println!("{}", r.trim()) + } + })); + } +} + +fn readline() -> Result { + let mut input = String::new(); + std::io::stdout().flush()?; + std::io::stdin().read_line(&mut input)?; + Ok(input.trim().to_string()) +} -- cgit