aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md1
-rw-r--r--Cargo.lock6
-rw-r--r--Cargo.toml8
-rw-r--r--README.md1
-rw-r--r--docs/README.md1
-rw-r--r--docs/pages/2-basic/2-setup.md8
-rw-r--r--examples/example-async/Cargo.toml8
-rw-r--r--examples/example-async/src/main.rs53
-rw-r--r--mingling/src/example_docs.rs69
-rw-r--r--mingling_macros/src/program_setup.rs6
10 files changed, 152 insertions, 9 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index ea00cf1..ce51fec 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -15,6 +15,7 @@
1. Removed macro `dispatcher_render!` from `mingling_macros`
2. The `<..., Group>` in `Program<Collect, Group>` no longer requires `std::fmt::Display`
+3. Changed `Program<Collect, Group>` to `Program<Collect>` (merged the Group and Collect types)
---
diff --git a/Cargo.lock b/Cargo.lock
index 1787d82..3e81edc 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -129,7 +129,11 @@ dependencies = [
[[package]]
name = "example-async"
-version = "0.1.0"
+version = "0.0.1"
+dependencies = [
+ "mingling",
+ "tokio",
+]
[[package]]
name = "hashbrown"
diff --git a/Cargo.toml b/Cargo.toml
index ff3ca49..1b69a8f 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -4,10 +4,16 @@ version = "0.1.0"
edition = "2024"
[workspace]
-members = ["examples/example-async","mingling", "mingling_core", "mingling_macros"]
+members = [
+ "examples/example-async",
+ "mingling",
+ "mingling_core",
+ "mingling_macros",
+]
exclude = [
"mingling_cli",
"dev_tools",
+ "examples/example-async",
"examples/example-basic",
"examples/example-completion",
"examples/example-general-renderer",
diff --git a/README.md b/README.md
index eab4ee4..41d9f2b 100644
--- a/README.md
+++ b/README.md
@@ -134,6 +134,7 @@ The Mingling project consists of two main parts:
## Example Projects
- **[`examples/example-basic/`](examples/example-basic/src/main.rs)** - A simple "Hello, World!" example demonstrating the most basic usage of a Dispatcher and Renderer.
+- **[`examples/example-async/`](examples/example-async/src/main.rs)** - Based on `example-basic`, demonstrates how to integrate an async runtime
- **[`examples/example-picker/`](examples/example-picker/src/main.rs)** - Demonstrates how to use a Chain to process and transform command arguments.
- **[`examples/example-general-renderer/`](examples/example-general-renderer/src/main.rs)** - Shows how to use a general renderer for different data types (e.g., JSON, YAML, TOML, RON).
- **[`examples/example-completion/`](examples/example-completion/src/main.rs)** - An example implementing auto-completion for the shell.
diff --git a/docs/README.md b/docs/README.md
index 6dd9667..03e17dc 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -134,6 +134,7 @@ The Mingling project consists of two main parts:
## Example Projects
- **[`examples/example-basic/`](examples/example-basic/src/main.rs)** - A simple "Hello, World!" example demonstrating the most basic usage of a Dispatcher and Renderer.
+- **[`examples/example-async/`](examples/example-async/src/main.rs)** - Based on `example-basic`, demonstrates how to integrate an async runtime
- **[`examples/example-picker/`](examples/example-picker/src/main.rs)** - Demonstrates how to use a Chain to process and transform command arguments.
- **[`examples/example-general-renderer/`](examples/example-general-renderer/src/main.rs)** - Shows how to use a general renderer for different data types (e.g., JSON, YAML, TOML, RON).
- **[`examples/example-completion/`](examples/example-completion/src/main.rs)** - An example implementing auto-completion for the shell.
diff --git a/docs/pages/2-basic/2-setup.md b/docs/pages/2-basic/2-setup.md
index 97fbc5a..102e213 100644
--- a/docs/pages/2-basic/2-setup.md
+++ b/docs/pages/2-basic/2-setup.md
@@ -15,12 +15,12 @@ It is defined as follows:
```rust
struct MySetup;
-impl ProgramSetup<ThisProgram, ThisProgram>
+impl ProgramSetup<ThisProgram>
for MySetup
{
fn setup(
&mut self,
- program: &mut Program<ThisProgram, ThisProgram>
+ program: &mut Program<ThisProgram>
) {
// Your setup logic
}
@@ -89,7 +89,7 @@ If you find the above declaration method too **verbose**, you can use the `progr
```rust
#[program_setup]
fn my_setup(
- program: &mut Program<ThisProgram, ThisProgram>
+ program: &mut Program<ThisProgram>
) {
// Your setup logic
}
@@ -127,7 +127,7 @@ dispatcher!("member.rm",
#[program_setup]
fn my_setup(
- program: &mut Program<ThisProgram, ThisProgram>
+ program: &mut Program<ThisProgram>
) {
program.with_dispatcher(AddMemberCommand);
program.with_dispatcher(RemoveMemberCommand);
diff --git a/examples/example-async/Cargo.toml b/examples/example-async/Cargo.toml
new file mode 100644
index 0000000..0089520
--- /dev/null
+++ b/examples/example-async/Cargo.toml
@@ -0,0 +1,8 @@
+[package]
+name = "example-async"
+version = "0.0.1"
+edition = "2024"
+
+[dependencies]
+tokio = { version = "1", features = ["full"] }
+mingling = { path = "../../mingling", features = ["async"] }
diff --git a/examples/example-async/src/main.rs b/examples/example-async/src/main.rs
new file mode 100644
index 0000000..29aee7e
--- /dev/null
+++ b/examples/example-async/src/main.rs
@@ -0,0 +1,53 @@
+//! `Mingling` Example - Async
+//!
+//! After enabling the `async` feature:
+//! 1. The `chain!` macro will support using **async** functions,
+//! 2. The `exec` function of `Program` will return a `Future` for you to use with an async runtime
+//!
+//! ## Enable Feature
+//! Enable the `async` feature for mingling in `Cargo.toml`
+//! ```toml
+//! [dependencies]
+//! mingling = { version = "...", features = ["async"] }
+//! ```
+//!
+//! # How to Run
+//! ```bash
+//! cargo run --manifest-path ./examples/example-async/Cargo.toml -- hello World
+//! ```
+
+use mingling::{
+ macros::{chain, dispatcher, gen_program, pack, r_println, renderer},
+ marker::NextProcess,
+};
+
+dispatcher!("hello", HelloCommand => HelloEntry);
+
+// Use Tokio async runtime
+#[tokio::main]
+async fn main() {
+ let mut program = ThisProgram::new();
+ program.with_dispatcher(HelloCommand);
+
+ // Run program
+ program.exec().await;
+}
+
+pack!(Hello = String);
+
+// You can freely use async / non-async functions to declare your Chain
+
+#[chain]
+// fn parse_name(prev: HelloEntry) -> NextProcess {
+async fn parse_name(prev: HelloEntry) -> NextProcess {
+ let name = prev.first().cloned().unwrap_or_else(|| "World".to_string());
+ Hello::new(name).to_render()
+}
+
+// For renderers, you can still only use synchronous functions
+#[renderer]
+fn render_hello_who(prev: Hello) {
+ r_println!("Hello, {}!", *prev);
+}
+
+gen_program!();
diff --git a/mingling/src/example_docs.rs b/mingling/src/example_docs.rs
index 31a298f..519c5cc 100644
--- a/mingling/src/example_docs.rs
+++ b/mingling/src/example_docs.rs
@@ -65,6 +65,75 @@
/// gen_program!();
/// ```
pub mod example_basic {}
+/// `Mingling` Example - Async
+///
+/// After enabling the `async` feature:
+/// 1. The `chain!` macro will support using **async** functions,
+/// 2. The `exec` function of `Program` will return a `Future` for you to use with an async runtime
+///
+/// ## Enable Feature
+/// Enable the `async` feature for mingling in `Cargo.toml`
+/// ```toml
+/// [dependencies]
+/// mingling = { version = "...", features = ["async"] }
+/// ```
+///
+/// # How to Run
+/// ```bash
+/// cargo run --manifest-path ./examples/example-async/Cargo.toml -- hello World
+/// ```
+///
+/// Cargo.toml
+/// ```ignore
+/// [package]
+/// name = "example-async"
+/// version = "0.0.1"
+/// edition = "2024"
+///
+/// [dependencies]
+/// tokio = { version = "1", features = ["full"] }
+/// mingling = { path = "../../mingling", features = ["async"] }
+/// ```
+///
+/// main.rs
+/// ```ignore
+/// use mingling::{
+/// macros::{chain, dispatcher, gen_program, pack, r_println, renderer},
+/// marker::NextProcess,
+/// };
+///
+/// dispatcher!("hello", HelloCommand => HelloEntry);
+///
+/// // Use Tokio async runtime
+/// #[tokio::main]
+/// async fn main() {
+/// let mut program = ThisProgram::new();
+/// program.with_dispatcher(HelloCommand);
+///
+/// // Run program
+/// program.exec().await;
+/// }
+///
+/// pack!(Hello = String);
+///
+/// // You can freely use async / non-async functions to declare your Chain
+///
+/// #[chain]
+/// // fn parse_name(prev: HelloEntry) -> NextProcess {
+/// async fn parse_name(prev: HelloEntry) -> NextProcess {
+/// let name = prev.first().cloned().unwrap_or_else(|| "World".to_string());
+/// Hello::new(name).to_render()
+/// }
+///
+/// // For renderers, you can still only use synchronous functions
+/// #[renderer]
+/// fn render_hello_who(prev: Hello) {
+/// r_println!("Hello, {}!", *prev);
+/// }
+///
+/// gen_program!();
+/// ```
+pub mod example_async {}
/// `Mingling` Example - Completion
///
/// # How to Deploy
diff --git a/mingling_macros/src/program_setup.rs b/mingling_macros/src/program_setup.rs
index f68ea40..ee6f054 100644
--- a/mingling_macros/src/program_setup.rs
+++ b/mingling_macros/src/program_setup.rs
@@ -1,6 +1,6 @@
//! Setup Attribute Macro Implementation
//!
-//! This module provides the `#[setup]` attribute macro for automatically
+//! This module provides the `#[program_setup]` attribute macro for automatically
//! generating structs that implement the `ProgramSetup` trait from functions.
use proc_macro::TokenStream;
@@ -53,7 +53,7 @@ fn extract_return_type(sig: &Signature) -> syn::Result<()> {
}
pub fn setup_attr(attr: TokenStream, item: TokenStream) -> TokenStream {
- // Parse the attribute arguments (e.g., MyProgram from #[setup(MyProgram)])
+ // Parse the attribute arguments (e.g., MyProgram from #[program_setup(MyProgram)])
// If no argument is provided, use ThisProgram
let (program_name, use_crate_prefix) = if attr.is_empty() {
(
@@ -91,7 +91,7 @@ pub fn setup_attr(attr: TokenStream, item: TokenStream) -> TokenStream {
// Get function attributes (excluding the setup attribute)
let mut fn_attrs = input_fn.attrs.clone();
- // Remove any #[setup(...)] attributes to avoid infinite recursion
+ // Remove any #[program_setup(...)] attributes to avoid infinite recursion
fn_attrs.retain(|attr| !attr.path().is_ident("setup"));
// Get function visibility