aboutsummaryrefslogtreecommitdiff
path: root/mingling_core
diff options
context:
space:
mode:
Diffstat (limited to 'mingling_core')
-rw-r--r--mingling_core/Cargo.toml4
-rw-r--r--mingling_core/src/any.rs6
-rw-r--r--mingling_core/src/asset.rs36
-rw-r--r--mingling_core/src/asset/chain.rs1
-rw-r--r--mingling_core/src/asset/core_invokes.rs271
-rw-r--r--mingling_core/src/asset/global_resource.rs59
-rw-r--r--mingling_core/src/asset/lazy_resource.rs12
-rw-r--r--mingling_core/src/build.rs13
-rw-r--r--mingling_core/src/build/comp.rs (renamed from mingling_core/src/builds/comp.rs)0
-rw-r--r--mingling_core/src/build/pathf.rs (renamed from mingling_core/src/builds/pathf.rs)0
-rw-r--r--mingling_core/src/builds.rs7
-rw-r--r--mingling_core/src/comp.rs55
-rw-r--r--mingling_core/src/lib.rs121
-rw-r--r--mingling_core/src/private.rs12
-rw-r--r--mingling_core/src/program/exec.rs177
-rw-r--r--mingling_core/src/program/once_exec.rs194
-rw-r--r--mingling_core/src/program/repl_exec.rs126
-rw-r--r--mingling_core/tests/test-all/Cargo.lock82
-rw-r--r--mingling_core/tests/test-all/tests/integration.rs2
-rw-r--r--mingling_core/tests/test-basic/Cargo.lock142
-rw-r--r--mingling_core/tests/test-comp/Cargo.lock144
-rw-r--r--mingling_core/tests/test-comp/tests/integration.rs2
-rw-r--r--mingling_core/tests/test-dispatch-tree/Cargo.lock142
-rw-r--r--mingling_core/tests/test-repl/Cargo.lock142
-rw-r--r--mingling_core/tests/test-structural-renderer/Cargo.lock82
25 files changed, 1308 insertions, 524 deletions
diff --git a/mingling_core/Cargo.toml b/mingling_core/Cargo.toml
index 14140c6..833a857 100644
--- a/mingling_core/Cargo.toml
+++ b/mingling_core/Cargo.toml
@@ -14,7 +14,7 @@ categories = ["command-line-interface"]
nightly = []
default = []
async = []
-builds = []
+build = []
picker = []
dispatch_tree = []
@@ -49,3 +49,5 @@ toml = { workspace = true, optional = true }
# debug
log = { workspace = true, optional = true }
env_logger = { workspace = true, optional = true }
+
+might_be_async.workspace = true
diff --git a/mingling_core/src/any.rs b/mingling_core/src/any.rs
index 3e8fdf0..e922e2e 100644
--- a/mingling_core/src/any.rs
+++ b/mingling_core/src/any.rs
@@ -1,8 +1,8 @@
+use crate::ProgramCollect;
use crate::error::ChainProcessError;
-use crate::{Grouped, ProgramCollect};
-#[doc(hidden)]
-pub mod group;
+mod group;
+pub use group::*;
/// Any type output
///
diff --git a/mingling_core/src/asset.rs b/mingling_core/src/asset.rs
index 9b9a5d4..8c709ac 100644
--- a/mingling_core/src/asset.rs
+++ b/mingling_core/src/asset.rs
@@ -1,26 +1,10 @@
-#[doc(hidden)]
-pub mod chain;
-
-#[doc(hidden)]
-pub mod dispatcher;
-
-#[doc(hidden)]
-pub mod enum_tag;
-
-#[doc(hidden)]
-pub mod global_resource;
-
-#[doc(hidden)]
-pub mod help;
-
-#[doc(hidden)]
-pub mod lazy_resource;
-
-#[doc(hidden)]
-pub mod node;
-
-#[doc(hidden)]
-pub mod renderer;
-
-#[doc(hidden)]
-pub mod routable;
+pub(crate) mod chain;
+pub(crate) mod core_invokes;
+pub(crate) mod dispatcher;
+pub(crate) mod enum_tag;
+pub(crate) mod global_resource;
+pub(crate) mod help;
+pub(crate) mod lazy_resource;
+pub(crate) mod node;
+pub(crate) mod renderer;
+pub(crate) mod routable;
diff --git a/mingling_core/src/asset/chain.rs b/mingling_core/src/asset/chain.rs
index 423e218..bd504d0 100644
--- a/mingling_core/src/asset/chain.rs
+++ b/mingling_core/src/asset/chain.rs
@@ -12,6 +12,7 @@ pub trait Chain<G> {
#[cfg(feature = "async")]
fn proc(p: Self::Previous) -> impl Future<Output = ChainProcess<G>> + Send;
+ /// Process the previous value and return a future that resolves to a [`ChainProcess<G>`](./enum.ChainProcess.html)
#[cfg(not(feature = "async"))]
fn proc(p: Self::Previous) -> ChainProcess<G>;
}
diff --git a/mingling_core/src/asset/core_invokes.rs b/mingling_core/src/asset/core_invokes.rs
new file mode 100644
index 0000000..6a3da2d
--- /dev/null
+++ b/mingling_core/src/asset/core_invokes.rs
@@ -0,0 +1,271 @@
+use std::marker::PhantomData;
+
+use crate::{
+ AnyOutput, ChainProcess, Grouped, NextProcess, ProgramCollect, RenderResult, ResourceMarker,
+};
+
+/// Type used to invoke Renderers in Mingling
+///
+/// It is marked as `#[non_exhaustive]` and all internal fields are private.
+/// This type can only be implicitly created by the hidden external API
+/// `__resource_marker_default` of `ResourceMarker`.
+///
+/// ```rust,ignore
+/// // You can inject other renderers as types into the current function
+/// // |
+/// #[renderer(buffer)] // vvvvvvvvvvvvvvvvvvvv
+/// fn render_foo(_: ResultFoo, renderer: &RendererInvoker<Bar>) {
+/// let bar = Bar::default();
+/// r_append!(renderer.invoke(bar));
+/// }
+/// ```
+#[non_exhaustive]
+pub struct RendererInvoker<T> {
+ phantom: PhantomData<T>,
+ create_by_res_injection: bool,
+}
+
+impl<T> RendererInvoker<T>
+where
+ T: Send,
+{
+ /// Invoke the renderer with the given value.
+ ///
+ /// This function triggers the rendering pipeline for the provided value `T`.
+ /// It can only be executed when the `RendererInvoker` was created by the resource injection system
+ /// (i.e., via `__resource_marker_default`). If the invoker was created manually or cloned outside
+ /// the injection context, calling this method will panic.
+ ///
+ /// # Panics
+ ///
+ /// Panics if the `RendererInvoker` was not created by the resource injection system.
+ ///
+ /// # Hook
+ ///
+ /// It will not execute any program hooks, because this type is used for **bypassing** or **reusing**, not for flow control.
+ pub fn invoke<C>(&self, value: T) -> RenderResult
+ where
+ C: ProgramCollect<Enum = C> + 'static,
+ T: Grouped<C>,
+ {
+ if !self.create_by_res_injection {
+ panic!(
+ "The current RendererInvoker was not created by the resource injection system, so it cannot be executed!"
+ );
+ }
+ C::render(AnyOutput::new(value))
+ }
+}
+
+impl<T> ResourceMarker for RendererInvoker<T> {
+ fn __resource_marker_clone(&self) -> Self {
+ RendererInvoker {
+ phantom: PhantomData,
+ create_by_res_injection: self.create_by_res_injection,
+ }
+ }
+
+ fn __resource_marker_default() -> Self {
+ // Create RendererInvoker with `create_by_res_injection` marked as true
+ //
+ // Reason: RendererInvoker is designed to only be created through resource injection.
+ // When the resource injection does not find a corresponding value,
+ // this method will be used to generate a default value to pass in.
+ RendererInvoker {
+ phantom: PhantomData,
+ create_by_res_injection: true,
+ }
+ }
+
+ fn __resource_marker_modify<C>(f: impl FnOnce(&mut Self))
+ where
+ C: ProgramCollect<Enum = C> + 'static,
+ {
+ // DO NOTHING
+ //
+ // When ResourceMarker is asked to modify, it should not execute anything.
+ let _ = f;
+ }
+}
+
+/// Type used to invoke Chain in Mingling
+///
+/// It is marked as `#[non_exhaustive]` and all internal fields are private.
+/// This type can only be implicitly created by the hidden external API
+/// `__resource_marker_default` of `ResourceMarker`.
+///
+/// ```rust,ignore
+/// // You can inject other chain as types into the current function
+/// // |
+/// #[chain] // vvvvvvvvvvvvvvvvvvvvv
+/// fn handle_foo(_: EntryFoo, chain: &ChainInvoker<StateBar>) {
+/// let bar = Bar::default();
+/// let next = chain.invoke_once(bar);
+/// }
+/// ```
+#[non_exhaustive]
+pub struct ChainInvoker<T> {
+ phantom: PhantomData<T>,
+ create_by_res_injection: bool,
+}
+
+impl<T> ChainInvoker<T>
+where
+ T: Send,
+{
+ /// Execute one step of the chain with the given value, returning the next state.
+ ///
+ /// This function performs **only a single step** of chain execution — it invokes the
+ /// current handler for value `T` and returns the next [`ChainProcess`] state, without
+ /// automatically continuing the chain. The caller is responsible for proceeding through
+ /// subsequent steps based on the returned state.
+ ///
+ /// It can only be executed when the `ChainInvoker` was created by the resource injection system
+ /// (i.e., via `__resource_marker_default`). If the invoker was created manually or cloned outside
+ /// the injection context, calling this method will panic.
+ ///
+ /// # Special Behavior
+ ///
+ /// If no chain exists for this type, it will convert itself into a `ChainProcess` that routes to the chain and return it.
+ ///
+ /// # Panics
+ ///
+ /// Panics if the `ChainInvoker` was not created by the resource injection system.
+ ///
+ /// # Hooks
+ ///
+ /// It will not execute any program hooks, because this type is used for **bypassing** or **reusing**, not for flow control.
+ #[might_be_async::func]
+ pub fn invoke_once<C>(&self, value: T) -> ChainProcess<C>
+ where
+ C: ProgramCollect<Enum = C> + 'static,
+ T: Grouped<C>,
+ {
+ self.pre_check();
+
+ let any = AnyOutput::new(value);
+
+ if C::has_chain(&any) {
+ might_be_async::invoke!(C::do_chain(any))
+ } else {
+ ChainProcess::Ok((any, NextProcess::Chain))
+ }
+ }
+
+ /// Continuously execute the chain until it is routed to a renderer or can no longer continue
+ ///
+ /// This function can only be called when the `ChainInvoker` was created by the resource injection system
+ /// (i.e., via `__resource_marker_default`). If the invoker was created manually or cloned outside
+ /// the injection context, calling this method will panic.
+ ///
+ /// # Panics
+ ///
+ /// Panics if the `ChainInvoker` was not created by the resource injection system.
+ ///
+ /// # Hooks
+ ///
+ /// It will not execute any program hooks, because this type is used for **bypassing** or **reusing**, not for flow control.
+ #[might_be_async::func]
+ pub fn invoke_to_last<C>(&self, value: T) -> ChainProcess<C>
+ where
+ C: ProgramCollect<Enum = C> + 'static,
+ T: Grouped<C>,
+ {
+ self.pre_check();
+
+ let mut current = might_be_async::invoke!(C::do_chain(AnyOutput::new(value)));
+
+ loop {
+ match current {
+ ChainProcess::Ok((any, NextProcess::Chain)) => {
+ if C::has_chain(&any) {
+ current = might_be_async::invoke!(C::do_chain(any));
+ } else {
+ // If the next step of this type does not have a Chain, reconstruct it back
+ return ChainProcess::Ok((any, NextProcess::Chain));
+ }
+ }
+ _ => return current,
+ }
+ }
+ }
+
+ /// Continuously execute the chain until it is rendered into a RenderResult
+ ///
+ /// This function can only be called when the `ChainInvoker` was created by the resource injection system
+ /// (i.e., via `__resource_marker_default`). If the invoker was created manually or cloned outside
+ /// the injection context, calling this method will panic.
+ ///
+ /// # Special Behavior
+ ///
+ /// If an error occurs during rendering, or the result type does not contain a renderer, it will be rendered as an empty RenderResult
+ ///
+ /// # Panics
+ ///
+ /// Panics if the `ChainInvoker` was not created by the resource injection system.
+ ///
+ /// # Hooks
+ ///
+ /// It will not execute any program hooks, because this type is used for **bypassing** or **reusing**, not for flow control.
+ #[might_be_async::func]
+ pub fn invoke_to_result<C>(&self, value: T) -> RenderResult
+ where
+ C: ProgramCollect<Enum = C> + 'static,
+ T: Grouped<C>,
+ {
+ self.pre_check();
+
+ let last = might_be_async::invoke!(self.invoke_to_last(value));
+
+ match last {
+ ChainProcess::Err(_) => RenderResult::new(),
+ ChainProcess::Ok((any, _)) => {
+ if C::has_renderer(&any) {
+ C::render(any)
+ } else {
+ RenderResult::new()
+ }
+ }
+ }
+ }
+
+ #[inline(always)]
+ fn pre_check(&self) {
+ if !self.create_by_res_injection {
+ panic!(
+ "The current ChainInvoker was not created by the resource injection system, so it cannot be executed!"
+ );
+ }
+ }
+}
+
+impl<T> ResourceMarker for ChainInvoker<T> {
+ fn __resource_marker_clone(&self) -> Self {
+ ChainInvoker {
+ phantom: PhantomData,
+ create_by_res_injection: self.create_by_res_injection,
+ }
+ }
+
+ fn __resource_marker_default() -> Self {
+ // Create ChainInvoker with `create_by_res_injection` marked as true
+ //
+ // Reason: ChainInvoker is designed to only be created through resource injection.
+ // When the resource injection does not find a corresponding value,
+ // this method will be used to generate a default value to pass in.
+ ChainInvoker {
+ phantom: PhantomData,
+ create_by_res_injection: true,
+ }
+ }
+
+ fn __resource_marker_modify<C>(f: impl FnOnce(&mut Self))
+ where
+ C: ProgramCollect<Enum = C> + 'static,
+ {
+ // DO NOTHING
+ //
+ // When ResourceMarker is asked to modify, it should not execute anything.
+ let _ = f;
+ }
+}
diff --git a/mingling_core/src/asset/global_resource.rs b/mingling_core/src/asset/global_resource.rs
index a610378..18e4446 100644
--- a/mingling_core/src/asset/global_resource.rs
+++ b/mingling_core/src/asset/global_resource.rs
@@ -38,7 +38,7 @@ where
{
let mut new_res = match Arc::try_unwrap(std::mem::take(arc_res)) {
Ok(val) => val,
- Err(arc) => (*arc).res_clone(),
+ Err(arc) => (*arc).__resource_marker_clone(),
};
let r = f(&mut new_res);
*arc_res = Arc::new(new_res);
@@ -57,7 +57,7 @@ where
Res: 'static + Default + ResourceMarker + Send + Sync,
{
let Ok(mut guard) = self.resources.lock() else {
- let mut default_res = Res::res_default();
+ let mut default_res = Res::__resource_marker_default();
return f(&mut default_res);
};
if let Some(arc_res) = guard
@@ -66,13 +66,13 @@ where
{
let mut new_res = match Arc::try_unwrap(std::mem::take(arc_res)) {
Ok(val) => val,
- Err(arc) => (*arc).res_clone(),
+ Err(arc) => (*arc).__resource_marker_clone(),
};
let r = f(&mut new_res);
*arc_res = Arc::new(new_res);
r
} else {
- let mut default_res = Res::res_default();
+ let mut default_res = Res::__resource_marker_default();
f(&mut default_res)
}
}
@@ -85,7 +85,7 @@ where
#[must_use]
pub fn __extract_res_mut<Res: 'static + Default + ResourceMarker + Send + Sync>(&self) -> Res {
let Ok(mut guard) = self.resources.lock() else {
- return Res::res_default();
+ return Res::__resource_marker_default();
};
if let Some(arc_res) = guard
.get_mut(&TypeId::of::<Res>())
@@ -93,10 +93,10 @@ where
{
match Arc::try_unwrap(std::mem::take(arc_res)) {
Ok(val) => val,
- Err(arc) => (*arc).res_clone(),
+ Err(arc) => (*arc).__resource_marker_clone(),
}
} else {
- Res::res_default()
+ Res::__resource_marker_default()
}
}
@@ -136,7 +136,7 @@ where
&self,
) -> GlobalResource<Res> {
self.res()
- .unwrap_or_else(|| GlobalResource::from(Arc::new(Res::res_default())))
+ .unwrap_or_else(|| GlobalResource::from(Arc::new(Res::__resource_marker_default())))
}
}
@@ -176,24 +176,38 @@ impl<ResType: 'static + Send + Sync> AsRef<ResType> for GlobalResource<ResType>
/// Resource marker trait, types that implement the Clone and Default traits can be considered as resources
pub trait ResourceMarker {
+ /// Clone the resource. This is an internal method used by the resource injection system
+ /// and should not be called directly by user code.
#[must_use]
- fn res_clone(&self) -> Self;
- fn res_default() -> Self;
- fn modify<C>(f: impl FnOnce(&mut Self))
+ #[doc(hidden)]
+ fn __resource_marker_clone(&self) -> Self;
+
+ /// Create a default instance of the resource. This is an internal method used by the
+ /// resource injection system and should not be called directly by user code.
+ #[doc(hidden)]
+ fn __resource_marker_default() -> Self;
+
+ /// Modify the resource using a closure. This is an internal method used by the resource
+ /// injection system and should not be called directly by user code.
+ #[doc(hidden)]
+ fn __resource_marker_modify<C>(f: impl FnOnce(&mut Self))
where
C: ProgramCollect<Enum = C> + 'static;
}
-impl<T: Default + Clone + Send + Sync + 'static> ResourceMarker for T {
- fn res_clone(&self) -> Self {
+impl<T> ResourceMarker for T
+where
+ T: Default + Clone + Send + Sync + 'static,
+{
+ fn __resource_marker_clone(&self) -> Self {
Clone::clone(self)
}
- fn res_default() -> Self {
+ fn __resource_marker_default() -> Self {
Default::default()
}
- fn modify<C>(f: impl FnOnce(&mut Self))
+ fn __resource_marker_modify<C>(f: impl FnOnce(&mut Self))
where
C: ProgramCollect<Enum = C> + 'static,
{
@@ -227,38 +241,41 @@ mod tests {
#[test]
fn resource_marker_i32_res_clone() {
let val = 42i32;
- let cloned = val.res_clone();
+ let cloned = val.__resource_marker_clone();
assert_eq!(cloned, 42);
}
#[test]
fn resource_marker_i32_res_default() {
- assert_eq!(<i32 as ResourceMarker>::res_default(), 0i32);
+ assert_eq!(<i32 as ResourceMarker>::__resource_marker_default(), 0i32);
}
#[test]
fn resource_marker_string_res_clone() {
let val = "hello".to_string();
- let cloned = val.res_clone();
+ let cloned = val.__resource_marker_clone();
assert_eq!(cloned, "hello");
}
#[test]
fn resource_marker_string_res_default() {
- assert_eq!(<String as ResourceMarker>::res_default(), "");
+ assert_eq!(<String as ResourceMarker>::__resource_marker_default(), "");
}
#[test]
fn resource_marker_vec_res_clone() {
let val = vec![1, 2, 3];
- let cloned = val.res_clone();
+ let cloned = val.__resource_marker_clone();
assert_eq!(cloned, vec![1, 2, 3]);
}
#[test]
fn resource_marker_vec_res_default() {
let empty: Vec<i32> = vec![];
- assert_eq!(<Vec<i32> as ResourceMarker>::res_default(), empty);
+ assert_eq!(
+ <Vec<i32> as ResourceMarker>::__resource_marker_default(),
+ empty
+ );
}
// Note: Tests for Program::with_resource, res(), res_or_route(), res_or_default(),
diff --git a/mingling_core/src/asset/lazy_resource.rs b/mingling_core/src/asset/lazy_resource.rs
index 918aeb2..3cb7563 100644
--- a/mingling_core/src/asset/lazy_resource.rs
+++ b/mingling_core/src/asset/lazy_resource.rs
@@ -280,7 +280,7 @@ where
{
/// Clones the lazy resource. The cloned resource retains any initialized value,
/// but the initializer is reset to `T::default()`.
- fn res_clone(&self) -> Self {
+ fn __resource_marker_clone(&self) -> Self {
match &self.inner {
LazyInner::Init(t, _) => Self {
inner: LazyInner::Init(t.clone(), None),
@@ -290,7 +290,7 @@ where
}
/// Returns a default lazy resource (uninitialized, using `T::default()` as the initializer).
- fn res_default() -> Self
+ fn __resource_marker_default() -> Self
where
T: Default,
{
@@ -298,7 +298,7 @@ where
}
/// Modifies the current lazy resource via the `this` context provided by `C`.
- fn modify<C>(f: impl FnOnce(&mut Self))
+ fn __resource_marker_modify<C>(f: impl FnOnce(&mut Self))
where
C: ProgramCollect<Enum = C> + 'static,
{
@@ -583,7 +583,7 @@ mod tests {
fn res_clone_of_initialized_clones_value() {
let mut r = LazyRes::new(|| vec![1, 2, 3]);
r.get_ref();
- let cloned = r.res_clone();
+ let cloned = r.__resource_marker_clone();
assert!(cloned.is_initialized());
assert_eq!(cloned.into_inner(), Some(vec![1, 2, 3]));
}
@@ -591,14 +591,14 @@ mod tests {
#[test]
fn res_clone_of_uninitialized_creates_default() {
let r: LazyRes<Vec<i32>> = LazyRes::new(|| vec![1, 2, 3]);
- let cloned = r.res_clone();
+ let cloned = r.__resource_marker_clone();
// The source is uninitialized, so res_clone returns a default lazy
assert!(!cloned.is_initialized());
}
#[test]
fn res_default_returns_uninitialized() {
- let r: LazyRes<i32> = LazyRes::<i32>::res_default();
+ let r: LazyRes<i32> = LazyRes::<i32>::__resource_marker_default();
assert!(!r.is_initialized());
}
diff --git a/mingling_core/src/build.rs b/mingling_core/src/build.rs
new file mode 100644
index 0000000..7918f3a
--- /dev/null
+++ b/mingling_core/src/build.rs
@@ -0,0 +1,13 @@
+#[doc(hidden)]
+#[cfg(feature = "comp")]
+mod comp;
+
+#[cfg(feature = "comp")]
+pub use comp::*;
+
+#[doc(hidden)]
+#[cfg(feature = "pathf")]
+mod pathf;
+
+#[cfg(feature = "pathf")]
+pub use pathf::*;
diff --git a/mingling_core/src/builds/comp.rs b/mingling_core/src/build/comp.rs
index 2abb1e1..2abb1e1 100644
--- a/mingling_core/src/builds/comp.rs
+++ b/mingling_core/src/build/comp.rs
diff --git a/mingling_core/src/builds/pathf.rs b/mingling_core/src/build/pathf.rs
index d8d4698..d8d4698 100644
--- a/mingling_core/src/builds/pathf.rs
+++ b/mingling_core/src/build/pathf.rs
diff --git a/mingling_core/src/builds.rs b/mingling_core/src/builds.rs
deleted file mode 100644
index 3c52907..0000000
--- a/mingling_core/src/builds.rs
+++ /dev/null
@@ -1,7 +0,0 @@
-#[doc(hidden)]
-#[cfg(feature = "comp")]
-pub mod comp;
-
-#[doc(hidden)]
-#[cfg(feature = "pathf")]
-pub mod pathf;
diff --git a/mingling_core/src/comp.rs b/mingling_core/src/comp.rs
index 55e9952..d8dcfbd 100644
--- a/mingling_core/src/comp.rs
+++ b/mingling_core/src/comp.rs
@@ -34,7 +34,17 @@ use crate::exec::match_user_input;
/// Types implementing this trait can provide custom completion suggestions
/// based on the current shell context.
pub trait Completion {
+ /// The entry point type that the completion functionality will act on.
+ ///
+ /// It marks the **previous** type, which typically represents an `EntryXXX` type
+ /// (unless you have specific requirements).
type Previous;
+
+ /// Generates completion suggestions based on the current shell context.
+ ///
+ /// This method is called when the completion system needs to provide
+ /// custom suggestions for the current command or argument. Implementations
+ /// should use the provided [`ShellContext`] to determine what to suggest.
fn comp(ctx: &ShellContext) -> Suggest;
}
@@ -44,6 +54,18 @@ pub trait Completion {
/// automatically implement this trait for `Entry` types to extract the
/// arguments from user input for completion suggestions.
pub trait CompletionEntry {
+ /// Extracts the user input arguments for completion processing.
+ ///
+ /// This method is called when the completion system needs to retrieve
+ /// the raw input arguments from the user's command line. The returned
+ /// vector of strings represents the parsed arguments that will be used
+ /// to match against the program's command tree and generate completion
+ /// suggestions.
+ ///
+ /// # Returns
+ ///
+ /// A vector of strings containing the individual arguments from the
+ /// user's command-line input.
fn get_input(self) -> Vec<String>;
}
@@ -54,6 +76,27 @@ pub trait CompletionEntry {
/// format appropriate for the target shell.
pub struct CompletionHelper;
impl CompletionHelper {
+ /// Executes the completion logic for the given program type (`P`).
+ ///
+ /// This is the **entry point** of the Mingling Completion system. It converts
+ /// the user's shell context (current command line, cursor position, previous
+ /// words, etc.) into actual completion suggestions.
+ ///
+ /// The function first attempts to match the input arguments against the
+ /// program's command tree. If a matching dispatcher is found, it delegates to
+ /// the program's custom completion logic (`P::do_comp`). If no match is found
+ /// or the dispatcher signals "not found", a default completion is used instead,
+ /// which provides subcommand suggestions based on the input path.
+ ///
+ /// # Type Parameters
+ ///
+ /// * `P` — The top-level program type that implements [`ProgramCollect`], can be
+ /// displayed, compared for equality, and kept alive for the program's lifetime.
+ ///
+ /// # Returns
+ ///
+ /// A [`Suggest`] value containing either file completion instructions or a set
+ /// of candidate suggestions.
#[must_use]
pub fn exec_completion<P>(ctx: &ShellContext) -> Suggest
where
@@ -126,7 +169,17 @@ impl CompletionHelper {
}
}
- #[allow(clippy::needless_pass_by_value)]
+ /// Renders the completion suggestions to standard output.
+ ///
+ /// This method takes the [`Suggest`] value produced by
+ /// [`exec_completion`], and prints the results in a format appropriate for the
+ /// user's shell environment.
+ ///
+ /// - If the suggestion is [`Suggest::FileCompletion`], it prints `"_file_"` and
+ /// exits, instructing the shell to fall back to file completion.
+ /// - If the suggestion is [`Suggest::Suggest`] with a set of candidates, it
+ /// formats and prints them according to the shell type (Zsh/PowerShell, Fish,
+ /// or default).
pub fn render_suggest<P>(ctx: ShellContext, suggest: Suggest)
where
P: ProgramCollect<Enum = P> + Display + 'static,
diff --git a/mingling_core/src/lib.rs b/mingling_core/src/lib.rs
index 31476c9..2f63cf6 100644
--- a/mingling_core/src/lib.rs
+++ b/mingling_core/src/lib.rs
@@ -1,3 +1,4 @@
+#![deny(missing_docs)]
//! Mingling Core
//!
//! # Intro
@@ -8,7 +9,7 @@
//!
//! Recommended to import [mingling](https://crates.io/crates/mingling) to use its features.
-#![deny(missing_docs)]
+// Private Modules
mod any;
mod asset;
@@ -16,21 +17,67 @@ mod program;
mod renderer;
mod tester;
+/// Module for setting up a `Mingling` program.
+///
+/// This module provides the [`ProgramSetup`] type, which allows users to configure
+/// and initialize the program's execution environment.
+pub mod setup {
+ pub use crate::program::setup::ProgramSetup;
+}
+
+/// This module provides result types for Mingling components.
+///
+/// These are re-exported at the top level via `mingling::res`.
+#[doc(hidden)]
+pub mod core_res {
+ #[cfg(feature = "repl")]
+ pub use crate::program::repl_exec::res::*;
+}
+
+/// Provides the runtime logic for Mingling's dynamic completion system.
+///
+/// This module contains the core functionality for the "comp" (completion) feature,
+/// which enables dynamic tab-completion and input suggestion capabilities within
+/// Mingling applications.
+#[cfg(feature = "comp")]
+pub(crate) mod comp;
+
+/// Provides Mingling's build script module, used in `build.rs` to provide build-time behavior for certain features.
+///
+/// To use it, add the following to your `Cargo.toml` under `[build-dependencies]`, and enable the features
+/// that require build-time behavior from the crate:
+///
+/// ```toml
+/// [build-dependencies.mingling]
+/// version = "0.3.0"
+/// features = [
+/// "build", // Enable it
+/// "comp", // If you need completion-related build-time behavior, enable this as well
+/// ]
+/// ```
+#[cfg(feature = "build")]
+#[doc(hidden)]
+pub mod build;
+
+// Public Modules
+
/// Provides a toolkit for `Mingling` testing capabilities.
pub mod test {
pub use crate::tester::*;
}
-#[cfg(feature = "structural_renderer")]
-pub use crate::renderer::structural::StructuralRenderer;
+/// Provided for framework developers
+pub mod debug;
// NOT re-exported at top level: the `StructuralData` trait is sealed and only
// accessible through the derive macro. Users who need the trait can access it
// via `mingling::renderer::structural::StructuralData` (through the inner alias).
-pub use crate::any::group::*;
-pub use crate::any::*;
+#[cfg(feature = "structural_renderer")]
+pub use crate::renderer::structural::StructuralRenderer;
+pub use crate::any::*;
pub use crate::asset::chain::*;
+pub use crate::asset::core_invokes::*;
pub use crate::asset::dispatcher::*;
pub use crate::asset::enum_tag::*;
pub use crate::asset::global_resource::*;
@@ -39,74 +86,32 @@ pub use crate::asset::lazy_resource::*;
pub use crate::asset::node::*;
pub use crate::asset::renderer::*;
pub use crate::asset::routable::*;
+#[cfg(feature = "comp")]
+pub use crate::comp::*;
+pub use crate::program::*;
+pub use crate::renderer::render_result::*;
/// All error types of `Mingling`
pub mod error {
pub use crate::asset::chain::error::*;
pub use crate::exec::error::*;
pub use crate::program::error::*;
+
#[cfg(feature = "structural_renderer")]
pub use crate::renderer::structural::error::*;
- #[cfg(feature = "pathf")]
- pub use mingling_pathf::error::*;
-}
-
-pub use crate::program::*;
-
-pub use crate::renderer::render_result::*;
-
-#[cfg(feature = "builds")]
-#[doc(hidden)]
-pub mod builds;
-
-/// Provides build scripts for users
-#[cfg(feature = "builds")]
-pub mod build {
- #[cfg(feature = "comp")]
- pub use crate::builds::comp::*;
#[cfg(feature = "pathf")]
- pub use crate::builds::pathf::*;
+ pub use mingling_pathf::error::*;
}
-/// Provided for framework developers
-pub mod debug;
-
-#[cfg(feature = "comp")]
#[doc(hidden)]
-pub mod comp;
+mod private;
-#[cfg(feature = "comp")]
-pub use crate::comp::*;
-
-/// Module for setting up a `Mingling` program.
+/// Internal API provided by Mingling Core
///
-/// This module provides the [`ProgramSetup`] type, which allows users to configure
-/// and initialize the program's execution environment.
-pub mod setup {
- pub use crate::program::setup::ProgramSetup;
-}
-
-/// Private API — not intended for direct use.
+/// These are used by macros and are not exposed to users, but are still accessible externally.
#[doc(hidden)]
+#[allow(unused_imports)]
pub mod __private {
- use crate::ProgramCollect;
-
- /// Sealed trait for `StructuralData` — only implementable via derive macro.
- pub trait StructuralDataSealed<C>
- where
- C: ProgramCollect<Enum = C>,
- {
- }
-
- /// Re-export so the derive macro can reference the trait without
- /// conflicting with the derive macro name at `::mingling::StructuralData`.
- #[cfg(feature = "structural_renderer")]
- pub use crate::renderer::structural::structural_data::StructuralData;
-}
-
-#[doc(hidden)]
-pub mod core_res {
- #[cfg(feature = "repl")]
- pub use crate::program::repl_exec::res::ResREPL;
+ pub use crate::private::*;
}
diff --git a/mingling_core/src/private.rs b/mingling_core/src/private.rs
new file mode 100644
index 0000000..371ada2
--- /dev/null
+++ b/mingling_core/src/private.rs
@@ -0,0 +1,12 @@
+/// Sealed trait for `StructuralData` — only implementable via derive macro.
+#[cfg(feature = "structural_renderer")]
+pub trait StructuralDataSealed<C>
+where
+ C: crate::ProgramCollect<Enum = C>,
+{
+}
+
+/// Re-export so the derive macro can reference the trait without
+/// conflicting with the derive macro name at `::mingling::StructuralData`.
+#[cfg(feature = "structural_renderer")]
+pub use crate::renderer::structural::structural_data::StructuralData;
diff --git a/mingling_core/src/program/exec.rs b/mingling_core/src/program/exec.rs
index f5bdc2b..f0322a5 100644
--- a/mingling_core/src/program/exec.rs
+++ b/mingling_core/src/program/exec.rs
@@ -8,184 +8,15 @@ use crate::{
#[doc(hidden)]
pub mod error;
-#[cfg(feature = "async")]
-pub async fn exec<C>(
- program: &'static Program<C>,
-) -> Result<RenderResult, ProgramInternalExecuteError>
-where
- C: ProgramCollect<Enum = C>,
-{
- exec_with_args(program, &program.args).await
-}
-
-#[cfg(not(feature = "async"))]
+#[might_be_async::func]
pub fn exec<C>(program: &'static Program<C>) -> Result<RenderResult, ProgramInternalExecuteError>
where
C: ProgramCollect<Enum = C>,
{
- exec_with_args(program, &program.args)
-}
-
-#[cfg(feature = "async")]
-pub async fn exec_with_args<C>(
- program: &'static Program<C>,
- args: &[String],
-) -> Result<RenderResult, ProgramInternalExecuteError>
-where
- C: ProgramCollect<Enum = C>,
-{
- // Exit code
- let mut exit_code: i32 = 0;
-
- macro_rules! control {
- ($hook_call:expr, $current:expr) => {
- let __ccc = $hook_call;
- if let Some(r) =
- handle_program_control(program, __ccc, Some(&mut $current), &mut exit_code)
- {
- return Ok(r);
- }
- };
- ($hook_call:expr) => {
- let __ccc = $hook_call;
- if let Some(r) = handle_program_control(program, __ccc, None, &mut exit_code) {
- return Ok(r);
- }
- };
- }
-
- // Current
- let mut current = C::build_dispatcher_not_found(vec![]);
-
- // Run hooks
- control!(
- program.run_hook_pre_dispatch(crate::hook::HookPreDispatchInfo { arguments: args }),
- current
- );
-
- // Dispatch args - either via dynamic dispatch or trie dispatch based on feature flag
- let mut current = if cfg!(not(feature = "dispatch_tree")) {
- dispatch_args_dynamic(program, args)?
- } else {
- C::dispatch_args_trie(args)?
- };
-
- // Run hook
- control!(
- program.run_hook_post_dispatch(crate::hook::HookPostDispatchInfo {
- entry: &current.member_id,
- }),
- current
- );
-
- let mut stop_next = false;
-
- // If the program has Help enabled, skip actual logic and jump to Help
- if program.user_context.help {
- let mut render_result = render_help::<C>(program, current);
-
- // Run hook
- control!(program.run_hook_finish(crate::hook::HookFinishInfo {}));
- render_result.exit_code = exit_code;
-
- return Ok(render_result);
- }
-
- loop {
- let final_exec = stop_next;
-
- current = {
- // If a chain exists, execute as a chain
- if C::has_chain(&current) {
- // Run hook
- control!(
- program.run_hook_pre_chain(crate::hook::HookPreChainInfo {
- input: &current.member_id,
- raw: current.inner.as_ref(),
- }),
- current
- );
-
- match C::do_chain(current).await {
- ChainProcess::Ok((any, NextProcess::Renderer)) => {
- {
- let mut render_result = render::<C>(program, any);
-
- // Run hook
- control!(program.run_hook_finish(crate::hook::HookFinishInfo {}));
- render_result.exit_code = exit_code;
-
- return Ok(render_result);
- };
- }
- ChainProcess::Ok((mut any, NextProcess::Chain)) => {
- // Run hook
- control!(
- program.run_hook_post_chain(crate::hook::HookPostChainInfo {
- output: &any
- }),
- any
- );
- any
- }
- ChainProcess::Err(e) => {
- // Run hook
- control!(
- program.run_hook_finish(crate::hook::HookFinishInfo {}),
- &mut C::build_empty_result()
- );
- return Err(e.into());
- }
- }
- }
- // If no chain exists, attempt to render
- else if C::has_renderer(&current) {
- // Run hook
- control!(
- program.run_hook_pre_render(crate::hook::HookPreRenderInfo {
- input: &current.member_id,
- raw: current.inner.as_ref(),
- }),
- current
- );
-
- let mut render_result = render::<C>(program, current);
-
- // Run hooks
- control!(
- program.run_hook_post_render(crate::hook::HookPostRenderInfo {
- result: &render_result,
- })
- );
-
- control!(program.run_hook_finish(crate::hook::HookFinishInfo {}));
-
- render_result.exit_code = exit_code;
- return Ok(render_result);
- }
- // No renderer exists
- else {
- stop_next = true;
- C::build_renderer_not_found(current.member_id)
- }
- };
-
- if final_exec && stop_next {
- break;
- }
- }
- let mut render_result = RenderResult::default();
-
- // Run hook
- control!(
- program.run_hook_finish(crate::hook::HookFinishInfo {}),
- current
- );
- render_result.exit_code = exit_code;
- Ok(render_result)
+ might_be_async::invoke!(exec_with_args(program, &program.args))
}
-#[cfg(not(feature = "async"))]
+#[might_be_async::func]
pub fn exec_with_args<C>(
program: &'static Program<C>,
args: &[String],
@@ -265,7 +96,7 @@ where
current
);
- match C::do_chain(current) {
+ match might_be_async::invoke!(C::do_chain(current)) {
ChainProcess::Ok((any, NextProcess::Renderer)) => {
{
let mut render_result = render::<C>(program, any);
diff --git a/mingling_core/src/program/once_exec.rs b/mingling_core/src/program/once_exec.rs
index a846d04..96723fd 100644
--- a/mingling_core/src/program/once_exec.rs
+++ b/mingling_core/src/program/once_exec.rs
@@ -1,28 +1,10 @@
use crate::THIS_PROGRAM;
use crate::{Program, ProgramCollect, RenderResult, error::ProgramExecuteError};
-// Async program
-#[cfg(feature = "async")]
impl<C> Program<C>
where
C: ProgramCollect<Enum = C>,
{
- pub(crate) async fn exec_wrapper<F, Fut>(self, f: F) -> Fut::Output
- where
- C: 'static + Send + Sync,
- F: FnOnce(&'static Program<C>) -> Fut + Send + Sync,
- Fut: Future + Send,
- {
- THIS_PROGRAM.set(Box::new(self));
- let program = THIS_PROGRAM
- .get_raw()
- .unwrap()
- .downcast_ref::<Program<C>>()
- .unwrap();
-
- f(program).await
- }
-
/// Run the command line program
///
/// # Errors
@@ -33,7 +15,8 @@ where
/// # Panics
///
/// Panics if the program encounters a non-recoverable internal error.
- pub async fn exec_without_render(mut self) -> Result<RenderResult, ProgramExecuteError>
+ #[might_be_async::func]
+ pub fn exec_without_render(mut self) -> Result<RenderResult, ProgramExecuteError>
where
C: 'static + Send + Sync,
{
@@ -42,21 +25,56 @@ where
self.args = self.args.iter().skip(1).cloned().collect();
- return self
- .exec_wrapper(|p| async { crate::exec::exec(p).await.map_err(|e| e.into()) })
- .await;
+ #[cfg(not(feature = "async"))]
+ {
+ #[cfg(panic = "abort")]
+ return self.exec_wrapper(|p| crate::exec::exec(p).map_err(|e| e.into()));
+
+ #[cfg(not(panic = "abort"))]
+ match std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
+ self.exec_wrapper(|p| crate::exec::exec(p).map_err(std::convert::Into::into))
+ })) {
+ Ok(result) => result,
+ Err(panic_info) => {
+ let panic_payload = crate::error::ProgramPanic {
+ payload: panic_info,
+ };
+
+ let program = THIS_PROGRAM
+ .get_raw()
+ .unwrap()
+ .downcast_ref::<Program<C>>()
+ .unwrap();
+
+ #[cfg(not(feature = "async"))]
+ program.run_hook_exec_panic(crate::hook::HookPanicInfo {
+ panic: &panic_payload,
+ });
+
+ Err(ProgramExecuteError::Panic(panic_payload))
+ }
+ }
+ }
+
+ #[cfg(feature = "async")]
+ {
+ return self
+ .exec_wrapper(|p| async { crate::exec::exec(p).await.map_err(|e| e.into()) })
+ .await;
+ }
}
/// Run the command line program
#[must_use]
- pub async fn exec(self) -> i32
+ #[might_be_async::func]
+ pub fn exec(self) -> i32
where
C: 'static + Send + Sync,
{
use crate::error::ProgramExecuteError;
let stdout_setting = self.stdout_setting.clone();
- let result = match self.exec_without_render().await {
+ let result = match might_be_async::invoke!(self.exec_without_render()) {
Ok(r) => r,
Err(e) => match e {
ProgramExecuteError::DispatcherNotFound => {
@@ -88,11 +106,12 @@ where
}
/// Run the command line program, then exit
- pub async fn exec_and_exit(self)
+ #[might_be_async::func]
+ pub fn exec_and_exit(self)
where
C: 'static + Send + Sync,
{
- let exit_code = self.exec().await;
+ let exit_code = might_be_async::invoke!(self.exec());
// SAFETY: exec() is synchronous — it returns only after all
// chain handlers and renderers have finished. No code still
// holds references from get_raw() at this point.
@@ -101,6 +120,29 @@ where
}
}
+// Async program
+#[cfg(feature = "async")]
+impl<C> Program<C>
+where
+ C: ProgramCollect<Enum = C>,
+{
+ pub(crate) async fn exec_wrapper<F, Fut>(self, f: F) -> Fut::Output
+ where
+ C: 'static + Send + Sync,
+ F: FnOnce(&'static Program<C>) -> Fut + Send + Sync,
+ Fut: Future + Send,
+ {
+ THIS_PROGRAM.set(Box::new(self));
+ let program = THIS_PROGRAM
+ .get_raw()
+ .unwrap()
+ .downcast_ref::<Program<C>>()
+ .unwrap();
+
+ f(program).await
+ }
+}
+
// Sync program
#[cfg(not(feature = "async"))]
impl<C> Program<C>
@@ -126,104 +168,4 @@ where
f(program)
}
-
- /// Run the command line program
- ///
- /// # Errors
- ///
- /// Returns `Err(ProgramExecuteError)` if execution fails,
- /// e.g., if no dispatcher is found or a chain error occurs.
- ///
- /// # Panics
- ///
- /// Panics if the program encounters a non-recoverable internal error.
- pub fn exec_without_render(mut self) -> Result<RenderResult, ProgramExecuteError>
- where
- C: 'static + Send + Sync,
- {
- // Run hooks
- self.run_hook_on_begin(crate::hook::HookBeginInfo {});
-
- self.args = self.args.iter().skip(1).cloned().collect();
-
- #[cfg(panic = "abort")]
- return self.exec_wrapper(|p| crate::exec::exec(p).map_err(|e| e.into()));
-
- #[cfg(not(panic = "abort"))]
- match std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
- self.exec_wrapper(|p| crate::exec::exec(p).map_err(std::convert::Into::into))
- })) {
- Ok(result) => result,
- Err(panic_info) => {
- let panic_payload = crate::error::ProgramPanic {
- payload: panic_info,
- };
-
- let program = THIS_PROGRAM
- .get_raw()
- .unwrap()
- .downcast_ref::<Program<C>>()
- .unwrap();
-
- program.run_hook_exec_panic(crate::hook::HookPanicInfo {
- panic: &panic_payload,
- });
-
- Err(ProgramExecuteError::Panic(panic_payload))
- }
- }
- }
-
- /// Run the command line program
- #[must_use]
- pub fn exec(self) -> i32
- where
- C: 'static + Send + Sync,
- {
- use crate::error::ProgramExecuteError;
-
- let stdout_setting = self.stdout_setting.clone();
- let result = match self.exec_without_render() {
- Ok(r) => r,
- Err(e) => match e {
- ProgramExecuteError::DispatcherNotFound => {
- eprintln!("Dispatcher not found");
- return 1;
- }
- ProgramExecuteError::RendererNotFound(renderer_name) => {
- eprintln!("Renderer `{renderer_name}` not found");
- return 1;
- }
- ProgramExecuteError::Other(e) => {
- eprintln!("{e}");
- return 1;
- }
- ProgramExecuteError::Panic(unwinded_error) => {
- eprintln!("{unwinded_error}");
- return 1;
- }
- },
- };
-
- // Read exit code
- // Render result
- if stdout_setting.render_output {
- result.std_print();
- }
-
- result.exit_code
- }
-
- /// Run the command line program, then exit
- pub fn exec_and_exit(self)
- where
- C: 'static + Send + Sync,
- {
- let exit_code = self.exec();
- // SAFETY: exec() is synchronous — it returns only after all
- // chain handlers and renderers have finished. No code still
- // holds references from get_raw() at this point.
- drop(unsafe { THIS_PROGRAM.take() });
- std::process::exit(exit_code)
- }
}
diff --git a/mingling_core/src/program/repl_exec.rs b/mingling_core/src/program/repl_exec.rs
index cbda9da..f84b291 100644
--- a/mingling_core/src/program/repl_exec.rs
+++ b/mingling_core/src/program/repl_exec.rs
@@ -13,7 +13,6 @@ use crate::program::repl_exec::splitter::split_input_string;
use crate::{Program, ProgramCollect, RenderResult};
use crate::{program::repl_exec::res::ResREPL, this};
-#[cfg(not(feature = "async"))]
impl<C> Program<C>
where
C: ProgramCollect<Enum = C> + Send + Sync + 'static,
@@ -22,106 +21,63 @@ where
///
/// This method starts an infinite loop that continuously reads user input, parses commands, executes them,
/// and displays the execution result or error message. It is suitable for scenarios requiring command-line interaction with the user.
+ ///
+ /// **Note:** When the `async` feature is enabled, panic unwinding is not supported.
+ /// Any panics during command execution will result in an abort rather than being caught and handled gracefully.
+ #[might_be_async::func]
pub fn exec_repl(mut self) {
// Inject default REPL resource
self.with_resource(ResREPL::default());
self.run_hook_repl_on_begin(crate::hook::HookREPLBeginInfo {});
- self.exec_wrapper(|p| -> () {
- loop {
- p.run_hook_repl_pre_readline(crate::hook::HookREPLPreReadlineInfo {});
- let mut readline = p
- .run_hook_repl_readline(crate::hook::HookREPLReadlineInfo {})
- .unwrap_or_default();
- p.run_hook_repl_post_readline(crate::hook::HookREPLPostReadlineInfo {
- line: &mut readline,
- });
-
- let args = split_input_string(readline.clone());
-
- p.run_hook_repl_pre_exec(crate::hook::HookREPLPreExecInfo { args: &args });
- match exec_once(p, args) {
- Ok(r) => {
- p.run_hook_repl_on_receive_result(
- crate::hook::HookREPLOnReceiveResultInfo { result: &r },
- );
- }
- Err(ProgramInternalExecuteError::REPLPanic(panic)) => {
- p.run_hook_repl_on_panic(crate::hook::HookREPLOnPanicInfo {
- panic: &panic,
- });
- }
- _ => {}
- }
- p.run_hook_repl_post_exec(crate::hook::HookREPLPostExecInfo {});
-
- if this::<C>().res::<ResREPL>().unwrap().exit {
- p.run_hook_repl_exit(crate::hook::HookREPLExitInfo {});
- break;
- }
-
- p.run_hook_repl_loop_once(crate::hook::HookREPLLoopOnceInfo {});
- }
- });
+ might_be_async::select!(
+ self.exec_wrapper(async |p| -> () {
+ repl_loop(p).await;
+ })
+ else
+ self.exec_wrapper(|p| -> () { repl_loop(p); }
+ )
+ );
}
}
-#[cfg(feature = "async")]
-impl<C> Program<C>
+#[might_be_async::func]
+fn repl_loop<C>(p: &'static Program<C>)
where
C: ProgramCollect<Enum = C> + Send + Sync + 'static,
{
- /// Executes the REPL interactive CLI mode.
- ///
- /// This method starts an infinite loop that continuously reads user input, parses commands, executes them,
- /// and displays the execution result or error message. It is suitable for scenarios requiring command-line interaction with the user.
- ///
- /// **Note:** When the `async` feature is enabled, panic unwinding is not supported.
- /// Any panics during command execution will result in an abort rather than being caught and handled gracefully.
- pub async fn exec_repl(mut self) {
- // Inject default REPL resource
- self.with_resource(ResREPL::default());
+ loop {
+ p.run_hook_repl_pre_readline(crate::hook::HookREPLPreReadlineInfo {});
+ let mut readline = p
+ .run_hook_repl_readline(crate::hook::HookREPLReadlineInfo {})
+ .unwrap_or_default();
+ p.run_hook_repl_post_readline(crate::hook::HookREPLPostReadlineInfo {
+ line: &mut readline,
+ });
- self.run_hook_repl_on_begin(crate::hook::HookREPLBeginInfo {});
+ let args = split_input_string(readline.clone());
- self.exec_wrapper(async |p| -> () {
- loop {
- p.run_hook_repl_pre_readline(crate::hook::HookREPLPreReadlineInfo {});
- let mut readline = p
- .run_hook_repl_readline(crate::hook::HookREPLReadlineInfo {})
- .unwrap_or_default();
- p.run_hook_repl_post_readline(crate::hook::HookREPLPostReadlineInfo {
- line: &mut readline,
+ p.run_hook_repl_pre_exec(crate::hook::HookREPLPreExecInfo { args: &args });
+ match might_be_async::invoke!(exec_once(p, args)) {
+ Ok(r) => {
+ p.run_hook_repl_on_receive_result(crate::hook::HookREPLOnReceiveResultInfo {
+ result: &r,
});
-
- let args = split_input_string(readline.clone());
-
- p.run_hook_repl_pre_exec(crate::hook::HookREPLPreExecInfo { args: &args });
- match exec_once(p, args).await {
- Ok(r) => {
- p.run_hook_repl_on_receive_result(
- crate::hook::HookREPLOnReceiveResultInfo { result: &r },
- );
- }
- Err(ProgramInternalExecuteError::REPLPanic(panic)) => {
- p.run_hook_repl_on_panic(crate::hook::HookREPLOnPanicInfo {
- panic: &panic,
- });
- }
- _ => {}
- }
- p.run_hook_repl_post_exec(crate::hook::HookREPLPostExecInfo {});
-
- if this::<C>().res::<ResREPL>().unwrap().exit {
- p.run_hook_repl_exit(crate::hook::HookREPLExitInfo {});
- break;
- }
-
- p.run_hook_repl_loop_once(crate::hook::HookREPLLoopOnceInfo {});
}
- })
- .await;
+ Err(ProgramInternalExecuteError::REPLPanic(panic)) => {
+ p.run_hook_repl_on_panic(crate::hook::HookREPLOnPanicInfo { panic: &panic });
+ }
+ _ => {}
+ }
+ p.run_hook_repl_post_exec(crate::hook::HookREPLPostExecInfo {});
+
+ if this::<C>().res::<ResREPL>().unwrap().exit {
+ p.run_hook_repl_exit(crate::hook::HookREPLExitInfo {});
+ break;
+ }
+
+ p.run_hook_repl_loop_once(crate::hook::HookREPLLoopOnceInfo {});
}
}
diff --git a/mingling_core/tests/test-all/Cargo.lock b/mingling_core/tests/test-all/Cargo.lock
index bb7b75b..9760ded 100644
--- a/mingling_core/tests/test-all/Cargo.lock
+++ b/mingling_core/tests/test-all/Cargo.lock
@@ -116,6 +116,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6b947ae49db0d222b1dbc6b113ce7248a3fc3a6ca21b696717bfc000ba4484d8"
[[package]]
+name = "might_be_async"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eca871cea620b07bd2e6da0c883891a25bead698c43a9ab64b0fd663a7a78d5f"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+ "toml 0.8.23",
+]
+
+[[package]]
name = "mingling"
version = "0.3.0"
dependencies = [
@@ -131,11 +143,12 @@ version = "0.3.0"
dependencies = [
"just_fmt 0.2.0",
"just_template",
+ "might_be_async",
"ron",
"serde",
"serde_json",
"serde_yaml",
- "toml",
+ "toml 1.1.2+spec-1.1.0",
]
[[package]]
@@ -292,6 +305,15 @@ dependencies = [
[[package]]
name = "serde_spanned"
+version = "0.6.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "serde_spanned"
version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6662b5879511e06e8999a8a235d848113e942c9124f211511b16466ee2995f26"
@@ -394,17 +416,38 @@ dependencies = [
[[package]]
name = "toml"
+version = "0.8.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362"
+dependencies = [
+ "serde",
+ "serde_spanned 0.6.9",
+ "toml_datetime 0.6.11",
+ "toml_edit",
+]
+
+[[package]]
+name = "toml"
version = "1.1.2+spec-1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "81f3d15e84cbcd896376e6730314d59fb5a87f31e4b038454184435cd57defee"
dependencies = [
"indexmap",
"serde_core",
- "serde_spanned",
- "toml_datetime",
+ "serde_spanned 1.1.1",
+ "toml_datetime 1.1.1+spec-1.1.0",
"toml_parser",
"toml_writer",
- "winnow",
+ "winnow 1.0.3",
+]
+
+[[package]]
+name = "toml_datetime"
+version = "0.6.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c"
+dependencies = [
+ "serde",
]
[[package]]
@@ -417,15 +460,35 @@ dependencies = [
]
[[package]]
+name = "toml_edit"
+version = "0.22.27"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a"
+dependencies = [
+ "indexmap",
+ "serde",
+ "serde_spanned 0.6.9",
+ "toml_datetime 0.6.11",
+ "toml_write",
+ "winnow 0.7.15",
+]
+
+[[package]]
name = "toml_parser"
version = "1.1.2+spec-1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526"
dependencies = [
- "winnow",
+ "winnow 1.0.3",
]
[[package]]
+name = "toml_write"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801"
+
+[[package]]
name = "toml_writer"
version = "1.1.1+spec-1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -472,6 +535,15 @@ dependencies = [
[[package]]
name = "winnow"
+version = "0.7.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "winnow"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0592e1c9d151f854e6fd382574c3a0855250e1d9b2f99d9281c6e6391af352f1"
diff --git a/mingling_core/tests/test-all/tests/integration.rs b/mingling_core/tests/test-all/tests/integration.rs
index d36b9df..acb12db 100644
--- a/mingling_core/tests/test-all/tests/integration.rs
+++ b/mingling_core/tests/test-all/tests/integration.rs
@@ -7,9 +7,9 @@ use mingling::StringVec;
use mingling::StructuralData;
use mingling::StructuralRenderer;
use mingling::StructuralRendererSetting;
-use mingling::comp::{ShellContext, ShellFlag, Suggest};
use mingling::core_res::ResREPL;
use mingling::hook::ProgramHook;
+use mingling::{ShellContext, ShellFlag, Suggest};
use serde::Serialize;
use std::sync::atomic::{AtomicBool, Ordering};
diff --git a/mingling_core/tests/test-basic/Cargo.lock b/mingling_core/tests/test-basic/Cargo.lock
index 5029bbf..a2f10e6 100644
--- a/mingling_core/tests/test-basic/Cargo.lock
+++ b/mingling_core/tests/test-basic/Cargo.lock
@@ -3,12 +3,52 @@
version = 4
[[package]]
+name = "equivalent"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
+
+[[package]]
+name = "hashbrown"
+version = "0.17.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a"
+
+[[package]]
+name = "indexmap"
+version = "2.14.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9"
+dependencies = [
+ "equivalent",
+ "hashbrown",
+]
+
+[[package]]
name = "just_fmt"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6170dccbc3ea15dfb7f2da964097f814aba1dd8f746d4ffc56f33245c38e6d96"
[[package]]
+name = "memchr"
+version = "2.8.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98"
+
+[[package]]
+name = "might_be_async"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eca871cea620b07bd2e6da0c883891a25bead698c43a9ab64b0fd663a7a78d5f"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.118",
+ "toml",
+]
+
+[[package]]
name = "mingling"
version = "0.3.0"
dependencies = [
@@ -21,6 +61,7 @@ name = "mingling_core"
version = "0.3.0"
dependencies = [
"just_fmt",
+ "might_be_async",
]
[[package]]
@@ -30,7 +71,7 @@ dependencies = [
"just_fmt",
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.118",
]
[[package]]
@@ -52,6 +93,44 @@ dependencies = [
]
[[package]]
+name = "serde"
+version = "1.0.229"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba"
+dependencies = [
+ "serde_core",
+]
+
+[[package]]
+name = "serde_core"
+version = "1.0.229"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "67dca2c9c51e58a4791a4b1ed58308b39c64224d349a935ab5039aa360942a48"
+dependencies = [
+ "serde_derive",
+]
+
+[[package]]
+name = "serde_derive"
+version = "1.0.229"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 3.0.3",
+]
+
+[[package]]
+name = "serde_spanned"
+version = "0.6.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3"
+dependencies = [
+ "serde",
+]
+
+[[package]]
name = "syn"
version = "2.0.118"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -63,6 +142,17 @@ dependencies = [
]
[[package]]
+name = "syn"
+version = "3.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "53e9bae58849f64dfa4f5d5ae372c8341f7305f82a3868709269343628b659a3"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
name = "test-basic"
version = "0.1.0"
dependencies = [
@@ -70,7 +160,57 @@ dependencies = [
]
[[package]]
+name = "toml"
+version = "0.8.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362"
+dependencies = [
+ "serde",
+ "serde_spanned",
+ "toml_datetime",
+ "toml_edit",
+]
+
+[[package]]
+name = "toml_datetime"
+version = "0.6.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "toml_edit"
+version = "0.22.27"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a"
+dependencies = [
+ "indexmap",
+ "serde",
+ "serde_spanned",
+ "toml_datetime",
+ "toml_write",
+ "winnow",
+]
+
+[[package]]
+name = "toml_write"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801"
+
+[[package]]
name = "unicode-ident"
version = "1.0.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
+
+[[package]]
+name = "winnow"
+version = "0.7.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945"
+dependencies = [
+ "memchr",
+]
diff --git a/mingling_core/tests/test-comp/Cargo.lock b/mingling_core/tests/test-comp/Cargo.lock
index 175b65e..87b9088 100644
--- a/mingling_core/tests/test-comp/Cargo.lock
+++ b/mingling_core/tests/test-comp/Cargo.lock
@@ -3,6 +3,28 @@
version = 4
[[package]]
+name = "equivalent"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
+
+[[package]]
+name = "hashbrown"
+version = "0.17.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a"
+
+[[package]]
+name = "indexmap"
+version = "2.14.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9"
+dependencies = [
+ "equivalent",
+ "hashbrown",
+]
+
+[[package]]
name = "just_fmt"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -32,7 +54,25 @@ checksum = "1471eb68722ecefeb71debdde2859e8725341f171d3f42b3a98a0862ad19416e"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.118",
+]
+
+[[package]]
+name = "memchr"
+version = "2.8.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98"
+
+[[package]]
+name = "might_be_async"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eca871cea620b07bd2e6da0c883891a25bead698c43a9ab64b0fd663a7a78d5f"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.118",
+ "toml",
]
[[package]]
@@ -49,6 +89,7 @@ version = "0.3.0"
dependencies = [
"just_fmt 0.2.0",
"just_template",
+ "might_be_async",
]
[[package]]
@@ -58,7 +99,7 @@ dependencies = [
"just_fmt 0.2.0",
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.118",
]
[[package]]
@@ -80,6 +121,44 @@ dependencies = [
]
[[package]]
+name = "serde"
+version = "1.0.229"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba"
+dependencies = [
+ "serde_core",
+]
+
+[[package]]
+name = "serde_core"
+version = "1.0.229"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "67dca2c9c51e58a4791a4b1ed58308b39c64224d349a935ab5039aa360942a48"
+dependencies = [
+ "serde_derive",
+]
+
+[[package]]
+name = "serde_derive"
+version = "1.0.229"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 3.0.3",
+]
+
+[[package]]
+name = "serde_spanned"
+version = "0.6.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3"
+dependencies = [
+ "serde",
+]
+
+[[package]]
name = "syn"
version = "2.0.118"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -91,6 +170,17 @@ dependencies = [
]
[[package]]
+name = "syn"
+version = "3.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "53e9bae58849f64dfa4f5d5ae372c8341f7305f82a3868709269343628b659a3"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
name = "test-comp"
version = "0.1.0"
dependencies = [
@@ -98,7 +188,57 @@ dependencies = [
]
[[package]]
+name = "toml"
+version = "0.8.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362"
+dependencies = [
+ "serde",
+ "serde_spanned",
+ "toml_datetime",
+ "toml_edit",
+]
+
+[[package]]
+name = "toml_datetime"
+version = "0.6.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "toml_edit"
+version = "0.22.27"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a"
+dependencies = [
+ "indexmap",
+ "serde",
+ "serde_spanned",
+ "toml_datetime",
+ "toml_write",
+ "winnow",
+]
+
+[[package]]
+name = "toml_write"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801"
+
+[[package]]
name = "unicode-ident"
version = "1.0.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
+
+[[package]]
+name = "winnow"
+version = "0.7.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945"
+dependencies = [
+ "memchr",
+]
diff --git a/mingling_core/tests/test-comp/tests/integration.rs b/mingling_core/tests/test-comp/tests/integration.rs
index 37aa716..5c5a9e4 100644
--- a/mingling_core/tests/test-comp/tests/integration.rs
+++ b/mingling_core/tests/test-comp/tests/integration.rs
@@ -1,6 +1,6 @@
use mingling::MockProgramCollect;
use mingling::Program;
-use mingling::comp::{ShellContext, ShellFlag, Suggest, SuggestItem};
+use mingling::{ShellContext, ShellFlag, Suggest, SuggestItem};
#[test]
fn test_shell_context_parsing_full() {
diff --git a/mingling_core/tests/test-dispatch-tree/Cargo.lock b/mingling_core/tests/test-dispatch-tree/Cargo.lock
index 39d82c5..5f6e3bc 100644
--- a/mingling_core/tests/test-dispatch-tree/Cargo.lock
+++ b/mingling_core/tests/test-dispatch-tree/Cargo.lock
@@ -3,12 +3,52 @@
version = 4
[[package]]
+name = "equivalent"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
+
+[[package]]
+name = "hashbrown"
+version = "0.17.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a"
+
+[[package]]
+name = "indexmap"
+version = "2.14.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9"
+dependencies = [
+ "equivalent",
+ "hashbrown",
+]
+
+[[package]]
name = "just_fmt"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6170dccbc3ea15dfb7f2da964097f814aba1dd8f746d4ffc56f33245c38e6d96"
[[package]]
+name = "memchr"
+version = "2.8.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98"
+
+[[package]]
+name = "might_be_async"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eca871cea620b07bd2e6da0c883891a25bead698c43a9ab64b0fd663a7a78d5f"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.118",
+ "toml",
+]
+
+[[package]]
name = "mingling"
version = "0.3.0"
dependencies = [
@@ -21,6 +61,7 @@ name = "mingling_core"
version = "0.3.0"
dependencies = [
"just_fmt",
+ "might_be_async",
]
[[package]]
@@ -30,7 +71,7 @@ dependencies = [
"just_fmt",
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.118",
]
[[package]]
@@ -52,6 +93,44 @@ dependencies = [
]
[[package]]
+name = "serde"
+version = "1.0.229"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba"
+dependencies = [
+ "serde_core",
+]
+
+[[package]]
+name = "serde_core"
+version = "1.0.229"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "67dca2c9c51e58a4791a4b1ed58308b39c64224d349a935ab5039aa360942a48"
+dependencies = [
+ "serde_derive",
+]
+
+[[package]]
+name = "serde_derive"
+version = "1.0.229"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 3.0.3",
+]
+
+[[package]]
+name = "serde_spanned"
+version = "0.6.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3"
+dependencies = [
+ "serde",
+]
+
+[[package]]
name = "syn"
version = "2.0.118"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -63,6 +142,17 @@ dependencies = [
]
[[package]]
+name = "syn"
+version = "3.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "53e9bae58849f64dfa4f5d5ae372c8341f7305f82a3868709269343628b659a3"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
name = "test-dispatch-tree"
version = "0.1.0"
dependencies = [
@@ -70,7 +160,57 @@ dependencies = [
]
[[package]]
+name = "toml"
+version = "0.8.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362"
+dependencies = [
+ "serde",
+ "serde_spanned",
+ "toml_datetime",
+ "toml_edit",
+]
+
+[[package]]
+name = "toml_datetime"
+version = "0.6.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "toml_edit"
+version = "0.22.27"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a"
+dependencies = [
+ "indexmap",
+ "serde",
+ "serde_spanned",
+ "toml_datetime",
+ "toml_write",
+ "winnow",
+]
+
+[[package]]
+name = "toml_write"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801"
+
+[[package]]
name = "unicode-ident"
version = "1.0.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
+
+[[package]]
+name = "winnow"
+version = "0.7.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945"
+dependencies = [
+ "memchr",
+]
diff --git a/mingling_core/tests/test-repl/Cargo.lock b/mingling_core/tests/test-repl/Cargo.lock
index 2b990f2..37f3385 100644
--- a/mingling_core/tests/test-repl/Cargo.lock
+++ b/mingling_core/tests/test-repl/Cargo.lock
@@ -3,12 +3,52 @@
version = 4
[[package]]
+name = "equivalent"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
+
+[[package]]
+name = "hashbrown"
+version = "0.17.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a"
+
+[[package]]
+name = "indexmap"
+version = "2.14.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9"
+dependencies = [
+ "equivalent",
+ "hashbrown",
+]
+
+[[package]]
name = "just_fmt"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6170dccbc3ea15dfb7f2da964097f814aba1dd8f746d4ffc56f33245c38e6d96"
[[package]]
+name = "memchr"
+version = "2.8.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98"
+
+[[package]]
+name = "might_be_async"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eca871cea620b07bd2e6da0c883891a25bead698c43a9ab64b0fd663a7a78d5f"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.118",
+ "toml",
+]
+
+[[package]]
name = "mingling"
version = "0.3.0"
dependencies = [
@@ -21,6 +61,7 @@ name = "mingling_core"
version = "0.3.0"
dependencies = [
"just_fmt",
+ "might_be_async",
]
[[package]]
@@ -30,7 +71,7 @@ dependencies = [
"just_fmt",
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.118",
]
[[package]]
@@ -52,6 +93,44 @@ dependencies = [
]
[[package]]
+name = "serde"
+version = "1.0.229"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba"
+dependencies = [
+ "serde_core",
+]
+
+[[package]]
+name = "serde_core"
+version = "1.0.229"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "67dca2c9c51e58a4791a4b1ed58308b39c64224d349a935ab5039aa360942a48"
+dependencies = [
+ "serde_derive",
+]
+
+[[package]]
+name = "serde_derive"
+version = "1.0.229"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 3.0.3",
+]
+
+[[package]]
+name = "serde_spanned"
+version = "0.6.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3"
+dependencies = [
+ "serde",
+]
+
+[[package]]
name = "syn"
version = "2.0.118"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -63,6 +142,17 @@ dependencies = [
]
[[package]]
+name = "syn"
+version = "3.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "53e9bae58849f64dfa4f5d5ae372c8341f7305f82a3868709269343628b659a3"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
name = "test-repl"
version = "0.1.0"
dependencies = [
@@ -70,7 +160,57 @@ dependencies = [
]
[[package]]
+name = "toml"
+version = "0.8.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362"
+dependencies = [
+ "serde",
+ "serde_spanned",
+ "toml_datetime",
+ "toml_edit",
+]
+
+[[package]]
+name = "toml_datetime"
+version = "0.6.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "toml_edit"
+version = "0.22.27"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a"
+dependencies = [
+ "indexmap",
+ "serde",
+ "serde_spanned",
+ "toml_datetime",
+ "toml_write",
+ "winnow",
+]
+
+[[package]]
+name = "toml_write"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801"
+
+[[package]]
name = "unicode-ident"
version = "1.0.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
+
+[[package]]
+name = "winnow"
+version = "0.7.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945"
+dependencies = [
+ "memchr",
+]
diff --git a/mingling_core/tests/test-structural-renderer/Cargo.lock b/mingling_core/tests/test-structural-renderer/Cargo.lock
index bf5291d..aaf6c26 100644
--- a/mingling_core/tests/test-structural-renderer/Cargo.lock
+++ b/mingling_core/tests/test-structural-renderer/Cargo.lock
@@ -52,6 +52,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6b947ae49db0d222b1dbc6b113ce7248a3fc3a6ca21b696717bfc000ba4484d8"
[[package]]
+name = "might_be_async"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eca871cea620b07bd2e6da0c883891a25bead698c43a9ab64b0fd663a7a78d5f"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+ "toml 0.8.23",
+]
+
+[[package]]
name = "mingling"
version = "0.3.0"
dependencies = [
@@ -66,11 +78,12 @@ name = "mingling_core"
version = "0.3.0"
dependencies = [
"just_fmt",
+ "might_be_async",
"ron",
"serde",
"serde_json",
"serde_yaml",
- "toml",
+ "toml 1.1.2+spec-1.1.0",
]
[[package]]
@@ -172,6 +185,15 @@ dependencies = [
[[package]]
name = "serde_spanned"
+version = "0.6.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "serde_spanned"
version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6662b5879511e06e8999a8a235d848113e942c9124f211511b16466ee2995f26"
@@ -219,17 +241,38 @@ dependencies = [
[[package]]
name = "toml"
+version = "0.8.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362"
+dependencies = [
+ "serde",
+ "serde_spanned 0.6.9",
+ "toml_datetime 0.6.11",
+ "toml_edit",
+]
+
+[[package]]
+name = "toml"
version = "1.1.2+spec-1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "81f3d15e84cbcd896376e6730314d59fb5a87f31e4b038454184435cd57defee"
dependencies = [
"indexmap",
"serde_core",
- "serde_spanned",
- "toml_datetime",
+ "serde_spanned 1.1.1",
+ "toml_datetime 1.1.1+spec-1.1.0",
"toml_parser",
"toml_writer",
- "winnow",
+ "winnow 1.0.3",
+]
+
+[[package]]
+name = "toml_datetime"
+version = "0.6.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c"
+dependencies = [
+ "serde",
]
[[package]]
@@ -242,15 +285,35 @@ dependencies = [
]
[[package]]
+name = "toml_edit"
+version = "0.22.27"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a"
+dependencies = [
+ "indexmap",
+ "serde",
+ "serde_spanned 0.6.9",
+ "toml_datetime 0.6.11",
+ "toml_write",
+ "winnow 0.7.15",
+]
+
+[[package]]
name = "toml_parser"
version = "1.1.2+spec-1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526"
dependencies = [
- "winnow",
+ "winnow 1.0.3",
]
[[package]]
+name = "toml_write"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801"
+
+[[package]]
name = "toml_writer"
version = "1.1.1+spec-1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -276,6 +339,15 @@ checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861"
[[package]]
name = "winnow"
+version = "0.7.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "winnow"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0592e1c9d151f854e6fd382574c3a0855250e1d9b2f99d9281c6e6391af352f1"