From 596e5e2440df2d32f1cf3e052dc633e774edf6ee Mon Sep 17 00:00:00 2001 From: 魏曹先生 <1992414357@qq.com> Date: Sun, 29 Mar 2026 21:48:23 +0800 Subject: Rename mingling to mingling_core and update dependencies --- mingling/src/program/config.rs | 26 ------- mingling/src/program/exec.rs | 126 ------------------------------ mingling/src/program/exec/error.rs | 46 ----------- mingling/src/program/flag.rs | 148 ------------------------------------ mingling/src/program/hint.rs | 62 --------------- mingling/src/program/setup.rs | 19 ----- mingling/src/program/setup/basic.rs | 31 -------- 7 files changed, 458 deletions(-) delete mode 100644 mingling/src/program/config.rs delete mode 100644 mingling/src/program/exec.rs delete mode 100644 mingling/src/program/exec/error.rs delete mode 100644 mingling/src/program/flag.rs delete mode 100644 mingling/src/program/hint.rs delete mode 100644 mingling/src/program/setup.rs delete mode 100644 mingling/src/program/setup/basic.rs (limited to 'mingling/src/program') diff --git a/mingling/src/program/config.rs b/mingling/src/program/config.rs deleted file mode 100644 index 386b112..0000000 --- a/mingling/src/program/config.rs +++ /dev/null @@ -1,26 +0,0 @@ -#[derive(Debug, Clone)] -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, - } - } -} - -#[derive(Debug, Clone, Default)] -pub struct ProgramUserContext { - /// View help information instead of running the command - pub help: bool, - - /// Skip user confirmation step - pub confirm: bool, -} diff --git a/mingling/src/program/exec.rs b/mingling/src/program/exec.rs deleted file mode 100644 index 853bff1..0000000 --- a/mingling/src/program/exec.rs +++ /dev/null @@ -1,126 +0,0 @@ -#![allow(clippy::borrowed_box)] - -use crate::{ - AnyOutput, ChainProcess, Dispatcher, Next, Program, ProgramCollect, RenderResult, - error::ProgramInternalExecuteError, - hint::{DispatcherNotFound, RendererNotFound}, -}; - -pub mod error; - -pub async fn exec( - program: Program, -) -> Result { - // Match user input - let matched: (Box, Vec) = match match_user_input(&program) { - Ok(r) => (r.0.clone(), r.1), - Err(ProgramInternalExecuteError::DispatcherNotFound) => { - // If no Dispatcher is found, dispatch to the DispatcherNotFound Dispatcher - // to route it to the NoDispatcherFound struct - let disp: Box = Box::new(DispatcherNotFound); - (disp, program.args) - } - Err(e) => return Err(e), - }; - - // Entry point - let (dispatcher, args) = matched; - let mut current = match dispatcher.begin(args) { - ChainProcess::Ok((any, Next::Renderer)) => return Ok(render::(any)), - ChainProcess::Ok((any, Next::Chain)) => any, - ChainProcess::Err(e) => return Err(e.into()), - }; - - loop { - current = { - // If a chain exists, execute as a chain - if C::has_chain(¤t) { - match C::do_chain(current).await { - ChainProcess::Ok((any, Next::Renderer)) => return Ok(render::(any)), - ChainProcess::Ok((any, Next::Chain)) => any, - ChainProcess::Err(e) => return Err(e.into()), - } - } - // If no chain exists, attempt to render - else if C::has_renderer(¤t) { - let mut render_result = RenderResult::default(); - C::render(current, &mut render_result); - return Ok(render_result); - } - // If no renderer exists, transfer to the RendererNotFound Dispatcher for execution - else { - let disp: Box = Box::new(RendererNotFound); - - match disp.begin(vec![format!("{:?}", current.type_id)]) { - ChainProcess::Ok((any, Next::Renderer)) => return Ok(render::(any)), - ChainProcess::Ok((any, Next::Chain)) => any, - ChainProcess::Err(e) => return Err(e.into()), - } - } - }; - } -} - -/// Match user input against registered dispatchers and return the matched dispatcher and remaining arguments. -fn match_user_input( - program: &Program, -) -> Result<(&Box, Vec), ProgramInternalExecuteError> { - let nodes = get_nodes(program); - let command = format!("{} ", program.args.join(" ")); - - // Find all nodes that match the command prefix - let matching_nodes: Vec<&(String, &Box)> = nodes - .iter() - // Also add a space to the node string to ensure consistent matching logic - .filter(|(node_str, _)| command.starts_with(&format!("{} ", node_str))) - .collect(); - - match matching_nodes.len() { - 0 => { - // No matching node found - Err(ProgramInternalExecuteError::DispatcherNotFound) - } - 1 => { - let matched_prefix = matching_nodes[0]; - let prefix_len = matched_prefix.0.split_whitespace().count(); - let trimmed_args: Vec = program.args.iter().skip(prefix_len).cloned().collect(); - Ok((matched_prefix.1, trimmed_args)) - } - _ => { - // Multiple matching nodes found - // Find the node with the longest length (most specific match) - let matched_prefix = matching_nodes - .iter() - .max_by_key(|node| node.0.len()) - .unwrap(); - - let prefix_len = matched_prefix.0.split_whitespace().count(); - let trimmed_args: Vec = program.args.iter().skip(prefix_len).cloned().collect(); - Ok((matched_prefix.1, trimmed_args)) - } - } -} - -#[inline(always)] -fn render(any: AnyOutput) -> RenderResult { - let mut render_result = RenderResult::default(); - C::render(any, &mut render_result); - render_result -} - -// Get all registered dispatcher names from the program -fn get_nodes(program: &Program) -> Vec<(String, &Box)> { - program - .dispatcher - .iter() - .map(|disp| { - let node_str = disp - .node() - .to_string() - .split('.') - .collect::>() - .join(" "); - (node_str, disp) - }) - .collect() -} diff --git a/mingling/src/program/exec/error.rs b/mingling/src/program/exec/error.rs deleted file mode 100644 index fe66e22..0000000 --- a/mingling/src/program/exec/error.rs +++ /dev/null @@ -1,46 +0,0 @@ -use crate::error::ChainProcessError; - -#[derive(thiserror::Error, Debug)] -pub enum ProgramExecuteError { - #[error("No Dispatcher Found")] - DispatcherNotFound, - - #[error("Other error: {0}")] - Other(String), -} - -#[derive(thiserror::Error, Debug)] -pub enum ProgramInternalExecuteError { - #[error("No Dispatcher Found")] - DispatcherNotFound, - - #[error("Other error: {0}")] - Other(String), - - #[error("IO error: {0}")] - IO(#[from] std::io::Error), -} - -impl From for ProgramExecuteError { - fn from(value: ProgramInternalExecuteError) -> Self { - match value { - ProgramInternalExecuteError::DispatcherNotFound => { - ProgramExecuteError::DispatcherNotFound - } - ProgramInternalExecuteError::Other(s) => ProgramExecuteError::Other(s), - ProgramInternalExecuteError::IO(e) => ProgramExecuteError::Other(format!("{}", e)), - } - } -} - -impl From for ProgramInternalExecuteError { - fn from(value: ChainProcessError) -> Self { - match value { - ChainProcessError::Other(s) => ProgramInternalExecuteError::Other(s), - ChainProcessError::IO(error) => ProgramInternalExecuteError::IO(error), - ChainProcessError::Broken(_) => { - ProgramInternalExecuteError::Other("Broken".to_string()) - } - } - } -} diff --git a/mingling/src/program/flag.rs b/mingling/src/program/flag.rs deleted file mode 100644 index 3a678be..0000000 --- a/mingling/src/program/flag.rs +++ /dev/null @@ -1,148 +0,0 @@ -use crate::{Program, ProgramCollect}; - -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 From<[&'static str; N]> for Flag { - fn from(slice: [&'static str; N]) -> Self { - Flag { - vec: slice.to_vec(), - } - } -} - -impl 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 = 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 -where - C: ProgramCollect, -{ - /// Registers a global argument (with value) and its handler. - pub fn global_argument(&mut self, arguments: A, do_fn: F) - where - F: Fn(&mut Program, String), - A: Into, - { - 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(&mut self, flag: A, do_fn: F) - where - F: Fn(&mut Program), - A: Into, - { - let flag = flag.into(); - for argument in flag.iter() { - let enabled = special_flag!(self.args, argument); - if enabled { - do_fn(self); - return; - } - } - } - - /// Extracts a global argument (with value) from arguments - pub fn pick_global_argument(&mut self, flag: F) -> Option - where - F: Into, - { - let flag: Flag = flag.into(); - for argument in flag.iter() { - let value = special_argument!(self.args, argument); - if value.is_some() { - return value; - } - } - None - } - - /// Extracts global flags from arguments - pub fn pick_global_flag(&mut self, flag: F) -> bool - where - F: Into, - { - let flag: Flag = flag.into(); - for argument in flag.iter() { - let enabled = special_flag!(self.args, argument); - if enabled { - return enabled; - } - } - false - } -} diff --git a/mingling/src/program/hint.rs b/mingling/src/program/hint.rs deleted file mode 100644 index 6dbbac2..0000000 --- a/mingling/src/program/hint.rs +++ /dev/null @@ -1,62 +0,0 @@ -use crate::{AnyOutput, ChainProcess, Dispatcher, Node}; - -/// Marker: Dispatcher Not Found -/// -/// If a Dispatcher outputs NoDispatcherFound to the Chain, -/// the program will terminate directly. -/// -/// You can implement Renderer for NoDispatcherFound -/// to render relevant information when a Dispatcher cannot be found. -#[cfg_attr(feature = "general_renderer", derive(serde::Serialize))] -pub struct NoDispatcherFound { - pub args: Vec, -} - -#[derive(Default)] -#[cfg_attr(feature = "general_renderer", derive(serde::Serialize))] -pub struct DispatcherNotFound; -impl Dispatcher for DispatcherNotFound { - fn node(&self) -> crate::Node { - Node::default().join("_not_found") - } - - fn begin(&self, args: Vec) -> ChainProcess { - AnyOutput::new(NoDispatcherFound { args }).route_renderer() - } - - fn clone_dispatcher(&self) -> Box { - Box::new(DispatcherNotFound) - } -} - -/// Marker: Renderer Not Found -/// -/// If a Chain outputs NoRendererFound to the Chain, -/// the program will terminate directly. -/// -/// You can implement Renderer for NoRendererFound -/// to render relevant information when a Renderer cannot be found. -#[cfg_attr(feature = "general_renderer", derive(serde::Serialize))] -pub struct NoRendererFound { - pub type_to_render: String, -} - -#[derive(Default)] -#[cfg_attr(feature = "general_renderer", derive(serde::Serialize))] -pub struct RendererNotFound; -impl Dispatcher for RendererNotFound { - fn node(&self) -> crate::Node { - Node::default().join("_not_found") - } - - fn begin(&self, args: Vec) -> ChainProcess { - AnyOutput::new(NoRendererFound { - type_to_render: args.first().unwrap().clone(), - }) - .route_renderer() - } - - fn clone_dispatcher(&self) -> Box { - Box::new(RendererNotFound) - } -} diff --git a/mingling/src/program/setup.rs b/mingling/src/program/setup.rs deleted file mode 100644 index e81247e..0000000 --- a/mingling/src/program/setup.rs +++ /dev/null @@ -1,19 +0,0 @@ -use crate::{ProgramCollect, program::Program}; - -mod basic; -pub use basic::*; - -pub trait ProgramSetup { - fn setup(&mut self, program: &mut Program); -} - -impl Program -where - C: ProgramCollect, -{ - /// Load and execute init logic - pub fn with_setup + 'static>(&mut self, mut setup: S) -> S { - S::setup(&mut setup, self); - setup - } -} diff --git a/mingling/src/program/setup/basic.rs b/mingling/src/program/setup/basic.rs deleted file mode 100644 index 43c14b9..0000000 --- a/mingling/src/program/setup/basic.rs +++ /dev/null @@ -1,31 +0,0 @@ -use crate::{ - ProgramCollect, - 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 -where - C: ProgramCollect, -{ - fn setup(&mut self, 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; - }); - } -} -- cgit