aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author魏曹先生 <1992414357@qq.com>2026-06-20 01:11:25 +0800
committer魏曹先生 <1992414357@qq.com>2026-06-20 01:11:25 +0800
commit9d491352d161ee629cc47459537344ba0ea4bb35 (patch)
tree40d847da5cfafce48c3ca99c78bcc077da4c4fb2
parent8749087c5035fbe4c0dce0893a39e0e2265fa130 (diff)
Add shared `MockProgramCollect` and conditional `Groupped` bounds
Extract duplicate `MockCollect` implementations into a reusable `MockProgramCollect` type. Conditionally require `Serialize` on the `Groupped` trait when the `general_renderer` feature is enabled.
-rw-r--r--examples/example-pack-err/page.toml2
-rw-r--r--mingling_core/src/any/group.rs87
-rw-r--r--mingling_core/src/comp/comp_ctx.rs65
-rw-r--r--mingling_core/src/program/collection.rs3
-rw-r--r--mingling_core/src/program/collection/mock.rs105
-rw-r--r--mingling_core/src/program/setup.rs63
-rw-r--r--mingling_core/tests/test-all/tests/integration.rs76
-rw-r--r--mingling_core/tests/test-comp/tests/integration.rs55
-rw-r--r--mingling_macros/src/dispatcher.rs1
-rw-r--r--mingling_macros/src/lib.rs7
-rw-r--r--mling/src/cli.rs2
11 files changed, 205 insertions, 261 deletions
diff --git a/examples/example-pack-err/page.toml b/examples/example-pack-err/page.toml
index 5534236..255bbdd 100644
--- a/examples/example-pack-err/page.toml
+++ b/examples/example-pack-err/page.toml
@@ -1,6 +1,6 @@
[example]
id = "example-pack-err"
-name = "pack_err!"
+name = "Pack an Error"
icon = "🛑"
category = "macros"
desc = """
diff --git a/mingling_core/src/any/group.rs b/mingling_core/src/any/group.rs
index c251286..e9fce5e 100644
--- a/mingling_core/src/any/group.rs
+++ b/mingling_core/src/any/group.rs
@@ -1,21 +1,74 @@
-use crate::{AnyOutput, ChainProcess};
-
-/// Used to mark a type with a unique enum ID, assisting dynamic dispatch
-pub trait Groupped<Group> {
- /// Returns the specific enum value representing its ID within that enum
- fn member_id() -> Group;
-
- /// Converts the grouped item into a `ChainProcess` directed to the chain route.
- ///
- /// This wraps the item into an `AnyOutput` and routes it to the chain processing pipeline.
- fn to_chain(self) -> ChainProcess<Group> {
- AnyOutput::new(self).route_chain()
+#[cfg(feature = "general_renderer")]
+pub use general_renderer_groupped::*;
+
+#[cfg(not(feature = "general_renderer"))]
+pub use groupped::*;
+
+#[cfg(feature = "general_renderer")]
+mod general_renderer_groupped {
+ use serde::Serialize;
+
+ use crate::{AnyOutput, ChainProcess};
+ /// Used to mark a type with a unique enum ID, assisting dynamic dispatch
+ pub trait Groupped<Group>
+ where
+ Self: Sized + Serialize + 'static,
+ {
+ /// Returns the specific enum value representing its ID within that enum
+ fn member_id() -> Group;
+
+ /// Converts the grouped item into a `ChainProcess` directed to the chain route.
+ ///
+ /// This wraps the item into an `AnyOutput` and routes it to the chain processing pipeline.
+ fn to_chain(self) -> ChainProcess<Group>
+ where
+ Self: Send + Serialize,
+ {
+ AnyOutput::new(self).route_chain()
+ }
+
+ /// Converts the grouped item into a `ChainProcess` directed to the render route.
+ ///
+ /// This wraps the item into an `AnyOutput` and routes it to the render processing pipeline.
+ fn to_render(self) -> ChainProcess<Group>
+ where
+ Self: Send + Serialize,
+ {
+ AnyOutput::new(self).route_renderer()
+ }
}
+}
+
+#[cfg(not(feature = "general_renderer"))]
+mod groupped {
+ use crate::{AnyOutput, ChainProcess};
+
+ /// Used to mark a type with a unique enum ID, assisting dynamic dispatch
+ pub trait Groupped<Group>
+ where
+ Self: Sized + 'static,
+ {
+ /// Returns the specific enum value representing its ID within that enum
+ fn member_id() -> Group;
+
+ /// Converts the grouped item into a `ChainProcess` directed to the chain route.
+ ///
+ /// This wraps the item into an `AnyOutput` and routes it to the chain processing pipeline.
+ fn to_chain(self) -> ChainProcess<Group>
+ where
+ Self: Send,
+ {
+ AnyOutput::new(self).route_chain()
+ }
- /// Converts the grouped item into a `ChainProcess` directed to the render route.
- ///
- /// This wraps the item into an `AnyOutput` and routes it to the render processing pipeline.
- fn to_render(self) -> ChainProcess<Group> {
- AnyOutput::new(self).route_renderer()
+ /// Converts the grouped item into a `ChainProcess` directed to the render route.
+ ///
+ /// This wraps the item into an `AnyOutput` and routes it to the render processing pipeline.
+ fn to_render(self) -> ChainProcess<Group>
+ where
+ Self: Send,
+ {
+ AnyOutput::new(self).route_renderer()
+ }
}
}
diff --git a/mingling_core/src/comp/comp_ctx.rs b/mingling_core/src/comp/comp_ctx.rs
index b9f9020..8d7fa5c 100644
--- a/mingling_core/src/comp/comp_ctx.rs
+++ b/mingling_core/src/comp/comp_ctx.rs
@@ -20,80 +20,27 @@ where
#[cfg(test)]
mod tests {
- use super::*;
- use crate::{AnyOutput, ChainProcess, Groupped, RenderResult};
-
- /// Minimal mock collector that satisfies `C: ProgramCollect<Enum = C>`
- /// by setting `Enum = Self`.
- #[derive(Debug, Clone, PartialEq)]
- struct MockCollect;
-
- impl Groupped<MockCollect> for MockCollect {
- fn member_id() -> MockCollect {
- MockCollect
- }
- }
+ use crate::MockProgramCollect;
- impl ProgramCollect for MockCollect {
- type Enum = MockCollect;
- type ErrorDispatcherNotFound = MockCollect;
- type ErrorRendererNotFound = MockCollect;
- type ResultEmpty = MockCollect;
-
- fn build_renderer_not_found(_member_id: MockCollect) -> AnyOutput<MockCollect> {
- unimplemented!()
- }
- fn build_dispatcher_not_found(_args: Vec<String>) -> AnyOutput<MockCollect> {
- unimplemented!()
- }
- fn build_empty_result() -> AnyOutput<MockCollect> {
- unimplemented!()
- }
- fn render(_any: AnyOutput<MockCollect>, _r: &mut RenderResult) {
- unimplemented!()
- }
- fn render_help(_any: AnyOutput<MockCollect>, _r: &mut RenderResult) {
- unimplemented!()
- }
- fn do_chain(_any: AnyOutput<MockCollect>) -> ChainProcess<MockCollect> {
- unimplemented!()
- }
- #[cfg(feature = "comp")]
- fn do_comp(_any: &AnyOutput<MockCollect>, _ctx: &crate::ShellContext) -> crate::Suggest {
- unimplemented!()
- }
- fn has_renderer(_any: &AnyOutput<MockCollect>) -> bool {
- unimplemented!()
- }
- fn has_chain(_any: &AnyOutput<MockCollect>) -> bool {
- unimplemented!()
- }
-
- #[cfg(feature = "general_renderer")]
- fn general_render(
- _any: AnyOutput<MockCollect>,
- _setting: &crate::GeneralRendererSetting,
- ) -> Result<RenderResult, crate::error::GeneralRendererSerializeError> {
- unimplemented!()
- }
- }
+ use super::*;
#[test]
fn test_is_completing_with_comp_subcommand() {
- let program: Program<MockCollect> =
+ let program: Program<MockProgramCollect> =
Program::new_with_args(["program", "__comp", "some", "args"]);
assert!(program.is_completing());
}
#[test]
fn test_is_completing_with_normal_subcommand() {
- let program: Program<MockCollect> = Program::new_with_args(["program", "normal", "cmd"]);
+ let program: Program<MockProgramCollect> =
+ Program::new_with_args(["program", "normal", "cmd"]);
assert!(!program.is_completing());
}
#[test]
fn test_is_completing_with_no_args() {
- let program: Program<MockCollect> = Program::new_with_args(["program"]);
+ let program: Program<MockProgramCollect> = Program::new_with_args(["program"]);
assert!(!program.is_completing());
}
}
diff --git a/mingling_core/src/program/collection.rs b/mingling_core/src/program/collection.rs
index d3d18d6..078f736 100644
--- a/mingling_core/src/program/collection.rs
+++ b/mingling_core/src/program/collection.rs
@@ -12,6 +12,9 @@ use crate::{GeneralRendererSetting, error::GeneralRendererSerializeError};
#[cfg(feature = "comp")]
use crate::{ShellContext, Suggest};
+mod mock;
+pub use mock::*;
+
/// Collected program context
///
/// Note: It is recommended to use the `gen_program!()` macro from [mingling_macros](https://crates.io/crates/mingling_macros) to automatically create this type
diff --git a/mingling_core/src/program/collection/mock.rs b/mingling_core/src/program/collection/mock.rs
new file mode 100644
index 0000000..e1b3aa4
--- /dev/null
+++ b/mingling_core/src/program/collection/mock.rs
@@ -0,0 +1,105 @@
+pub use mock::*;
+
+mod mock {
+ #[cfg(feature = "async")]
+ use std::pin::Pin;
+
+ #[cfg(feature = "dispatch_tree")]
+ use crate::Dispatcher;
+
+ use crate::{AnyOutput, ChainProcess, Groupped, ProgramCollect, RenderResult};
+
+ #[cfg(feature = "general_renderer")]
+ use crate::{GeneralRendererSetting, error::GeneralRendererSerializeError};
+
+ #[cfg(feature = "comp")]
+ use crate::{ShellContext, Suggest};
+
+ #[cfg(feature = "general_renderer")]
+ use serde::Serialize;
+
+ #[cfg_attr(feature = "general_renderer", derive(Serialize))]
+ #[allow(unused)]
+ pub enum MockProgramCollect {
+ Foo,
+ Bar,
+ }
+
+ impl Groupped<MockProgramCollect> for MockProgramCollect {
+ fn member_id() -> MockProgramCollect {
+ MockProgramCollect::Foo
+ }
+ }
+
+ impl ProgramCollect for MockProgramCollect {
+ type Enum = MockProgramCollect;
+ type ErrorDispatcherNotFound = MockProgramCollect;
+ type ErrorRendererNotFound = MockProgramCollect;
+ type ResultEmpty = MockProgramCollect;
+
+ #[cfg(feature = "dispatch_tree")]
+ fn dispatch_args_trie(
+ _raw: &[String],
+ ) -> Result<AnyOutput<Self::Enum>, crate::error::ProgramInternalExecuteError> {
+ unreachable!()
+ }
+
+ #[cfg(feature = "dispatch_tree")]
+ fn get_nodes() -> Vec<(String, &'static (dyn Dispatcher<Self::Enum> + Send + Sync))> {
+ unreachable!()
+ }
+
+ fn build_renderer_not_found(_member_id: Self::Enum) -> AnyOutput<Self::Enum> {
+ unreachable!()
+ }
+
+ fn build_dispatcher_not_found(_args: Vec<String>) -> AnyOutput<Self::Enum> {
+ unreachable!()
+ }
+
+ fn build_empty_result() -> AnyOutput<Self::Enum> {
+ unreachable!()
+ }
+
+ fn render(_any: AnyOutput<Self::Enum>, _r: &mut RenderResult) {
+ unreachable!()
+ }
+
+ fn render_help(_any: AnyOutput<Self::Enum>, _r: &mut RenderResult) {
+ unreachable!()
+ }
+
+ #[cfg(feature = "async")]
+ fn do_chain(
+ _any: AnyOutput<Self::Enum>,
+ ) -> Pin<Box<dyn Future<Output = ChainProcess<Self::Enum>> + Send>> {
+ unreachable!()
+ }
+
+ #[cfg(not(feature = "async"))]
+ fn do_chain(_any: AnyOutput<Self::Enum>) -> ChainProcess<Self::Enum> {
+ unreachable!()
+ }
+
+ #[cfg(feature = "comp")]
+ fn do_comp(_any: &AnyOutput<Self::Enum>, _ctx: &ShellContext) -> Suggest {
+ unreachable!()
+ }
+
+ fn has_renderer(_any: &AnyOutput<Self::Enum>) -> bool {
+ unreachable!()
+ }
+
+ fn has_chain(_any: &AnyOutput<Self::Enum>) -> bool {
+ unreachable!()
+ }
+
+ #[cfg(feature = "general_renderer")]
+ fn general_render(
+ _any: AnyOutput<Self::Enum>,
+ _setting: &GeneralRendererSetting,
+ ) -> Result<RenderResult, GeneralRendererSerializeError> {
+ unreachable!()
+ }
+ }
+}
diff --git a/mingling_core/src/program/setup.rs b/mingling_core/src/program/setup.rs
index 2bfced1..f248fb6 100644
--- a/mingling_core/src/program/setup.rs
+++ b/mingling_core/src/program/setup.rs
@@ -20,69 +20,14 @@ where
#[cfg(test)]
mod tests {
use super::*;
- use crate::{AnyOutput, ChainProcess, Groupped, RenderResult};
-
- /// Minimal mock collector that satisfies `C: ProgramCollect<Enum = C>`
- /// by setting `Enum = Self`.
- #[derive(Debug, Clone, PartialEq)]
- struct MockCollect;
-
- impl Groupped<MockCollect> for MockCollect {
- fn member_id() -> MockCollect {
- MockCollect
- }
- }
-
- impl ProgramCollect for MockCollect {
- type Enum = MockCollect;
- type ErrorDispatcherNotFound = MockCollect;
- type ErrorRendererNotFound = MockCollect;
- type ResultEmpty = MockCollect;
-
- fn build_renderer_not_found(_member_id: MockCollect) -> AnyOutput<MockCollect> {
- unimplemented!()
- }
- fn build_dispatcher_not_found(_args: Vec<String>) -> AnyOutput<MockCollect> {
- unimplemented!()
- }
- fn build_empty_result() -> AnyOutput<MockCollect> {
- unimplemented!()
- }
- fn render(_any: AnyOutput<MockCollect>, _r: &mut RenderResult) {
- unimplemented!()
- }
- fn render_help(_any: AnyOutput<MockCollect>, _r: &mut RenderResult) {
- unimplemented!()
- }
- fn do_chain(_any: AnyOutput<MockCollect>) -> ChainProcess<MockCollect> {
- unimplemented!()
- }
- #[cfg(feature = "comp")]
- fn do_comp(_any: &AnyOutput<MockCollect>, _ctx: &crate::ShellContext) -> crate::Suggest {
- unimplemented!()
- }
- fn has_renderer(_any: &AnyOutput<MockCollect>) -> bool {
- unimplemented!()
- }
- fn has_chain(_any: &AnyOutput<MockCollect>) -> bool {
- unimplemented!()
- }
-
- #[cfg(feature = "general_renderer")]
- fn general_render(
- _any: AnyOutput<MockCollect>,
- _setting: &crate::GeneralRendererSetting,
- ) -> Result<RenderResult, crate::error::GeneralRendererSerializeError> {
- unimplemented!()
- }
- }
+ use crate::MockProgramCollect;
struct TestSetup {
called: std::rc::Rc<std::cell::Cell<bool>>,
}
- impl ProgramSetup<MockCollect> for TestSetup {
- fn setup(self, _program: &mut Program<MockCollect>) {
+ impl ProgramSetup<MockProgramCollect> for TestSetup {
+ fn setup(self, _program: &mut Program<MockProgramCollect>) {
self.called.set(true);
}
}
@@ -93,7 +38,7 @@ mod tests {
let setup = TestSetup {
called: std::rc::Rc::clone(&called),
};
- let mut program: Program<MockCollect> = Program::new_with_args(["test"]);
+ let mut program: Program<MockProgramCollect> = Program::new_with_args(["test"]);
program.with_setup(setup);
assert!(called.get());
}
diff --git a/mingling_core/tests/test-all/tests/integration.rs b/mingling_core/tests/test-all/tests/integration.rs
index f910729..c622835 100644
--- a/mingling_core/tests/test-all/tests/integration.rs
+++ b/mingling_core/tests/test-all/tests/integration.rs
@@ -1,11 +1,10 @@
use mingling::Flag;
use mingling::GeneralRenderer;
use mingling::GeneralRendererSetting;
-use mingling::Groupped;
+use mingling::MockProgramCollect;
use mingling::NextProcess;
use mingling::Node;
use mingling::Program;
-use mingling::ProgramCollect;
use mingling::RenderResult;
use mingling::StringVec;
use mingling::comp::{ShellContext, ShellFlag, Suggest};
@@ -14,73 +13,6 @@ use mingling::hook::ProgramHook;
use serde::Serialize;
use std::sync::atomic::{AtomicBool, Ordering};
-// MockCollect for is_completing tests
-
-#[derive(Debug, Clone, PartialEq)]
-struct MockCollect;
-
-impl Groupped<MockCollect> for MockCollect {
- fn member_id() -> MockCollect {
- MockCollect
- }
-}
-
-impl ProgramCollect for MockCollect {
- type Enum = MockCollect;
- type ErrorDispatcherNotFound = MockCollect;
- type ErrorRendererNotFound = MockCollect;
- type ResultEmpty = MockCollect;
-
- fn build_renderer_not_found(_member_id: MockCollect) -> mingling::AnyOutput<MockCollect> {
- unimplemented!()
- }
- fn build_dispatcher_not_found(_args: Vec<String>) -> mingling::AnyOutput<MockCollect> {
- unimplemented!()
- }
- fn build_empty_result() -> mingling::AnyOutput<MockCollect> {
- unimplemented!()
- }
- fn render(_any: mingling::AnyOutput<MockCollect>, _r: &mut RenderResult) {
- unimplemented!()
- }
- fn render_help(_any: mingling::AnyOutput<MockCollect>, _r: &mut RenderResult) {
- unimplemented!()
- }
- fn do_chain(_any: mingling::AnyOutput<MockCollect>) -> mingling::ChainProcess<MockCollect> {
- unimplemented!()
- }
- fn do_comp(_any: &mingling::AnyOutput<MockCollect>, _ctx: &ShellContext) -> Suggest {
- unimplemented!()
- }
- fn has_renderer(_any: &mingling::AnyOutput<MockCollect>) -> bool {
- unimplemented!()
- }
- fn has_chain(_any: &mingling::AnyOutput<MockCollect>) -> bool {
- unimplemented!()
- }
-
- fn dispatch_args_trie(
- _raw: &[String],
- ) -> Result<mingling::AnyOutput<MockCollect>, mingling::error::ProgramInternalExecuteError>
- {
- unimplemented!()
- }
-
- fn get_nodes() -> Vec<(
- String,
- &'static (dyn mingling::Dispatcher<MockCollect> + Send + Sync),
- )> {
- unimplemented!()
- }
-
- fn general_render(
- _any: mingling::AnyOutput<MockCollect>,
- _setting: &GeneralRendererSetting,
- ) -> Result<RenderResult, mingling::error::GeneralRendererSerializeError> {
- unimplemented!()
- }
-}
-
// ShellContext
#[test]
@@ -192,13 +124,13 @@ fn test_general_renderer_json() {
#[test]
fn test_is_completing() {
- let program: Program<MockCollect> = Program::new_with_args(["app", "__comp"]);
+ let program: Program<MockProgramCollect> = Program::new_with_args(["app", "__comp"]);
assert!(program.is_completing());
}
#[test]
fn test_is_not_completing() {
- let program: Program<MockCollect> = Program::new_with_args(["app", "greet"]);
+ let program: Program<MockProgramCollect> = Program::new_with_args(["app", "greet"]);
assert!(!program.is_completing());
}
@@ -208,7 +140,7 @@ fn test_is_not_completing() {
fn test_hook_setup() {
static CALLED: AtomicBool = AtomicBool::new(false);
- let hook = ProgramHook::<MockCollect>::empty().on_begin(|| {
+ let hook = ProgramHook::<MockProgramCollect>::empty().on_begin(|| {
CALLED.store(true, Ordering::SeqCst);
});
diff --git a/mingling_core/tests/test-comp/tests/integration.rs b/mingling_core/tests/test-comp/tests/integration.rs
index 4e6455e..37aa716 100644
--- a/mingling_core/tests/test-comp/tests/integration.rs
+++ b/mingling_core/tests/test-comp/tests/integration.rs
@@ -1,55 +1,7 @@
-use mingling::Groupped;
+use mingling::MockProgramCollect;
use mingling::Program;
-use mingling::ProgramCollect;
-use mingling::RenderResult;
use mingling::comp::{ShellContext, ShellFlag, Suggest, SuggestItem};
-/// Minimal mock collector that satisfies `C: ProgramCollect<Enum = C>`
-/// by setting `Enum = Self`.
-#[derive(Debug, Clone, PartialEq)]
-struct MockCollect;
-
-impl Groupped<MockCollect> for MockCollect {
- fn member_id() -> MockCollect {
- MockCollect
- }
-}
-
-impl ProgramCollect for MockCollect {
- type Enum = MockCollect;
- type ErrorDispatcherNotFound = MockCollect;
- type ErrorRendererNotFound = MockCollect;
- type ResultEmpty = MockCollect;
-
- fn build_renderer_not_found(_member_id: MockCollect) -> mingling::AnyOutput<MockCollect> {
- unimplemented!()
- }
- fn build_dispatcher_not_found(_args: Vec<String>) -> mingling::AnyOutput<MockCollect> {
- unimplemented!()
- }
- fn build_empty_result() -> mingling::AnyOutput<MockCollect> {
- unimplemented!()
- }
- fn render(_any: mingling::AnyOutput<MockCollect>, _r: &mut RenderResult) {
- unimplemented!()
- }
- fn render_help(_any: mingling::AnyOutput<MockCollect>, _r: &mut RenderResult) {
- unimplemented!()
- }
- fn do_chain(_any: mingling::AnyOutput<MockCollect>) -> mingling::ChainProcess<MockCollect> {
- unimplemented!()
- }
- fn do_comp(_any: &mingling::AnyOutput<MockCollect>, _ctx: &ShellContext) -> Suggest {
- unimplemented!()
- }
- fn has_renderer(_any: &mingling::AnyOutput<MockCollect>) -> bool {
- unimplemented!()
- }
- fn has_chain(_any: &mingling::AnyOutput<MockCollect>) -> bool {
- unimplemented!()
- }
-}
-
#[test]
fn test_shell_context_parsing_full() {
let args = vec![
@@ -112,12 +64,13 @@ fn test_suggest_item_with_description() {
#[test]
fn test_program_is_completing() {
- let program: Program<MockCollect> = Program::new_with_args(["myapp", "__comp", "hello", ""]);
+ let program: Program<MockProgramCollect> =
+ Program::new_with_args(["myapp", "__comp", "hello", ""]);
assert!(program.is_completing());
}
#[test]
fn test_program_is_not_completing() {
- let program: Program<MockCollect> = Program::new_with_args(["myapp", "hello"]);
+ let program: Program<MockProgramCollect> = Program::new_with_args(["myapp", "hello"]);
assert!(!program.is_completing());
}
diff --git a/mingling_macros/src/dispatcher.rs b/mingling_macros/src/dispatcher.rs
index 7e973eb..6bf10f1 100644
--- a/mingling_macros/src/dispatcher.rs
+++ b/mingling_macros/src/dispatcher.rs
@@ -223,6 +223,7 @@ pub fn dispatcher(input: TokenStream) -> TokenStream {
::mingling::macros::node!(#command_name_str)
}
fn begin(&self, args: Vec<String>) -> ::mingling::ChainProcess<#program_path> {
+ use ::mingling::Groupped;
#pack::new(args).to_chain()
}
fn clone_dispatcher(&self) -> Box<dyn ::mingling::Dispatcher<#program_path>> {
diff --git a/mingling_macros/src/lib.rs b/mingling_macros/src/lib.rs
index 408450a..9880cd6 100644
--- a/mingling_macros/src/lib.rs
+++ b/mingling_macros/src/lib.rs
@@ -480,7 +480,7 @@ pub fn route(input: TokenStream) -> TokenStream {
#[proc_macro]
pub fn empty_result(_input: TokenStream) -> TokenStream {
let expanded = quote! {
- crate::ResultEmpty::new(()).to_chain()
+ <crate::ResultEmpty as ::mingling::Groupped::<crate::ThisProgram>>::to_chain(crate::ResultEmpty::new(()))
};
TokenStream::from(expanded)
}
@@ -1413,6 +1413,8 @@ pub fn program_comp_gen(input: TokenStream) -> TokenStream {
#[doc(hidden)]
#[::mingling::macros::chain(#name)]
pub async fn __exec_completion(prev: CompletionContext) -> Next {
+ use ::mingling::Groupped;
+
let read_ctx = ::mingling::ShellContext::try_from(prev.inner);
match read_ctx {
Ok(ctx) => {
@@ -1429,6 +1431,8 @@ pub fn program_comp_gen(input: TokenStream) -> TokenStream {
#[doc(hidden)]
#[::mingling::macros::chain(#name)]
pub fn __exec_completion(prev: CompletionContext) -> Next {
+ use ::mingling::Groupped;
+
let read_ctx = ::mingling::ShellContext::try_from(prev.inner);
match read_ctx {
Ok(ctx) => {
@@ -1452,6 +1456,7 @@ pub fn program_comp_gen(input: TokenStream) -> TokenStream {
#[doc(hidden)]
mod __internal_completion_mod {
use super::#name;
+ use ::mingling::Groupped;
::mingling::macros::dispatcher!(#name, "__comp", CMDCompletion => CompletionContext);
::mingling::macros::pack!(
#name,
diff --git a/mling/src/cli.rs b/mling/src/cli.rs
index 6dc7b9e..123cca3 100644
--- a/mling/src/cli.rs
+++ b/mling/src/cli.rs
@@ -8,7 +8,7 @@ use crate::{
};
use colored::Colorize;
use mingling::{
- Program,
+ Groupped, Program,
hook::ProgramHook,
macros::{chain, help, pack, program_setup, r_println, renderer},
res::ResExitCode,