aboutsummaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
author魏曹先生 <1992414357@qq.com>2026-08-17 05:49:19 +0800
committer魏曹先生 <1992414357@qq.com>2026-08-17 05:49:19 +0800
commit57c53affe3542cb6bd4e79ee4c18f20a1bd76b2d (patch)
tree1cd4aef44cb7a45a8cd9d520b598f5f181e24c76 /examples
parentef23cd944402939605c78a4a853ef6e33af02c21 (diff)
refactor!: replace pack! macros with derive-based pipeline types
Remove the `pack!`, `pack_err!`, `pack_structural!`, and `pack_err_structural!` macros, replacing all pipeline type definitions with `#[derive(Grouped)]` and `#[derive(Grouped, Wrap)]` attributes. This changes the generated struct shape from named-field structs with an `inner` field to tuple structs accessed via `.0`, and removes the auto-generated `name` and `info` fields from error types.
Diffstat (limited to 'examples')
-rw-r--r--examples/example-argument-picker/src/main.rs69
-rw-r--r--examples/example-async-support/src/main.rs5
-rw-r--r--examples/example-basic/src/main.rs25
-rw-r--r--examples/example-combine-pathf-dispatch-tree/src/sub/mod.rs5
-rw-r--r--examples/example-combine-pathf-metadata/src/sub/mod.rs12
-rw-r--r--examples/example-command-macro/src/main.rs13
-rw-r--r--examples/example-completion/src/main.rs5
-rw-r--r--examples/example-error-handling/src/main.rs31
-rw-r--r--examples/example-exitcode/src/main.rs13
-rw-r--r--examples/example-hook/src/main.rs5
-rw-r--r--examples/example-lazy-resources/src/main.rs3
-rw-r--r--examples/example-metadata/src/main.rs13
-rw-r--r--examples/example-outside-type/src/main.rs7
-rw-r--r--examples/example-pack-err/Cargo.lock235
-rw-r--r--examples/example-pack-err/Cargo.toml16
-rw-r--r--examples/example-pack-err/page.toml10
-rw-r--r--examples/example-pack-err/src/main.rs151
-rw-r--r--examples/example-pack-err/test.toml35
-rw-r--r--examples/example-panic-unwind/src/main.rs6
-rw-r--r--examples/example-pathfinder/src/sub/mod.rs6
-rw-r--r--examples/example-repl-basic/src/main.rs26
-rw-r--r--examples/example-setup/src/main.rs5
-rw-r--r--examples/example-structural-renderer/src/main.rs5
-rw-r--r--examples/example-unit-test/src/main.rs41
-rw-r--r--examples/full-todolist/src/main.rs36
25 files changed, 191 insertions, 587 deletions
diff --git a/examples/example-argument-picker/src/main.rs b/examples/example-argument-picker/src/main.rs
index 99eee30..aefb86e 100644
--- a/examples/example-argument-picker/src/main.rs
+++ b/examples/example-argument-picker/src/main.rs
@@ -44,17 +44,32 @@ use mingling::setup::picker::BasicProgramSetup;
dispatcher!("calc", EntryCalculate);
-pack_err!(ErrorNumberANotProvided);
-pack_err!(ErrorNumberBNotProvided);
-pack_err!(ErrorNumberOperatorNotProvided);
-pack_err!(ErrorDivisionByZero);
+#[derive(Grouped, Default)]
+pub struct ErrorNumberANotProvided;
-pack!(StateAdd = (f32, f32));
-pack!(StateSubtract = (f32, f32));
-pack!(StateMultiply = (f32, f32));
-pack!(StateDivide = (f32, f32));
+#[derive(Grouped, Default)]
+pub struct ErrorNumberBNotProvided;
-pack!(ResultNumber = f32);
+#[derive(Grouped, Default)]
+pub struct ErrorNumberOperatorNotProvided;
+
+#[derive(Grouped, Default)]
+pub struct ErrorDivisionByZero;
+
+#[derive(Grouped, Wrap)]
+pub struct StateAdd((f32, f32));
+
+#[derive(Grouped, Wrap)]
+pub struct StateSubtract((f32, f32));
+
+#[derive(Grouped, Wrap)]
+pub struct StateMultiply((f32, f32));
+
+#[derive(Grouped, Wrap)]
+pub struct StateDivide((f32, f32));
+
+#[derive(Grouped, Wrap)]
+pub struct ResultNumber(f32);
#[derive(Grouped)]
struct StateCalculate {
@@ -135,13 +150,13 @@ fn handle_calc(args: EntryCalculate) -> Next {
// Use the arg! macro to define a positional argument of type f32
// |
// vvvvvvvvvv
- args.pick_or_route(&arg![f32], || ErrorNumberANotProvided::default().to_chain())
+ args.pick_or_route(&arg![f32], || ErrorNumberANotProvided.to_chain())
.pick_or_route(&arg![Operator], || {
- ErrorNumberOperatorNotProvided::default().to_chain()
+ ErrorNumberOperatorNotProvided.to_chain()
}) // Returns a routable type when not found or fails to parse
// |
- // vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
- .pick_or_route(&arg![f32], || ErrorNumberBNotProvided::default().to_chain())
+ // vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
+ .pick_or_route(&arg![f32], || ErrorNumberBNotProvided.to_chain())
// Use `to_result` to parse arguments
// and convert to Result<(Tuple, ...), Route> type
.to_result()
@@ -149,7 +164,7 @@ fn handle_calc(args: EntryCalculate) -> Next {
// --------- IMPORTANT ---------
if operator == Operator::Slash && number_b == 0. {
- return ErrorDivisionByZero::default().to_chain();
+ return ErrorDivisionByZero.to_chain();
}
StateCalculate {
@@ -163,41 +178,41 @@ fn handle_calc(args: EntryCalculate) -> Next {
#[chain]
fn handle_state_calculate(state: StateCalculate) -> Next {
match (state.operator, state.number_a, state.number_b) {
- (Operator::Plus, a, b) => StateAdd::new((a, b)).to_chain(),
- (Operator::Dash, a, b) => StateSubtract::new((a, b)).to_chain(),
- (Operator::Slash, a, b) => StateDivide::new((a, b)).to_chain(),
- (Operator::Star, a, b) => StateMultiply::new((a, b)).to_chain(),
+ (Operator::Plus, a, b) => StateAdd((a, b)).to_chain(),
+ (Operator::Dash, a, b) => StateSubtract((a, b)).to_chain(),
+ (Operator::Slash, a, b) => StateDivide((a, b)).to_chain(),
+ (Operator::Star, a, b) => StateMultiply((a, b)).to_chain(),
}
}
#[chain]
fn handle_state_add(state_add: StateAdd) -> ResultNumber {
- let (a, b) = state_add.inner;
- ResultNumber::new(a + b)
+ let (a, b) = state_add.0;
+ ResultNumber(a + b)
}
#[chain]
fn handle_state_subtract(state_subtract: StateSubtract) -> ResultNumber {
- let (a, b) = state_subtract.inner;
- ResultNumber::new(a - b)
+ let (a, b) = state_subtract.0;
+ ResultNumber(a - b)
}
#[chain]
fn handle_state_multiply(state_multiply: StateMultiply) -> ResultNumber {
- let (a, b) = state_multiply.inner;
- ResultNumber::new(a * b)
+ let (a, b) = state_multiply.0;
+ ResultNumber(a * b)
}
#[chain]
fn handle_state_divide(state_divide: StateDivide) -> ResultNumber {
- let (a, b) = state_divide.inner;
- ResultNumber::new(a / b)
+ let (a, b) = state_divide.0;
+ ResultNumber(a / b)
}
#[renderer]
fn render_result_number(result: ResultNumber, setting: &ResNumberDisplaySetting) -> String {
let round = setting.round;
- let result = if round { result.round() } else { result.inner };
+ let result = if round { result.round() } else { result.0 };
format!("Result: {}", result)
}
diff --git a/examples/example-async-support/src/main.rs b/examples/example-async-support/src/main.rs
index 090602a..7e212d9 100644
--- a/examples/example-async-support/src/main.rs
+++ b/examples/example-async-support/src/main.rs
@@ -41,7 +41,8 @@ async fn main() {
dispatcher!("download", EntryDownload);
-pack!(ResultDownloaded = String);
+#[derive(Grouped, Wrap)]
+pub struct ResultDownloaded(String);
// --------- IMPORTANT ---------
#[chain]
@@ -65,5 +66,5 @@ gen_program!();
async fn fake_download(file_name: String) -> ResultDownloaded {
tokio::time::sleep(std::time::Duration::from_secs(1)).await;
- ResultDownloaded::new(file_name)
+ ResultDownloaded(file_name)
}
diff --git a/examples/example-basic/src/main.rs b/examples/example-basic/src/main.rs
index 44736ad..ce41b2d 100644
--- a/examples/example-basic/src/main.rs
+++ b/examples/example-basic/src/main.rs
@@ -17,11 +17,11 @@ use mingling::prelude::*;
use std::io::Write;
// Define the `greet` subcommand
-// _____________________________ subcmd name, can be nested (e.g. "remote.add" "remote.rm")
-// / _____________________ dispatcher name
-// | / _________ entry, records raw arguments
-// | | / ^^^^^^^^^^^^^
-// vvvvv vvvvvvvv vvvvvvvvvv \_ equivalent to pack!(EntryGreet = Vec<String>)
+// _________________ subcmd name, can be nested (e.g. "remote.add" "remote.rm")
+// /
+// | _________ entry, records raw arguments
+// | / ^^^^^^^^^^^^^
+// vvvvv vvvvvvvvvv \_ a newtype wrapper around Vec<String>
dispatcher!("greet", EntryGreet);
fn main() {
@@ -33,21 +33,22 @@ fn main() {
}
// Quickly wrap a type into a type recognizable by the current program
-// ____________________ Wrapped type name
-// / _______ Wrapped type inner value
-// | /
-// vvvvvvvvvv vvvvvv
-pack!(ResultName = String);
+// ___________________ Registers this type into ThisProgram
+// / _______ Adds DerefMut, Deref, Into, From wrappers
+// | /
+// vvvvvvvvvv vvvvv
+#[derive(Grouped, Wrap)]
+pub struct ResultName(String);
// Define the `handle_greet` chain for parsing input text
// ____________________ Previous type:
// / Mingling deduces types at runtime and routes them to this function
// | _____ will be expanded to:
-// | / impl Into<mingling::ChainProcess<ThisProgram>>
+// | / ChainProcess<ThisProgram>
#[chain] // vvvvvvvvvv vvvv
fn handle_greet(args: EntryGreet) -> Next {
let name: ResultName = args
- .inner
+ .0
.first()
.cloned()
.unwrap_or_else(|| "World".to_string())
diff --git a/examples/example-combine-pathf-dispatch-tree/src/sub/mod.rs b/examples/example-combine-pathf-dispatch-tree/src/sub/mod.rs
index 2b7aba9..b04c683 100644
--- a/examples/example-combine-pathf-dispatch-tree/src/sub/mod.rs
+++ b/examples/example-combine-pathf-dispatch-tree/src/sub/mod.rs
@@ -4,12 +4,13 @@ use std::io::Write;
dispatcher!("hello");
-pack!(ResultMessage = String);
+#[derive(Grouped, Wrap)]
+pub struct ResultMessage(String);
#[chain]
pub fn handle_my(args: EntryHello) -> Next {
let name: ResultMessage = args
- .inner
+ .0
.first()
.cloned()
.unwrap_or_else(|| "World".to_string())
diff --git a/examples/example-combine-pathf-metadata/src/sub/mod.rs b/examples/example-combine-pathf-metadata/src/sub/mod.rs
index ba56285..38efa2f 100644
--- a/examples/example-combine-pathf-metadata/src/sub/mod.rs
+++ b/examples/example-combine-pathf-metadata/src/sub/mod.rs
@@ -7,6 +7,7 @@ use std::io::Write;
// Implicit dispatcher form — creates `CMDHello` / `EntryHello` in this module
dispatcher!("hello");
+
// Creates `CMDDescription` / `EntryDescription` in this module
dispatcher!("desc", EntryDescription);
@@ -27,14 +28,17 @@ pub fn hello_desc() -> Description {
}
}
-pack!(ResultName = String);
-pack!(DescResult = String);
+#[derive(Grouped, Wrap)]
+pub struct ResultName(String);
+
+#[derive(Grouped, Wrap)]
+pub struct DescResult(String);
/// Chain for `hello` — reads the name and produces a `ResultName`.
#[chain]
pub fn handle_hello(args: EntryHello) -> Next {
let name: ResultName = args
- .inner
+ .0
.first()
.cloned()
.unwrap_or_else(|| "World".to_string())
@@ -51,7 +55,7 @@ pub fn handle_desc(_args: EntryDescription) -> Next {
None => "EntryHello has no description".to_string(),
};
// --------- IMPORTANT ---------
- DescResult::new(msg).to_render()
+ DescResult(msg).to_render()
}
/// Renders the greeting message with the provided name.
diff --git a/examples/example-command-macro/src/main.rs b/examples/example-command-macro/src/main.rs
index e525098..6740518 100644
--- a/examples/example-command-macro/src/main.rs
+++ b/examples/example-command-macro/src/main.rs
@@ -22,27 +22,30 @@ fn main() {
ThisProgram::new().exec_and_exit();
}
-pack!(ResultGreeting = String);
-pack!(ResultGoodbye = ());
+#[derive(Grouped, Wrap)]
+pub struct ResultGreeting(String);
+
+#[derive(Grouped)]
+pub struct ResultGoodbye;
// --------- IMPORTANT ---------
// Auto-generates dispatcher!("hello.world", EntryHelloWorld);
#[command]
fn hello_world() -> ResultGreeting {
- ResultGreeting::new("World".to_string())
+ ResultGreeting("World".to_string())
}
// Auto-generates dispatcher!("hello-world", EntryGreetSomeone);
#[command(node = "greet-someone")]
fn greet_someone(args: Vec<String>) -> ResultGreeting {
let name = args.pick_or(&arg![String], || "World".to_string()).unwrap();
- ResultGreeting::new(name)
+ ResultGreeting(name)
}
// Auto-generates dispatcher!("goodbye", EntryGoodBye);
#[command(entry = EntryGoodBye)]
fn goodbye() -> ResultGoodbye {
- ResultGoodbye::default()
+ ResultGoodbye
}
// --------- IMPORTANT ---------
diff --git a/examples/example-completion/src/main.rs b/examples/example-completion/src/main.rs
index d363697..e14326f 100644
--- a/examples/example-completion/src/main.rs
+++ b/examples/example-completion/src/main.rs
@@ -101,7 +101,8 @@ fn complete_greet_entry(ctx: &ShellContext) -> Suggest {
// --------- IMPORTANT ---------
dispatcher!("greet", EntryGreet);
-pack!(ResultName = (u8, String));
+#[derive(Grouped, Wrap)]
+pub struct ResultName((u8, String));
#[chain]
fn handle_greet(args: EntryGreet) -> Next {
@@ -116,7 +117,7 @@ fn handle_greet(args: EntryGreet) -> Next {
/// Renders the greeting with the result name and repeat count.
#[renderer]
fn render_name(result: ResultName) -> RenderResult {
- let (repeat, name) = result.inner;
+ let (repeat, name) = result.0;
let mut render_result = RenderResult::new();
let mut parts = Vec::with_capacity(repeat as usize);
for _ in 0..repeat {
diff --git a/examples/example-error-handling/src/main.rs b/examples/example-error-handling/src/main.rs
index 05b451b..ec7e6c9 100644
--- a/examples/example-error-handling/src/main.rs
+++ b/examples/example-error-handling/src/main.rs
@@ -29,35 +29,41 @@ use std::io::Write;
dispatcher!("hello", EntryHello);
// Define error types
-pack!(ErrorNoNameProvided = ());
-pack!(ErrorNameTooLong = u16);
-pack!(ErrorNameNotAvailable = ());
+#[derive(Grouped)]
+pub struct ErrorNoNameProvided;
+
+#[derive(Grouped, Wrap)]
+pub struct ErrorNameTooLong(u16);
+
+#[derive(Grouped)]
+pub struct ErrorNameNotAvailable;
// Define success type
-pack!(ResultName = String);
+#[derive(Grouped, Wrap)]
+pub struct ResultName(String);
// Pre-registered names
static VEC_REGISTERED_NAMES: &[&str] = &["Alice", "Bob", "Charlie", "David", "Eve"];
#[chain]
fn handle_hello(args: EntryHello) -> Next {
- let Some(name) = args.inner.first().cloned() else {
+ let Some(name) = args.0.first().cloned() else {
// If no name is provided, pass ErrorNoNameProvided
- return ErrorNoNameProvided::default().to_render();
+ return ErrorNoNameProvided.to_render();
};
if name.len() > 10 {
// If the name is too long, pass ErrorNameTooLong
- return ErrorNameTooLong::new(name.len() as u16).to_render();
+ return ErrorNameTooLong(name.len() as u16).to_render();
}
if VEC_REGISTERED_NAMES.contains(&name.as_str()) {
// If the name already exists, pass ErrorNameNotAvailable
- return ErrorNameNotAvailable::default().to_render();
+ return ErrorNameNotAvailable.to_render();
}
// If the name is valid, pass ResultName
- ResultName::new(name).to_render()
+ ResultName(name).to_render()
}
/// Renders a successful greeting with the given name.
@@ -96,12 +102,7 @@ fn render_error_name_too_long(len: ErrorNameTooLong) -> RenderResult {
#[renderer]
fn render_entry_fallback(err: EntryFallback) -> RenderResult {
let mut render_result = RenderResult::new();
- writeln!(
- render_result,
- "Command not found: \"{}\"",
- err.inner.join(" ")
- )
- .ok();
+ writeln!(render_result, "Command not found: \"{}\"", err.0.join(" ")).ok();
render_result
}
diff --git a/examples/example-exitcode/src/main.rs b/examples/example-exitcode/src/main.rs
index d3e035e..c7f731d 100644
--- a/examples/example-exitcode/src/main.rs
+++ b/examples/example-exitcode/src/main.rs
@@ -36,18 +36,21 @@ fn main() {
dispatcher!("hello", EntryHello);
-pack!(ErrorNoNameProvided = ());
-pack!(ResultName = String);
+#[derive(Grouped)]
+pub struct ErrorNoNameProvided;
+
+#[derive(Grouped, Wrap)]
+pub struct ResultName(String);
#[chain]
fn handle_hello(args: EntryHello) -> Next {
- let Some(name) = args.inner.first().cloned() else {
+ let Some(name) = args.0.first().cloned() else {
// If no name is provided, pass ErrorNoNameProvided
- return ErrorNoNameProvided::default().to_render();
+ return ErrorNoNameProvided.to_render();
};
// If the name is valid, pass ResultName
- ResultName::new(name).to_render()
+ ResultName(name).to_render()
}
/// Renders a successful greeting with the given name.
diff --git a/examples/example-hook/src/main.rs b/examples/example-hook/src/main.rs
index 1807e5e..721cea0 100644
--- a/examples/example-hook/src/main.rs
+++ b/examples/example-hook/src/main.rs
@@ -53,12 +53,13 @@ fn main() {
program.exec_and_exit();
}
-pack!(ResultName = String);
+#[derive(Grouped, Wrap)]
+pub struct ResultName(String);
#[chain]
fn handle_greet(args: EntryGreet) -> Next {
let name: ResultName = args
- .inner
+ .0
.first()
.cloned()
.unwrap_or_else(|| "World".to_string())
diff --git a/examples/example-lazy-resources/src/main.rs b/examples/example-lazy-resources/src/main.rs
index cc1604a..2243f14 100644
--- a/examples/example-lazy-resources/src/main.rs
+++ b/examples/example-lazy-resources/src/main.rs
@@ -52,7 +52,8 @@ fn init_res_large_data() -> ResLargeData {
dispatcher!("show", EntryShow);
dispatcher!("none", EntryNone);
-pack!(ResultShow = BTreeMap<Key, Value>);
+#[derive(Grouped, Wrap)]
+pub struct ResultShow(BTreeMap<Key, Value>);
fn main() {
let mut program = ThisProgram::new();
diff --git a/examples/example-metadata/src/main.rs b/examples/example-metadata/src/main.rs
index 94facb4..99a8aae 100644
--- a/examples/example-metadata/src/main.rs
+++ b/examples/example-metadata/src/main.rs
@@ -56,14 +56,17 @@ pub fn greet_desc() -> Description {
}
// --------- IMPORTANT ---------
-pack!(ResultName = String);
-pack!(DescResult = String);
+#[derive(Grouped, Wrap)]
+pub struct ResultName(String);
+
+#[derive(Grouped, Wrap)]
+pub struct DescResult(String);
/// Chain for `greet` — reads the name and produces a `ResultName`.
#[chain]
fn handle_greet(args: EntryGreet) -> Next {
let name: ResultName = args
- .inner
+ .0
.first()
.cloned()
.unwrap_or_else(|| "World".to_string())
@@ -81,7 +84,7 @@ fn handle_desc(_args: EntryDescription) -> Next {
None => "EntryGreet has no description".to_string(),
};
// --------- IMPORTANT ---------
- DescResult::new(msg).to_render()
+ DescResult(msg).to_render()
}
/// Chain for `nodoc` — asks for metadata on an entry that has none.
@@ -94,7 +97,7 @@ fn handle_nodoc(_args: EntryNoDescription) -> Next {
None => "EntryDescription has no description".to_string(),
};
// --------- IMPORTANT ---------
- DescResult::new(msg).to_render()
+ DescResult(msg).to_render()
}
/// Renders the greeting message with the provided name.
diff --git a/examples/example-outside-type/src/main.rs b/examples/example-outside-type/src/main.rs
index a04727f..8721d9a 100644
--- a/examples/example-outside-type/src/main.rs
+++ b/examples/example-outside-type/src/main.rs
@@ -43,7 +43,8 @@ group!(ErrorIo = std::io::Error);
// you can use this syntax to create an alias simultaneously
// --------- IMPORTANT ---------
-pack!(ParsedNumber = i32);
+#[derive(Grouped, Wrap)]
+pub struct ParsedNumber(i32);
/// Parse the first argument as an `i32`
///
@@ -51,9 +52,9 @@ pack!(ParsedNumber = i32);
/// On failure, routes to `render_parse_error` via the registered outside type.
#[chain]
fn parse_number(args: EntryParse) -> Next {
- let input = args.inner.first().cloned().unwrap_or_default();
+ let input = args.0.first().cloned().unwrap_or_default();
match input.parse::<i32>() {
- Ok(num) => ParsedNumber::new(num).to_chain(),
+ Ok(num) => ParsedNumber(num).to_chain(),
Err(e) => e.to_chain(),
}
}
diff --git a/examples/example-pack-err/Cargo.lock b/examples/example-pack-err/Cargo.lock
deleted file mode 100644
index bcfbb41..0000000
--- a/examples/example-pack-err/Cargo.lock
+++ /dev/null
@@ -1,235 +0,0 @@
-# This file is automatically @generated by Cargo.
-# It is not intended for manual editing.
-version = 4
-
-[[package]]
-name = "equivalent"
-version = "1.0.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
-
-[[package]]
-name = "example-pack-err"
-version = "0.1.0"
-dependencies = [
- "mingling",
- "serde",
-]
-
-[[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 = "itoa"
-version = "1.0.18"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682"
-
-[[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.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "88904434abc2901f197fe8cc55f0445e7ded921dba5911dad2e2b39b48e663c4"
-
-[[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",
-]
-
-[[package]]
-name = "mingling"
-version = "0.5.0"
-dependencies = [
- "mingling_core",
- "mingling_macros",
- "serde",
-]
-
-[[package]]
-name = "mingling_core"
-version = "0.5.0"
-dependencies = [
- "just_fmt",
- "might_be_async",
- "serde",
- "serde_json",
-]
-
-[[package]]
-name = "mingling_macros"
-version = "0.5.0"
-dependencies = [
- "just_fmt",
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "proc-macro2"
-version = "1.0.106"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
-dependencies = [
- "unicode-ident",
-]
-
-[[package]]
-name = "quote"
-version = "1.0.46"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dfbc457d0c7a0759a614551b11a6409e5951f6c7537be1f1b7682b9ae9230368"
-dependencies = [
- "proc-macro2",
-]
-
-[[package]]
-name = "serde"
-version = "1.0.228"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
-dependencies = [
- "serde_core",
- "serde_derive",
-]
-
-[[package]]
-name = "serde_core"
-version = "1.0.228"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
-dependencies = [
- "serde_derive",
-]
-
-[[package]]
-name = "serde_derive"
-version = "1.0.228"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "serde_json"
-version = "1.0.150"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9"
-dependencies = [
- "itoa",
- "memchr",
- "serde",
- "serde_core",
- "zmij",
-]
-
-[[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"
-checksum = "1b9ae57f904213ebb649ce6895b8a66c66f0203b9319718f69a5612a065b1422"
-dependencies = [
- "proc-macro2",
- "quote",
- "unicode-ident",
-]
-
-[[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",
-]
-
-[[package]]
-name = "zmij"
-version = "1.0.21"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa"
diff --git a/examples/example-pack-err/Cargo.toml b/examples/example-pack-err/Cargo.toml
deleted file mode 100644
index ddab6fd..0000000
--- a/examples/example-pack-err/Cargo.toml
+++ /dev/null
@@ -1,16 +0,0 @@
-[package]
-name = "example-pack-err"
-version = "0.1.0"
-edition = "2024"
-
-[dependencies]
-serde = { version = "1.0.228", features = ["derive"] }
-
-[dependencies.mingling]
-path = "../../mingling"
-features = [
- "structural_renderer",
- "extras",
-]
-
-[workspace]
diff --git a/examples/example-pack-err/page.toml b/examples/example-pack-err/page.toml
deleted file mode 100644
index 7423087..0000000
--- a/examples/example-pack-err/page.toml
+++ /dev/null
@@ -1,10 +0,0 @@
-[example]
-id = "example-pack-err"
-name = "Pack an Error"
-icon = "🛑"
-category = "macros"
-desc = """
-Demonstrates how to use the `pack_err!` macro to define error types with automatic `name` field (snake_case at compile time) and optional `info` field. Also shows `--json` serialization when `structural_renderer` is enabled.
-"""
-tags = ["pack_err!", "extras", "structural_renderer", "--json"]
-files = ["src/main.rs", "Cargo.toml"]
diff --git a/examples/example-pack-err/src/main.rs b/examples/example-pack-err/src/main.rs
deleted file mode 100644
index e30e4cb..0000000
--- a/examples/example-pack-err/src/main.rs
+++ /dev/null
@@ -1,151 +0,0 @@
-//! Example `pack_err!`
-//!
-//! > This example demonstrates how to use the `pack_err!` macro to define error types
-//! > with automatic `name` field (set to snake_case at compile time) and optional `info` field.
-//! > Also demonstrates `--json` serialization when `structural_renderer` is enabled.
-//!
-//! Run:
-//! ```bash
-//! cargo run --manifest-path examples/example-pack-err/Cargo.toml --quiet -- find
-//! cargo run --manifest-path examples/example-pack-err/Cargo.toml --quiet -- find Cargo.toml
-//! cargo run --manifest-path examples/example-pack-err/Cargo.toml --quiet -- find src
-//! cargo run --manifest-path examples/example-pack-err/Cargo.toml --quiet -- find-structural --json
-//! cargo run --manifest-path examples/example-pack-err/Cargo.toml --quiet -- find-structural Cargo.toml --json
-//! cargo run --manifest-path examples/example-pack-err/Cargo.toml --quiet -- find-structural src --json
-//! ```
-//!
-//! Output:
-//! ```plaintext
-//! Search path not provided
-//! Not a directory: Cargo.toml
-//! Found directory: src
-//! {"name":"error_not_found"}
-//! {"name":"error_not_dir","info":"Cargo.toml"}
-//! {"inner":"src"}
-//! {"name":"error_not_found_structural"}
-//! {"name":"error_not_dir_structural","info":"Cargo.toml"}
-//! ```
-
-use mingling::prelude::*;
-use mingling::setup::StructuralRendererSetup;
-use std::io::Write;
-use std::path::PathBuf;
-
-dispatcher!("find", EntryFind);
-dispatcher!("find-structural", EntryFindStructural);
-
-// --------- IMPORTANT ---------
-// `pack_err!` is a convenient macro for defining error types.
-//
-// Simple form: pack_err!(ErrorNotFound);
-// Typed form: pack_err!(ErrorNotDir = PathBuf);
-//
-// The simple form generates a struct with `name: String` and `impl Default`.
-// name = "error_not_found" (automatically snake_cased at compile time)
-//
-// The typed form additionally generates `pub fn new(info)`.
-// name = "error_not_dir"
-//
-// When `structural_renderer` is enabled, the struct also gets
-// `#[derive(serde::Serialize)]` for --json / --yaml output.
-// --------- IMPORTANT ---------
-
-// Simple form — name = "error_not_found"
-pack_err!(ErrorNotFound);
-
-// Typed form — name = "error_not_dir"
-pack_err!(ErrorNotDir = PathBuf);
-
-// Simple form — with StructuralData support for --json / --yaml
-pack_err_structural!(ErrorNotFoundStructural);
-
-// Typed form — with StructuralData support for --json / --yaml
-pack_err_structural!(ErrorNotDirStructural = PathBuf);
-
-// Success type with StructuralData support
-pack_structural!(ResultPath = PathBuf);
-
-#[chain]
-fn handle_find(args: EntryFind) -> Next {
- let Some(path_str) = args.inner.first().cloned() else {
- // No path provided → use the simple error form (Default)
- return ErrorNotFound::default().to_render();
- };
-
- let path = PathBuf::from(&path_str);
- if path.is_dir() {
- // Is a directory → success
- ResultPath::new(path).to_render()
- } else {
- // Not a directory (or doesn't exist) → use the typed error form
- ErrorNotDir::new(path).to_render()
- }
-}
-
-#[chain]
-fn handle_find_structural(args: EntryFindStructural) -> Next {
- let Some(path_str) = args.inner.first().cloned() else {
- // No path provided → use the simple error form (Default)
- return ErrorNotFoundStructural::default().to_render();
- };
-
- let path = PathBuf::from(&path_str);
- if path.is_dir() {
- // Is a directory → success
- ResultPath::new(path).to_render()
- } else {
- // Not a directory (or doesn't exist) → use the typed error form
- ErrorNotDirStructural::new(path).to_render()
- }
-}
-
-/// Renders the successful result with the found directory path.
-#[renderer]
-fn render_result_path(path: ResultPath) -> RenderResult {
- let mut render_result = RenderResult::new();
- writeln!(render_result, "Found directory: {}", path.display()).ok();
- render_result
-}
-
-/// Renders the error when no search path is provided.
-#[renderer]
-fn render_error_not_found(_: ErrorNotFound) -> RenderResult {
- let mut render_result = RenderResult::new();
- writeln!(render_result, "Search path not provided").ok();
- render_result
-}
-
-/// Renders the error when the given path is not a directory.
-#[renderer]
-fn render_error_not_dir(err: ErrorNotDir) -> RenderResult {
- let mut render_result = RenderResult::new();
- writeln!(render_result, "Not a directory: {}", err.info.display()).ok();
- render_result
-}
-
-/// Renders the structural error when no search path is provided.
-#[renderer]
-fn render_error_not_found_structural(_: ErrorNotFoundStructural) -> RenderResult {
- let mut render_result = RenderResult::new();
- writeln!(render_result, "Search path not provided").ok();
- render_result
-}
-
-/// Renders the structural error when the given path is not a directory.
-#[renderer]
-fn render_error_not_dir_structural(err: ErrorNotDirStructural) -> RenderResult {
- let mut render_result = RenderResult::new();
- writeln!(render_result, "Not a directory: {}", err.info.display()).ok();
- render_result
-}
-
-gen_program!();
-
-fn main() {
- let mut program = ThisProgram::new();
-
- // Add StructuralRendererSetup to support --json / --yaml flags
- program.with_setup(StructuralRendererSetup);
-
- let _ = program.exec();
-}
diff --git a/examples/example-pack-err/test.toml b/examples/example-pack-err/test.toml
deleted file mode 100644
index c4509cb..0000000
--- a/examples/example-pack-err/test.toml
+++ /dev/null
@@ -1,35 +0,0 @@
-[[runs]]
-input = [ "find" ]
-
-expect.exit-code = 0
-expect.result = "Search path not provided"
-
-[[runs]]
-input = [ "find", "Cargo.toml" ]
-
-expect.exit-code = 0
-expect.result = "Not a directory: Cargo.toml"
-
-[[runs]]
-input = [ "find", "examples" ]
-
-expect.exit-code = 0
-expect.result = "Found directory: examples"
-
-[[runs]]
-input = [ "find-structural", "--json" ]
-
-expect.exit-code = 0
-expect.result = "{\"name\":\"error_not_found_structural\"}"
-
-[[runs]]
-input = [ "find-structural", "Cargo.toml", "--json" ]
-
-expect.exit-code = 0
-expect.result = "{\"name\":\"error_not_dir_structural\",\"info\":\"Cargo.toml\"}"
-
-[[runs]]
-input = [ "find-structural", "examples", "--json" ]
-
-expect.exit-code = 0
-expect.result = "{\"inner\":\"examples\"}"
diff --git a/examples/example-panic-unwind/src/main.rs b/examples/example-panic-unwind/src/main.rs
index 59adf07..f91b0f0 100644
--- a/examples/example-panic-unwind/src/main.rs
+++ b/examples/example-panic-unwind/src/main.rs
@@ -20,7 +20,9 @@ use mingling::{hook::ProgramHook, prelude::*};
use std::io::Write;
dispatcher!("panic", EntryPanic);
-pack!(NotPanic = ());
+
+#[derive(Grouped)]
+pub struct NotPanic;
fn main() {
let mut program = ThisProgram::new();
@@ -47,7 +49,7 @@ fn handle_panic(prev: EntryPanic) -> Next {
// Panic happens here, will be caught
panic!("{}", s)
}
- None => NotPanic::default().into(),
+ None => NotPanic.into(),
}
}
diff --git a/examples/example-pathfinder/src/sub/mod.rs b/examples/example-pathfinder/src/sub/mod.rs
index cf0a97a..b90c618 100644
--- a/examples/example-pathfinder/src/sub/mod.rs
+++ b/examples/example-pathfinder/src/sub/mod.rs
@@ -3,12 +3,14 @@ use mingling::prelude::*;
use std::io::Write;
dispatcher!("greet", EntryGreet);
-pack!(ResultName = String);
+
+#[derive(Grouped, Wrap)]
+pub struct ResultName(String);
#[chain]
pub fn handle_greet(args: EntryGreet) -> Next {
let name: ResultName = args
- .inner
+ .0
.first()
.cloned()
.unwrap_or_else(|| "World".to_string())
diff --git a/examples/example-repl-basic/src/main.rs b/examples/example-repl-basic/src/main.rs
index d0fad6d..9b81ced 100644
--- a/examples/example-repl-basic/src/main.rs
+++ b/examples/example-repl-basic/src/main.rs
@@ -70,7 +70,8 @@ fn main() {
}
// Create error route
-pack!(ErrorDirectoryNotExist = PathBuf);
+#[derive(Grouped, Wrap)]
+pub struct ErrorDirectoryNotExist(PathBuf);
// Create commands: cd ls exit
dispatcher!("cd", EntryCd);
@@ -79,16 +80,18 @@ dispatcher!("exit", EntryExit);
dispatcher!("clear", EntryClear);
// Define data needed for the cd command's execution phase
-pack!(StateChangeDirectory = String);
+#[derive(Grouped, Wrap)]
+pub struct StateChangeDirectory(String);
// Define data needed for the ls command's rendering phase
-pack!(ResultList = Vec<String>);
+#[derive(Grouped, Wrap)]
+pub struct ResultList(Vec<String>);
// Parse cd command arguments
#[chain]
fn parse_cd_args(prev: EntryCd) -> Next {
let join = prev.pick_or_default(&arg![String]).unwrap();
- StateChangeDirectory::new(join).into()
+ StateChangeDirectory(join).into()
}
// Execute directory change
@@ -96,12 +99,12 @@ fn parse_cd_args(prev: EntryCd) -> Next {
fn handle_cd(prev: StateChangeDirectory, current_dir: &mut ResCurrentDir) -> Next {
use just_fmt::fmt_path::fmt_path;
- let join = prev.inner;
+ let join = prev.0;
let new_dir = fmt_path(current_dir.dir.join(join)).unwrap_or_default();
// If the path is not found, route to error handling
if !new_dir.exists() {
- return ErrorDirectoryNotExist::new(new_dir).to_render();
+ return ErrorDirectoryNotExist(new_dir).to_render();
}
current_dir.dir = new_dir;
@@ -126,14 +129,14 @@ fn handle_ls(_prev: EntryLs, current_dir: &ResCurrentDir) -> Next {
.collect();
// Render ResultList
- ResultList::new(entries).to_render()
+ ResultList(entries).to_render()
}
/// Render ResultList data
#[renderer]
fn render_list(list: ResultList) -> RenderResult {
let mut render_result = RenderResult::new();
- for item in list.inner {
+ for item in list.0 {
writeln!(render_result, "{}", item).ok();
}
render_result
@@ -160,12 +163,7 @@ fn handle_clear(_prev: EntryClear) {
#[renderer]
fn render_error_directory_not_exist(err: ErrorDirectoryNotExist) -> RenderResult {
let mut render_result = RenderResult::new();
- writeln!(
- render_result,
- "Directory not found: {}",
- err.inner.display()
- )
- .ok();
+ writeln!(render_result, "Directory not found: {}", err.0.display()).ok();
render_result
}
diff --git a/examples/example-setup/src/main.rs b/examples/example-setup/src/main.rs
index 523a567..59c503f 100644
--- a/examples/example-setup/src/main.rs
+++ b/examples/example-setup/src/main.rs
@@ -55,13 +55,14 @@ fn custom_setup(program: &mut Program<ThisProgram>) {
dispatcher!("greet", EntryGreet);
-pack!(ResultGreeting = String);
+#[derive(Grouped, Wrap)]
+pub struct ResultGreeting(String);
/// Chain: reads the `ResAppName` and `ResAppVersion` resources.
#[chain]
fn handle_greet(args: EntryGreet, app: &ResAppName, version: &ResAppVersion) -> Next {
let who = args
- .inner
+ .0
.first()
.cloned()
.unwrap_or_else(|| "World".to_string());
diff --git a/examples/example-structural-renderer/src/main.rs b/examples/example-structural-renderer/src/main.rs
index a1bddbd..c1cfd69 100644
--- a/examples/example-structural-renderer/src/main.rs
+++ b/examples/example-structural-renderer/src/main.rs
@@ -32,7 +32,8 @@ fn main() {
}
// --------- IMPORTANT ---------
-// For beautiful output structure, do not use `pack!` to wrap the types that need to be output.
+// For beautiful output structure, do not wrap the types that need to be output
+// in a newtype; instead, use a named struct.
// Instead, manually implement
// ____________________________________ Mark as structured data so it can be rendered
// / ____________________ Implement serde::Serialize
@@ -48,7 +49,7 @@ struct Info {
}
// This will output: {"member_name":"name","member_age":32} structure
-// If using pack!(Info = (String, i32));
+// If wrapping with a tuple newtype (e.g. `#[derive(Grouped, Wrap)] pub struct Info((String, i32));`)
// Output: {"inner":["name", 32]}
// --------- IMPORTANT ---------
diff --git a/examples/example-unit-test/src/main.rs b/examples/example-unit-test/src/main.rs
index 29ff9da..e4c6504 100644
--- a/examples/example-unit-test/src/main.rs
+++ b/examples/example-unit-test/src/main.rs
@@ -36,30 +36,30 @@ mod tests {
let hello_with_valid_name = handle_hello(entry!("Peter")).into();
assert_render_result!(hello_with_valid_name);
let result_name = unpack_chain_process!(hello_with_valid_name, ResultName);
- assert_eq!(result_name.inner, "Peter");
+ assert_eq!(result_name.0, "Peter");
}
#[test]
fn test_render_result_name() {
- let r = render_result_name(ResultName::new("Peter".into()));
+ let r = render_result_name(ResultName("Peter".into()));
assert_eq!(r.to_string().as_str(), "Hello, Peter!")
}
#[test]
fn test_render_error_no_name_provided() {
- let r = render_error_no_name_provided(ErrorNoNameProvided::default());
+ let r = render_error_no_name_provided(ErrorNoNameProvided);
assert_eq!(r.to_string().as_str(), "No name provided")
}
#[test]
fn test_render_error_name_not_available() {
- let r = render_error_name_not_available(ErrorNameNotAvailable::default());
+ let r = render_error_name_not_available(ErrorNameNotAvailable);
assert_eq!(r.to_string().as_str(), "Name not available")
}
#[test]
fn test_render_error_name_too_long() {
- let r = render_error_name_too_long(ErrorNameTooLong::new(17));
+ let r = render_error_name_too_long(ErrorNameTooLong(17));
assert_eq!(r.to_string().as_str(), "Name too long: 17 > 10")
}
// --------- IMPORTANT ---------
@@ -67,29 +67,35 @@ mod tests {
dispatcher!("hello", EntryHello);
-pack!(ErrorNoNameProvided = ());
-pack!(ErrorNameTooLong = u16);
-pack!(ErrorNameNotAvailable = ());
+#[derive(Grouped)]
+pub struct ErrorNoNameProvided;
-pack!(ResultName = String);
+#[derive(Grouped, Wrap)]
+pub struct ErrorNameTooLong(u16);
+
+#[derive(Grouped)]
+pub struct ErrorNameNotAvailable;
+
+#[derive(Grouped, Wrap)]
+pub struct ResultName(String);
static VEC_REGISTERED_NAMES: &[&str] = &["Alice", "Bob", "Charlie", "David", "Eve"];
#[chain]
fn handle_hello(args: EntryHello) -> Next {
- let Some(name) = args.inner.first().cloned() else {
- return ErrorNoNameProvided::default().to_render();
+ let Some(name) = args.0.first().cloned() else {
+ return ErrorNoNameProvided.to_render();
};
if name.len() > 10 {
- return ErrorNameTooLong::new(name.len() as u16).to_render();
+ return ErrorNameTooLong(name.len() as u16).to_render();
}
if VEC_REGISTERED_NAMES.contains(&name.as_str()) {
- return ErrorNameNotAvailable::default().to_render();
+ return ErrorNameNotAvailable.to_render();
}
- ResultName::new(name).to_render()
+ ResultName(name).to_render()
}
/// Renders a successful greeting with the given name.
@@ -128,12 +134,7 @@ fn render_error_name_too_long(len: ErrorNameTooLong) -> RenderResult {
#[renderer]
fn render_entry_fallback(err: EntryFallback) -> RenderResult {
let mut render_result = RenderResult::new();
- writeln!(
- render_result,
- "Command not found: \"{}\"",
- err.inner.join(" ")
- )
- .ok();
+ writeln!(render_result, "Command not found: \"{}\"", err.0.join(" ")).ok();
render_result
}
diff --git a/examples/full-todolist/src/main.rs b/examples/full-todolist/src/main.rs
index eea417a..9c7bfe8 100644
--- a/examples/full-todolist/src/main.rs
+++ b/examples/full-todolist/src/main.rs
@@ -36,15 +36,25 @@ dispatcher!("clean");
// Define states
-pack!(StateAddTodo = String);
-pack!(StateCompleteTodo = i32);
-pack!(StateListTodo = bool);
+#[derive(Grouped, Wrap)]
+pub struct StateAddTodo(String);
+
+#[derive(Grouped, Wrap)]
+pub struct StateCompleteTodo(i32);
+
+#[derive(Grouped, Wrap)]
+pub struct StateListTodo(bool);
// Define errors
-pack!(ErrorNoTaskDescriptionProvided = ());
-pack!(ErrorNoIndexProvided = ());
-pack!(ErrorIndexOutOfBounds = ());
+#[derive(Grouped)]
+pub struct ErrorNoTaskDescriptionProvided;
+
+#[derive(Grouped)]
+pub struct ErrorNoIndexProvided;
+
+#[derive(Grouped)]
+pub struct ErrorIndexOutOfBounds;
fn main() {
let mut program = ThisProgram::new();
@@ -76,11 +86,11 @@ fn main() {
fn handle_add(args: EntryAdd) -> Next {
let task: String = route! {
args.pick_or_route(&arg![String], || {
- ErrorNoTaskDescriptionProvided::new(()).to_chain()
+ ErrorNoTaskDescriptionProvided.to_chain()
})
.to_result()
};
- StateAddTodo::new(task).to_chain()
+ StateAddTodo(task).to_chain()
}
#[chain]
@@ -92,7 +102,7 @@ fn handle_state_add_todo(
let todolist = todolist.get_mut();
// Unpack state and read description
- let description = state.inner;
+ let description = state.0;
todolist.items.push(Todo {
item: description,
@@ -117,10 +127,10 @@ fn handle_list(_args: EntryList, todolist: &mut LazyRes<ResTodoList>) -> Next {
#[chain]
fn handle_complete(args: EntryComplete) -> Next {
let index: i32 = route! {
- args.pick_or_route(&arg![i32], || ErrorNoIndexProvided::new(()).to_chain())
+ args.pick_or_route(&arg![i32], || ErrorNoIndexProvided.to_chain())
.to_result()
};
- StateCompleteTodo::new(index).to_chain()
+ StateCompleteTodo(index).to_chain()
}
#[chain]
@@ -129,12 +139,12 @@ fn handle_state_complete_todo(
todolist: &mut LazyRes<ResTodoList>,
) -> Next {
let todolist = todolist.get_mut();
- let index = state.inner as usize;
+ let index = state.0 as usize;
if index < todolist.items.len() {
todolist.items[index].completed = true;
todolist.clone().to_render()
} else {
- ErrorIndexOutOfBounds::new(()).to_render()
+ ErrorIndexOutOfBounds.to_render()
}
}