summaryrefslogtreecommitdiff
path: root/mingling/src
diff options
context:
space:
mode:
Diffstat (limited to 'mingling/src')
-rw-r--r--mingling/src/any.rs128
-rw-r--r--mingling/src/asset.rs4
-rw-r--r--mingling/src/asset/chain.rs8
-rw-r--r--mingling/src/asset/chain/error.rs13
-rw-r--r--mingling/src/asset/dispatcher.rs195
-rw-r--r--mingling/src/asset/node.rs54
-rw-r--r--mingling/src/asset/renderer.rs6
-rw-r--r--mingling/src/lib.rs39
-rw-r--r--mingling/src/program.rs132
-rw-r--r--mingling/src/program/config.rs26
-rw-r--r--mingling/src/program/exec.rs126
-rw-r--r--mingling/src/program/exec/error.rs46
-rw-r--r--mingling/src/program/flag.rs148
-rw-r--r--mingling/src/program/hint.rs62
-rw-r--r--mingling/src/program/setup.rs19
-rw-r--r--mingling/src/program/setup/basic.rs31
-rw-r--r--mingling/src/renderer.rs1
-rw-r--r--mingling/src/renderer/render_result.rs38
18 files changed, 0 insertions, 1076 deletions
diff --git a/mingling/src/any.rs b/mingling/src/any.rs
deleted file mode 100644
index 1bce96a..0000000
--- a/mingling/src/any.rs
+++ /dev/null
@@ -1,128 +0,0 @@
-#[cfg(feature = "general_renderer")]
-use serde::Serialize;
-
-use crate::error::ChainProcessError;
-
-#[derive(Debug)]
-pub struct AnyOutput {
- inner: Box<dyn std::any::Any + Send + 'static>,
- pub type_id: std::any::TypeId,
-}
-
-impl AnyOutput {
- #[cfg(feature = "general_renderer")]
- pub fn new<T>(value: T) -> Self
- where
- T: Send + Serialize + 'static,
- {
- Self {
- inner: Box::new(value),
- type_id: std::any::TypeId::of::<T>(),
- }
- }
-
- #[cfg(not(feature = "general_renderer"))]
- pub fn new<T>(value: T) -> Self
- where
- T: Send + 'static,
- {
- Self {
- inner: Box::new(value),
- type_id: std::any::TypeId::of::<T>(),
- }
- }
-
- pub fn downcast<T: 'static>(self) -> Result<T, Self> {
- if self.type_id == std::any::TypeId::of::<T>() {
- Ok(*self.inner.downcast::<T>().unwrap())
- } else {
- Err(self)
- }
- }
-
- pub fn is<T: 'static>(&self) -> bool {
- self.type_id == std::any::TypeId::of::<T>()
- }
-
- /// Route the output to the next Chain
- pub fn route_chain(self) -> ChainProcess {
- ChainProcess::Ok((self, Next::Chain))
- }
-
- /// Route the output to the Renderer, ending execution
- pub fn route_renderer(self) -> ChainProcess {
- ChainProcess::Ok((self, Next::Renderer))
- }
-}
-
-impl std::ops::Deref for AnyOutput {
- type Target = dyn std::any::Any + Send + 'static;
-
- fn deref(&self) -> &Self::Target {
- &*self.inner
- }
-}
-
-impl std::ops::DerefMut for AnyOutput {
- fn deref_mut(&mut self) -> &mut Self::Target {
- &mut *self.inner
- }
-}
-
-pub enum ChainProcess {
- Ok((AnyOutput, Next)),
- Err(ChainProcessError),
-}
-
-pub enum Next {
- Chain,
- Renderer,
-}
-
-impl ChainProcess {
- pub fn is_next(&self) -> bool {
- matches!(self, Self::Ok(_))
- }
-
- pub fn is_err(&self) -> bool {
- matches!(self, Self::Err(_))
- }
-
- pub fn next(&self) -> Option<&Next> {
- match self {
- Self::Ok((_, next)) => Some(next),
- Self::Err(_) => None,
- }
- }
-
- pub fn err(&self) -> Option<&ChainProcessError> {
- match self {
- Self::Ok(_) => None,
- Self::Err(err) => Some(err),
- }
- }
-
- pub fn unwrap(self) -> (AnyOutput, Next) {
- match self {
- Self::Ok(tuple) => tuple,
- Self::Err(_) => panic!("called `ChainProcess2::unwrap()` on an `Error` value"),
- }
- }
-
- pub fn unwrap_or(self, default: (AnyOutput, Next)) -> (AnyOutput, Next) {
- match self {
- Self::Ok(tuple) => tuple,
- Self::Err(_) => default,
- }
- }
-
- pub fn unwrap_or_else<F>(self, f: F) -> (AnyOutput, Next)
- where
- F: FnOnce(ChainProcessError) -> (AnyOutput, Next),
- {
- match self {
- Self::Ok(tuple) => tuple,
- Self::Err(err) => f(err),
- }
- }
-}
diff --git a/mingling/src/asset.rs b/mingling/src/asset.rs
deleted file mode 100644
index c2adf4e..0000000
--- a/mingling/src/asset.rs
+++ /dev/null
@@ -1,4 +0,0 @@
-pub mod chain;
-pub mod dispatcher;
-pub mod node;
-pub mod renderer;
diff --git a/mingling/src/asset/chain.rs b/mingling/src/asset/chain.rs
deleted file mode 100644
index 1ea1125..0000000
--- a/mingling/src/asset/chain.rs
+++ /dev/null
@@ -1,8 +0,0 @@
-use crate::ChainProcess;
-
-pub mod error;
-
-pub trait Chain {
- type Previous;
- fn proc(p: Self::Previous) -> impl Future<Output = ChainProcess> + Send;
-}
diff --git a/mingling/src/asset/chain/error.rs b/mingling/src/asset/chain/error.rs
deleted file mode 100644
index d4da4ac..0000000
--- a/mingling/src/asset/chain/error.rs
+++ /dev/null
@@ -1,13 +0,0 @@
-use crate::AnyOutput;
-
-#[derive(thiserror::Error, Debug)]
-pub enum ChainProcessError {
- #[error("Other error: {0}")]
- Other(String),
-
- #[error("IO error: {0}")]
- IO(#[from] std::io::Error),
-
- #[error("Broken chain")]
- Broken(AnyOutput),
-}
diff --git a/mingling/src/asset/dispatcher.rs b/mingling/src/asset/dispatcher.rs
deleted file mode 100644
index 13e35f7..0000000
--- a/mingling/src/asset/dispatcher.rs
+++ /dev/null
@@ -1,195 +0,0 @@
-use crate::{ChainProcess, Program, asset::node::Node};
-
-pub trait Dispatcher {
- fn node(&self) -> Node;
- fn begin(&self, args: Vec<String>) -> ChainProcess;
- fn clone_dispatcher(&self) -> Box<dyn Dispatcher>;
-}
-
-impl Clone for Box<dyn Dispatcher> {
- fn clone(&self) -> Self {
- self.clone_dispatcher()
- }
-}
-
-impl<C: crate::program::ProgramCollect> Program<C> {
- /// Adds a dispatcher to the program.
- pub fn with_dispatcher<D>(&mut self, dispatcher: D)
- where
- D: Into<Dispatchers>,
- {
- let dispatchers = dispatcher.into().dispatcher;
- self.dispatcher.extend(dispatchers);
- }
-}
-
-pub struct Dispatchers {
- dispatcher: Vec<Box<dyn Dispatcher + 'static>>,
-}
-
-impl<D> From<D> for Dispatchers
-where
- D: Dispatcher + 'static,
-{
- fn from(dispatcher: D) -> Self {
- Self {
- dispatcher: vec![Box::new(dispatcher)],
- }
- }
-}
-
-impl From<Vec<Box<dyn Dispatcher>>> for Dispatchers {
- fn from(dispatcher: Vec<Box<dyn Dispatcher>>) -> Self {
- Self { dispatcher }
- }
-}
-
-impl From<Box<dyn Dispatcher>> for Dispatchers {
- fn from(dispatcher: Box<dyn Dispatcher>) -> Self {
- Self {
- dispatcher: vec![dispatcher],
- }
- }
-}
-
-impl<D> From<(D,)> for Dispatchers
-where
- D: Dispatcher + 'static,
-{
- fn from(dispatcher: (D,)) -> Self {
- Self {
- dispatcher: vec![Box::new(dispatcher.0)],
- }
- }
-}
-
-impl<D1, D2> From<(D1, D2)> for Dispatchers
-where
- D1: Dispatcher + 'static,
- D2: Dispatcher + 'static,
-{
- fn from(dispatchers: (D1, D2)) -> Self {
- Self {
- dispatcher: vec![Box::new(dispatchers.0), Box::new(dispatchers.1)],
- }
- }
-}
-
-impl<D1, D2, D3> From<(D1, D2, D3)> for Dispatchers
-where
- D1: Dispatcher + 'static,
- D2: Dispatcher + 'static,
- D3: Dispatcher + 'static,
-{
- fn from(dispatchers: (D1, D2, D3)) -> Self {
- Self {
- dispatcher: vec![
- Box::new(dispatchers.0),
- Box::new(dispatchers.1),
- Box::new(dispatchers.2),
- ],
- }
- }
-}
-
-impl<D1, D2, D3, D4> From<(D1, D2, D3, D4)> for Dispatchers
-where
- D1: Dispatcher + 'static,
- D2: Dispatcher + 'static,
- D3: Dispatcher + 'static,
- D4: Dispatcher + 'static,
-{
- fn from(dispatchers: (D1, D2, D3, D4)) -> Self {
- Self {
- dispatcher: vec![
- Box::new(dispatchers.0),
- Box::new(dispatchers.1),
- Box::new(dispatchers.2),
- Box::new(dispatchers.3),
- ],
- }
- }
-}
-
-impl<D1, D2, D3, D4, D5> From<(D1, D2, D3, D4, D5)> for Dispatchers
-where
- D1: Dispatcher + 'static,
- D2: Dispatcher + 'static,
- D3: Dispatcher + 'static,
- D4: Dispatcher + 'static,
- D5: Dispatcher + 'static,
-{
- fn from(dispatchers: (D1, D2, D3, D4, D5)) -> Self {
- Self {
- dispatcher: vec![
- Box::new(dispatchers.0),
- Box::new(dispatchers.1),
- Box::new(dispatchers.2),
- Box::new(dispatchers.3),
- Box::new(dispatchers.4),
- ],
- }
- }
-}
-
-impl<D1, D2, D3, D4, D5, D6> From<(D1, D2, D3, D4, D5, D6)> for Dispatchers
-where
- D1: Dispatcher + 'static,
- D2: Dispatcher + 'static,
- D3: Dispatcher + 'static,
- D4: Dispatcher + 'static,
- D5: Dispatcher + 'static,
- D6: Dispatcher + 'static,
-{
- fn from(dispatchers: (D1, D2, D3, D4, D5, D6)) -> Self {
- Self {
- dispatcher: vec![
- Box::new(dispatchers.0),
- Box::new(dispatchers.1),
- Box::new(dispatchers.2),
- Box::new(dispatchers.3),
- Box::new(dispatchers.4),
- Box::new(dispatchers.5),
- ],
- }
- }
-}
-
-impl<D1, D2, D3, D4, D5, D6, D7> From<(D1, D2, D3, D4, D5, D6, D7)> for Dispatchers
-where
- D1: Dispatcher + 'static,
- D2: Dispatcher + 'static,
- D3: Dispatcher + 'static,
- D4: Dispatcher + 'static,
- D5: Dispatcher + 'static,
- D6: Dispatcher + 'static,
- D7: Dispatcher + 'static,
-{
- fn from(dispatchers: (D1, D2, D3, D4, D5, D6, D7)) -> Self {
- Self {
- dispatcher: vec![
- Box::new(dispatchers.0),
- Box::new(dispatchers.1),
- Box::new(dispatchers.2),
- Box::new(dispatchers.3),
- Box::new(dispatchers.4),
- Box::new(dispatchers.5),
- Box::new(dispatchers.6),
- ],
- }
- }
-}
-
-impl std::ops::Deref for Dispatchers {
- type Target = Vec<Box<dyn Dispatcher + 'static>>;
-
- fn deref(&self) -> &Self::Target {
- &self.dispatcher
- }
-}
-
-impl From<Dispatchers> for Vec<Box<dyn Dispatcher + 'static>> {
- fn from(val: Dispatchers) -> Self {
- val.dispatcher
- }
-}
diff --git a/mingling/src/asset/node.rs b/mingling/src/asset/node.rs
deleted file mode 100644
index c8b7600..0000000
--- a/mingling/src/asset/node.rs
+++ /dev/null
@@ -1,54 +0,0 @@
-use just_fmt::kebab_case;
-
-#[derive(Debug, Default)]
-pub struct Node {
- node: Vec<String>,
-}
-
-impl Node {
- pub fn join(self, node: impl Into<String>) -> Node {
- let mut new_node = self.node;
- new_node.push(node.into());
- Node { node: new_node }
- }
-}
-
-impl From<&str> for Node {
- fn from(s: &str) -> Self {
- let node = s.split('.').map(|part| kebab_case!(part)).collect();
- Node { node }
- }
-}
-
-impl From<String> for Node {
- fn from(s: String) -> Self {
- let node = s.split('.').map(|part| kebab_case!(part)).collect();
- Node { node }
- }
-}
-
-impl PartialEq for Node {
- fn eq(&self, other: &Self) -> bool {
- self.node == other.node
- }
-}
-
-impl Eq for Node {}
-
-impl PartialOrd for Node {
- fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
- Some(self.cmp(other))
- }
-}
-
-impl Ord for Node {
- fn cmp(&self, other: &Self) -> std::cmp::Ordering {
- self.node.cmp(&other.node)
- }
-}
-
-impl std::fmt::Display for Node {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- write!(f, "{}", self.node.join("."))
- }
-}
diff --git a/mingling/src/asset/renderer.rs b/mingling/src/asset/renderer.rs
deleted file mode 100644
index 3852b55..0000000
--- a/mingling/src/asset/renderer.rs
+++ /dev/null
@@ -1,6 +0,0 @@
-use crate::RenderResult;
-
-pub trait Renderer {
- type Previous;
- fn render(p: Self::Previous, r: &mut RenderResult);
-}
diff --git a/mingling/src/lib.rs b/mingling/src/lib.rs
deleted file mode 100644
index 4d9bcc5..0000000
--- a/mingling/src/lib.rs
+++ /dev/null
@@ -1,39 +0,0 @@
-mod any;
-pub use crate::any::*;
-
-pub mod error {
- pub use crate::asset::chain::error::*;
- pub use crate::exec::error::*;
-}
-
-mod program;
-pub use crate::program::*;
-pub mod setup {
- pub use crate::program::setup::*;
-}
-pub mod hint {
- pub use crate::program::hint::*;
-}
-
-#[cfg(feature = "macros")]
-#[allow(unused_imports)]
-pub mod macros {
- pub use mingling_macros::chain;
- pub use mingling_macros::chain_struct;
- pub use mingling_macros::dispatcher;
- pub use mingling_macros::dispatcher_render;
- pub use mingling_macros::node;
- pub use mingling_macros::program;
- pub use mingling_macros::r_print;
- pub use mingling_macros::r_println;
- pub use mingling_macros::renderer;
-}
-
-mod renderer;
-
-mod asset;
-pub use crate::asset::chain::*;
-pub use crate::asset::dispatcher::*;
-pub use crate::asset::node::*;
-pub use crate::asset::renderer::*;
-pub use crate::renderer::render_result::*;
diff --git a/mingling/src/program.rs b/mingling/src/program.rs
deleted file mode 100644
index 3d8bc14..0000000
--- a/mingling/src/program.rs
+++ /dev/null
@@ -1,132 +0,0 @@
-use crate::{
- AnyOutput, ChainProcess, RenderResult, asset::dispatcher::Dispatcher,
- error::ProgramExecuteError,
-};
-use std::{env, pin::Pin};
-
-pub mod exec;
-pub mod hint;
-pub mod setup;
-
-mod config;
-pub use config::*;
-
-mod flag;
-pub use flag::*;
-use tokio::io::AsyncWriteExt;
-
-#[derive(Default)]
-pub struct Program<C: ProgramCollect> {
- pub(crate) collect: std::marker::PhantomData<C>,
-
- pub(crate) args: Vec<String>,
- pub(crate) dispatcher: Vec<Box<dyn Dispatcher>>,
-
- pub stdout_setting: ProgramStdoutSetting,
- pub user_context: ProgramUserContext,
-}
-
-impl<C> Program<C>
-where
- C: ProgramCollect,
-{
- /// Creates a new Program instance, initializing args from environment.
- pub fn new() -> Self {
- Program {
- collect: std::marker::PhantomData,
- args: env::args().collect(),
- dispatcher: Vec::new(),
- stdout_setting: Default::default(),
- user_context: Default::default(),
- }
- }
-
- /// Run the command line program
- pub async fn exec_without_render(mut self) -> Result<RenderResult, ProgramExecuteError> {
- self.args = self.args.iter().skip(1).cloned().collect();
- crate::exec::exec(self).await.map_err(|e| e.into())
- }
-
- /// Run the command line program
- pub async fn exec(self) {
- let stdout_setting = self.stdout_setting.clone();
- let result = match self.exec_without_render().await {
- Ok(r) => r,
- Err(e) => match e {
- ProgramExecuteError::DispatcherNotFound => {
- eprintln!("Dispatcher not found");
- return;
- }
- ProgramExecuteError::Other(e) => {
- eprintln!("{}", e);
- return;
- }
- },
- };
-
- // Render result
- if stdout_setting.render_output && !result.is_empty() {
- print!("{}", result);
- if let Err(e) = tokio::io::stdout().flush().await
- && stdout_setting.error_output
- {
- eprintln!("{}", e);
- }
- }
- }
-}
-
-pub trait ProgramCollect {
- fn render(any: AnyOutput, r: &mut RenderResult);
- fn do_chain(any: AnyOutput) -> Pin<Box<dyn Future<Output = ChainProcess> + Send>>;
- fn has_renderer(any: &AnyOutput) -> bool;
- fn has_chain(any: &AnyOutput) -> bool;
-}
-
-#[macro_export]
-#[doc(hidden)]
-macro_rules! __dispatch_program_renderers {
- (
- $( $render_ty:ty => $prev_ty:ty, )*
- ) => {
- fn render(any: mingling::AnyOutput, r: &mut mingling::RenderResult) {
- match any.type_id {
- $(
- id if id == std::any::TypeId::of::<$prev_ty>() => {
- let value = any.downcast::<$prev_ty>().unwrap();
- <$render_ty as mingling::Renderer>::render(value, r);
- }
- )*
- _ => (),
- }
- }
- };
-}
-
-#[macro_export]
-#[doc(hidden)]
-macro_rules! __dispatch_program_chains {
- (
- $( $chain_ty:ty => $chain_prev:ty, )*
- ) => {
- fn do_chain(
- any: mingling::AnyOutput,
- ) -> std::pin::Pin<Box<dyn Future<Output = mingling::ChainProcess> + Send>> {
- match any.type_id {
- $(
- id if id == std::any::TypeId::of::<$chain_prev>() => {
- let value = any.downcast::<$chain_prev>().unwrap();
- let fut = async { <$chain_ty as mingling::Chain>::proc(value).await };
- Box::pin(fut)
- }
- )*
- _ => Box::pin(async move {
- mingling::AnyOutput::new(mingling::hint::NoChainFound {
- name: format!("{:?}", any.type_id).to_string(),
- })
- .route_chain()
- }),
- }
- }
- };
-}
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<C: ProgramCollect>(
- program: Program<C>,
-) -> Result<RenderResult, ProgramInternalExecuteError> {
- // Match user input
- let matched: (Box<dyn Dispatcher>, Vec<String>) = 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<dyn Dispatcher> = 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::<C>(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(&current) {
- match C::do_chain(current).await {
- ChainProcess::Ok((any, Next::Renderer)) => return Ok(render::<C>(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(&current) {
- 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<dyn Dispatcher> = Box::new(RendererNotFound);
-
- match disp.begin(vec![format!("{:?}", current.type_id)]) {
- ChainProcess::Ok((any, Next::Renderer)) => return Ok(render::<C>(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<C: ProgramCollect>(
- program: &Program<C>,
-) -> Result<(&Box<dyn Dispatcher>, Vec<String>), 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<dyn Dispatcher>)> = 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<String> = 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<String> = program.args.iter().skip(prefix_len).cloned().collect();
- Ok((matched_prefix.1, trimmed_args))
- }
- }
-}
-
-#[inline(always)]
-fn render<C: ProgramCollect>(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<C: ProgramCollect>(program: &Program<C>) -> Vec<(String, &Box<dyn Dispatcher>)> {
- program
- .dispatcher
- .iter()
- .map(|disp| {
- let node_str = disp
- .node()
- .to_string()
- .split('.')
- .collect::<Vec<_>>()
- .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<ProgramInternalExecuteError> 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<ChainProcessError> 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<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<C> Program<C>
-where
- C: ProgramCollect,
-{
- /// 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<C>, 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<C>),
- 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;
- }
- }
- }
-
- /// Extracts a global argument (with value) from arguments
- pub fn pick_global_argument<F>(&mut self, flag: F) -> Option<String>
- where
- F: Into<Flag>,
- {
- 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<F>(&mut self, flag: F) -> bool
- where
- F: Into<Flag>,
- {
- 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<String>,
-}
-
-#[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<String>) -> ChainProcess {
- AnyOutput::new(NoDispatcherFound { args }).route_renderer()
- }
-
- fn clone_dispatcher(&self) -> Box<dyn Dispatcher> {
- 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<String>) -> ChainProcess {
- AnyOutput::new(NoRendererFound {
- type_to_render: args.first().unwrap().clone(),
- })
- .route_renderer()
- }
-
- fn clone_dispatcher(&self) -> Box<dyn Dispatcher> {
- 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<C: ProgramCollect> {
- fn setup(&mut self, program: &mut Program<C>);
-}
-
-impl<C> Program<C>
-where
- C: ProgramCollect,
-{
- /// Load and execute init logic
- pub fn with_setup<S: ProgramSetup<C> + '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<C> ProgramSetup<C> for BasicProgramSetup
-where
- C: ProgramCollect,
-{
- fn setup(&mut self, program: &mut Program<C>) {
- 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;
- });
- }
-}
diff --git a/mingling/src/renderer.rs b/mingling/src/renderer.rs
deleted file mode 100644
index 631092b..0000000
--- a/mingling/src/renderer.rs
+++ /dev/null
@@ -1 +0,0 @@
-pub mod render_result;
diff --git a/mingling/src/renderer/render_result.rs b/mingling/src/renderer/render_result.rs
deleted file mode 100644
index 73c38e7..0000000
--- a/mingling/src/renderer/render_result.rs
+++ /dev/null
@@ -1,38 +0,0 @@
-use std::{
- fmt::{Display, Formatter},
- ops::Deref,
-};
-
-#[derive(Default, Debug, PartialEq)]
-pub struct RenderResult {
- render_text: String,
-}
-
-impl Display for RenderResult {
- fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
- writeln!(f, "{}", self.render_text.trim())
- }
-}
-
-impl Deref for RenderResult {
- type Target = str;
-
- fn deref(&self) -> &Self::Target {
- &self.render_text
- }
-}
-
-impl RenderResult {
- pub fn print(&mut self, text: &str) {
- self.render_text.push_str(text);
- }
-
- pub fn println(&mut self, text: &str) {
- self.render_text.push_str(text);
- self.render_text.push('\n');
- }
-
- pub fn clear(&mut self) {
- self.render_text.clear();
- }
-}