aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author魏曹先生 <1992414357@qq.com>2026-07-11 15:15:12 +0800
committer魏曹先生 <1992414357@qq.com>2026-07-11 15:21:40 +0800
commit95815041fe2817b4b6bdba6b4f332c90320af7bb (patch)
tree224f3479eca9e44caa247132ecab42f8825b167c
parent356879cfd6149bdb235b4e02c0f351a4d2246202 (diff)
refactor(examples): migrate renderers to return RenderResult and add
std::io::Write import Replace r_println!/r_print! macro usage across all example renderers with explicit RenderResult construction using std::io::Write, enabling more flexible output handling and reducing reliance on macro-side effects.
-rw-r--r--examples/example-argument-parse/src/main.rs15
-rw-r--r--examples/example-async-support/src/main.rs7
-rw-r--r--examples/example-basic/src/main.rs7
-rw-r--r--examples/example-clap-binding/src/main.rs22
-rw-r--r--examples/example-combine-pathf-dispatch-tree/src/sub/mod.rs9
-rw-r--r--examples/example-completion/src/main.rs7
-rw-r--r--examples/example-custom-pickable/src/main.rs13
-rw-r--r--examples/example-dispatch-tree/src/main.rs7
-rw-r--r--examples/example-enum-tag/src/main.rs8
-rw-r--r--examples/example-error-handling/src/main.rs40
-rw-r--r--examples/example-exitcode/src/main.rs20
-rw-r--r--examples/example-help/src/main.rs7
-rw-r--r--examples/example-hook/src/main.rs8
-rw-r--r--examples/example-lazy-resources/src/main.rs14
-rw-r--r--examples/example-outside-type/src/main.rs19
-rw-r--r--examples/example-pack-err/src/main.rs31
-rw-r--r--examples/example-panic-unwind/src/main.rs8
-rw-r--r--examples/example-pathfinder/src/sub/mod.rs11
-rw-r--r--examples/example-repl-basic/src/main.rs24
-rw-r--r--examples/example-resources/src/main.rs15
-rw-r--r--examples/example-structural-renderer/src/main.rs9
-rw-r--r--examples/example-unit-test/src/main.rs44
-rw-r--r--examples/full-todolist/src/help.rs99
-rw-r--r--examples/full-todolist/src/main.rs40
-rw-r--r--examples/full-todolist/src/todolist.rs22
-rw-r--r--mingling/src/example_docs.rs325
-rw-r--r--mingling_macros/src/dispatcher_clap.rs10
27 files changed, 561 insertions, 280 deletions
diff --git a/examples/example-argument-parse/src/main.rs b/examples/example-argument-parse/src/main.rs
index 4929b7c..59499a2 100644
--- a/examples/example-argument-parse/src/main.rs
+++ b/examples/example-argument-parse/src/main.rs
@@ -19,6 +19,7 @@
//! ```
use mingling::{macros::route, prelude::*};
+use std::io::Write;
dispatcher!("transfer", CMDTransfer => EntryTransfer);
dispatcher!("strict-transfer", CMDStrictTransfer => EntryStrictTransfer);
@@ -71,20 +72,26 @@ fn handle_strict_transfer_parse(args: EntryStrictTransfer) -> Next {
/// Renders the parsed transfer result (file/dir, size, name).
#[renderer]
-fn render_result_file(result: ResultFile) {
+fn render_result_file(result: ResultFile) -> RenderResult {
let (is_dir, size, name) = result.into();
- r_println!(
+ let mut result = RenderResult::new();
+ writeln!(
+ result,
"{}: {} ({})",
if is_dir { "dir" } else { "file" },
name,
size
)
+ .ok();
+ result
}
/// Renders the error when no name is provided.
#[renderer]
-fn render_error_no_name_provided(_: ErrorNoNameProvided) {
- r_println!("Error: name is not provided")
+fn render_error_no_name_provided(_: ErrorNoNameProvided) -> RenderResult {
+ let mut result = RenderResult::new();
+ writeln!(result, "Error: name is not provided").ok();
+ result
}
gen_program!();
diff --git a/examples/example-async-support/src/main.rs b/examples/example-async-support/src/main.rs
index 847bfea..ac85aaf 100644
--- a/examples/example-async-support/src/main.rs
+++ b/examples/example-async-support/src/main.rs
@@ -24,6 +24,7 @@
//! ```
use mingling::{hook::ProgramHook, prelude::*};
+use std::io::Write;
#[tokio::main]
async fn main() {
@@ -55,8 +56,10 @@ pub async fn handle_download(args: EntryDownload) -> Next {
/// Renders the downloaded file name.
#[renderer]
// But renderers cannot use the `async` keyword
-pub fn render_downloaded(result: ResultDownloaded) {
- r_println!("\"{}\" downloaded.", *result);
+pub fn render_downloaded(result: ResultDownloaded) -> RenderResult {
+ let mut render_result = RenderResult::new();
+ writeln!(render_result, "\"{}\" downloaded.", *result).ok();
+ render_result
}
// --------- IMPORTANT ---------
diff --git a/examples/example-basic/src/main.rs b/examples/example-basic/src/main.rs
index 3d94a4b..7fc0bce 100644
--- a/examples/example-basic/src/main.rs
+++ b/examples/example-basic/src/main.rs
@@ -14,6 +14,7 @@
// Import commonly used Mingling modules
use mingling::prelude::*;
+use std::io::Write;
// Define the `greet` subcommand
// _____________________________ subcmd name, can be nested (e.g. "remote.add" "remote.rm")
@@ -60,8 +61,10 @@ fn handle_greet(args: EntryGreet) -> Next {
// Define renderer `render_name`, used to render `ResultName`
/// Renders the greeting message with the provided name.
#[renderer]
-fn render_name(name: ResultName) {
- r_println!("Hello, {}!", *name);
+fn render_name(name: ResultName) -> RenderResult {
+ let mut render_result = RenderResult::new();
+ writeln!(render_result, "Hello, {}!", *name).ok();
+ render_result
}
// Note: This macro generates the program entry point.
diff --git a/examples/example-clap-binding/src/main.rs b/examples/example-clap-binding/src/main.rs
index 19d794b..d99f8d1 100644
--- a/examples/example-clap-binding/src/main.rs
+++ b/examples/example-clap-binding/src/main.rs
@@ -38,7 +38,8 @@
//! For more information, try '--help'.
//! ```
-use mingling::{macros::dispatcher_clap, prelude::*, setup::BasicProgramSetup, Groupped};
+use mingling::{Groupped, macros::dispatcher_clap, prelude::*, setup::BasicProgramSetup};
+use std::io::Write;
fn main() {
let mut program = ThisProgram::new();
@@ -89,24 +90,29 @@ pub struct EntryGreet {
/// Renders the greet output with optional repetition.
#[renderer]
-fn render_greet(greet: EntryGreet) {
+fn render_greet(greet: EntryGreet) -> RenderResult {
let name = greet.name;
let count = greet.repeat.max(0) as usize;
- r_print!("Hello, ");
+ let mut render_result = RenderResult::default();
+ write!(render_result, "Hello, ").ok();
for i in 0..count {
- r_print!("{name}");
+ write!(render_result, "{name}").ok();
if i < count - 1 {
- r_print!(", ");
+ write!(render_result, ", ").ok();
}
}
- r_println!("!");
+ writeln!(render_result, "!").ok();
+ render_result
}
/// Renders the error message when greet argument parsing fails.
#[renderer]
-fn render_greet_parse_failed(err: ErrorGreetParsed) {
- r_println!("{}", *err);
+// renderers can return a RenderResult instead of using r_println!
+pub fn render_greet_parse_failed(err: ErrorGreetParsed) -> RenderResult {
+ let mut render_result = RenderResult::default();
+ writeln!(render_result, "{}", *err).ok();
+ render_result
}
gen_program!();
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 e0b7743..5ab0ece 100644
--- a/examples/example-combine-pathf-dispatch-tree/src/sub/mod.rs
+++ b/examples/example-combine-pathf-dispatch-tree/src/sub/mod.rs
@@ -1,5 +1,6 @@
use crate::Next;
-use mingling::{macros::r_println, prelude::*};
+use mingling::prelude::*;
+use std::io::Write;
dispatcher!("hello");
@@ -17,6 +18,8 @@ pub fn handle_my(args: EntryHello) -> Next {
}
#[renderer]
-pub fn render_my(msg: ResultMessage) {
- r_println!("Hello, {}!", *msg);
+pub fn render_my(msg: ResultMessage) -> RenderResult {
+ let mut render_result = RenderResult::new();
+ writeln!(render_result, "Hello, {}!", *msg).ok();
+ render_result
}
diff --git a/examples/example-completion/src/main.rs b/examples/example-completion/src/main.rs
index 0c64d03..0159807 100644
--- a/examples/example-completion/src/main.rs
+++ b/examples/example-completion/src/main.rs
@@ -45,6 +45,7 @@
//! ```
use mingling::{macros::suggest, prelude::*, ShellContext, Suggest};
+use std::io::Write;
fn main() {
let mut program = ThisProgram::new();
@@ -118,13 +119,15 @@ fn handle_greet(args: EntryGreet) -> Next {
/// Renders the greeting with the result name and repeat count.
#[renderer]
-fn render_name(result: ResultName) {
+fn render_name(result: ResultName) -> RenderResult {
let (repeat, name) = result.inner;
+ let mut render_result = RenderResult::new();
let mut parts = Vec::with_capacity(repeat as usize);
for _ in 0..repeat {
parts.push(name.clone());
}
- r_println!("Hello, {}!", parts.join(", "));
+ writeln!(render_result, "Hello, {}!", parts.join(", ")).ok();
+ render_result
}
gen_program!();
diff --git a/examples/example-custom-pickable/src/main.rs b/examples/example-custom-pickable/src/main.rs
index 015cc62..d203815 100644
--- a/examples/example-custom-pickable/src/main.rs
+++ b/examples/example-custom-pickable/src/main.rs
@@ -15,6 +15,7 @@
//! ```
use mingling::{macros::route, parser::Pickable, prelude::*, Groupped};
+use std::io::Write;
// Define types that can be recognized by Mingling
// ________________________ `Pickable` trait needs to implement Default
@@ -52,14 +53,18 @@ fn handle_connect(prev: EntryConnect) -> Next {
/// Renders the connected address.
#[renderer]
-fn render_address(addr: Address) {
- r_println!("Connected to \"{}\"", addr.to_string());
+pub fn render_address(addr: Address) -> RenderResult {
+ let mut render_result = RenderResult::new();
+ write!(render_result, "Connected to \"{}\"", addr).ok();
+ render_result
}
/// Renders the error message when address parsing fails.
#[renderer]
-fn render_error_parse_address_failed(_: ErrorParseAddressFailed) {
- r_println!("Failed to parse address");
+pub fn render_error_parse_address_failed(_: ErrorParseAddressFailed) -> RenderResult {
+ let mut render_result = RenderResult::new();
+ write!(render_result, "Failed to parse address").ok();
+ render_result
}
gen_program!();
diff --git a/examples/example-dispatch-tree/src/main.rs b/examples/example-dispatch-tree/src/main.rs
index e087b1e..9f76f15 100644
--- a/examples/example-dispatch-tree/src/main.rs
+++ b/examples/example-dispatch-tree/src/main.rs
@@ -21,6 +21,7 @@
//!
use mingling::prelude::*;
+use std::io::Write;
// --------- IMPORTANT ---------
// You have a large number of subcommands
@@ -53,8 +54,10 @@ fn main() {
/// Renders the confirmation message for the `cmd5` command.
#[renderer]
-fn render_cmd5(_: Entry5) {
- r_println!("It's works!");
+fn render_cmd5(_: Entry5) -> RenderResult {
+ let mut render_result = RenderResult::new();
+ writeln!(render_result, "It's works!").ok();
+ render_result
}
gen_program!();
diff --git a/examples/example-enum-tag/src/main.rs b/examples/example-enum-tag/src/main.rs
index ad9db82..01c7767 100644
--- a/examples/example-enum-tag/src/main.rs
+++ b/examples/example-enum-tag/src/main.rs
@@ -19,6 +19,7 @@ use mingling::{
macros::suggest_enum, parser::PickableEnum, prelude::*, EnumTag, Groupped, ShellContext,
Suggest,
};
+use std::io::Write;
// Define the enum and derive the EnumTag trait
// ________ adds metadata to the enum, enabling it to:
@@ -83,10 +84,11 @@ fn handle_language_selection(args: EntryLanguageSelection) -> Next {
/// Renders the selected programming language with its name and description.
#[renderer]
-fn render_programming_language(lang: ProgrammingLanguages) {
- // You can use `enum_info()` to get the name and description of the current enum
+pub fn render_programming_language(lang: ProgrammingLanguages) -> RenderResult {
+ let mut render_result = RenderResult::new();
let (name, desc) = lang.enum_info();
- r_println!("Selected: {} ({})", name, desc)
+ writeln!(render_result, "Selected: {} ({})", name, desc).ok();
+ render_result
}
#[completion(EntryLanguageSelection)]
diff --git a/examples/example-error-handling/src/main.rs b/examples/example-error-handling/src/main.rs
index ae79b97..de9792d 100644
--- a/examples/example-error-handling/src/main.rs
+++ b/examples/example-error-handling/src/main.rs
@@ -21,6 +21,7 @@
//! ```
use mingling::prelude::*;
+use std::io::Write;
// In Mingling, instead of using ? to propagate errors upward,
// errors are treated as branches that continue execution.
@@ -61,36 +62,47 @@ fn handle_hello(args: EntryHello) -> Next {
/// Renders a successful greeting with the given name.
#[renderer]
-fn render_result_name(name: ResultName) {
- r_println!("Hello, {}", *name);
+fn render_result_name(name: ResultName) -> RenderResult {
+ let mut render_result = RenderResult::new();
+ writeln!(render_result, "Hello, {}", *name).ok();
+ render_result
}
/// Renders the error when no name is provided.
#[renderer]
-fn render_error_no_name_provided(_: ErrorNoNameProvided) {
- // Prompt when no name is provided
- r_println!("No name provided");
+fn render_error_no_name_provided(_: ErrorNoNameProvided) -> RenderResult {
+ let mut render_result = RenderResult::new();
+ writeln!(render_result, "No name provided").ok();
+ render_result
}
/// Renders the error when the name is already taken.
#[renderer]
-fn render_error_name_not_available(_: ErrorNameNotAvailable) {
- // Prompt when name is already taken
- r_println!("Name not available");
+fn render_error_name_not_available(_: ErrorNameNotAvailable) -> RenderResult {
+ let mut render_result = RenderResult::new();
+ writeln!(render_result, "Name not available").ok();
+ render_result
}
/// Renders the error when the name exceeds the maximum length.
#[renderer]
-fn render_error_name_too_long(len: ErrorNameTooLong) {
- // Prompt when name is too long, showing actual length
- r_println!("Name too long: {} > 10", *len);
+fn render_error_name_too_long(len: ErrorNameTooLong) -> RenderResult {
+ let mut render_result = RenderResult::new();
+ writeln!(render_result, "Name too long: {} > 10", *len).ok();
+ render_result
}
/// Renders the error when the dispatcher (subcommand) is not found.
#[renderer]
-fn render_dispatcher_not_found(err: ErrorDispatcherNotFound) {
- // Prompt when command is not found, showing the input command
- r_println!("Command not found: \"{}\"", err.inner.join(" "));
+fn render_dispatcher_not_found(err: ErrorDispatcherNotFound) -> RenderResult {
+ let mut render_result = RenderResult::new();
+ writeln!(
+ render_result,
+ "Command not found: \"{}\"",
+ err.inner.join(" ")
+ )
+ .ok();
+ render_result
}
gen_program!();
diff --git a/examples/example-exitcode/src/main.rs b/examples/example-exitcode/src/main.rs
index b0b7467..6b22eae 100644
--- a/examples/example-exitcode/src/main.rs
+++ b/examples/example-exitcode/src/main.rs
@@ -20,6 +20,7 @@ use mingling::{
res::ResExitCode,
setup::{BasicProgramSetup, ExitCodeSetup},
};
+use std::io::Write;
fn main() {
let mut program = ThisProgram::new();
@@ -52,25 +53,32 @@ fn handle_hello(args: EntryHello) -> Next {
/// Renders a successful greeting with the given name.
#[renderer]
-fn render_result_name(name: ResultName) {
- r_println!("Hello, {}", *name);
+fn render_result_name(name: ResultName) -> RenderResult {
+ let mut result = RenderResult::new();
+ writeln!(result, "Hello, {}", *name).ok();
+ result
}
#[help]
-fn help_hello(_p: EntryHello, ec: &mut ResExitCode) {
- r_println!("Usage: hello <NAME>");
+fn help_hello(_p: EntryHello, ec: &mut ResExitCode) -> RenderResult {
+ let mut result = RenderResult::new();
+ writeln!(result, "Usage: hello <NAME>").ok();
ec.exit_code = 2;
+ result
}
// Define renderer, render error message _______________ Inject exit code resource
// /
/// Renders the error when no name is provided |
#[renderer] // vvvvvvvvvvvvvvvv
-fn render_error_no_name_provided(_: ErrorNoNameProvided, ec: &mut ResExitCode) {
+fn render_error_no_name_provided(_: ErrorNoNameProvided, ec: &mut ResExitCode) -> RenderResult {
ec.exit_code = 1;
+ let mut result = RenderResult::new();
+
// Prompt when no name is provided
- r_println!("No name provided (with exit code 1)");
+ writeln!(result, "No name provided (with exit code 1)").ok();
+ result
}
gen_program!();
diff --git a/examples/example-help/src/main.rs b/examples/example-help/src/main.rs
index 9567c49..3282683 100644
--- a/examples/example-help/src/main.rs
+++ b/examples/example-help/src/main.rs
@@ -14,14 +14,17 @@
//! ```
use mingling::{macros::help, prelude::*, setup::BasicProgramSetup};
+use std::io::Write;
dispatcher!("greet", CMDGreet => EntryGreet);
// Define help _________ When `program.user_context.help` is `true`
// / the command will not enter `#[chain]` / `#[renderer]`
#[help] // vvvvvvvvvv but instead enter this `#[help]` function
-fn help_greet(_prev: EntryGreet) {
- r_println!("Usage: greet <NAME>");
+fn help_greet(_prev: EntryGreet) -> RenderResult {
+ let mut render_result = RenderResult::new();
+ writeln!(render_result, "Usage: greet <NAME>").ok();
+ render_result
}
fn main() {
diff --git a/examples/example-hook/src/main.rs b/examples/example-hook/src/main.rs
index d9a8fd1..41928ca 100644
--- a/examples/example-hook/src/main.rs
+++ b/examples/example-hook/src/main.rs
@@ -24,6 +24,7 @@ use mingling::{
hook::{ProgramControlUnit, ProgramHook},
prelude::*,
};
+use std::io::Write;
dispatcher!("greet", CMDGreet => EntryGreet);
@@ -67,9 +68,12 @@ fn handle_greet(args: EntryGreet) -> Next {
}
/// Renders the greeting message with the provided name.
+/// Renders the greeting message with the provided name.
#[renderer]
-fn render_name(name: ResultName) {
- r_println!("Hello, {}!", *name);
+fn render_name(name: ResultName) -> RenderResult {
+ let mut render_result = RenderResult::new();
+ writeln!(render_result, "Hello, {}!", *name).ok();
+ render_result
}
gen_program!();
diff --git a/examples/example-lazy-resources/src/main.rs b/examples/example-lazy-resources/src/main.rs
index 3533ae2..aaafb98 100644
--- a/examples/example-lazy-resources/src/main.rs
+++ b/examples/example-lazy-resources/src/main.rs
@@ -22,6 +22,7 @@
//! ```
use std::collections::BTreeMap;
+use std::io::Write;
use mingling::{LazyInit, LazyRes, prelude::*};
@@ -73,20 +74,25 @@ fn main() {
// | _____________________ Use LazyRes<ResLargeData>
// | / instead of ResLargeData
#[renderer] // vvvv vvvvvvvvvvvvvvvvvvvvv
-fn render_entry_show(_args: EntryShow, res: &mut LazyRes<ResLargeData>) {
+fn render_entry_show(_args: EntryShow, res: &mut LazyRes<ResLargeData>) -> RenderResult {
+ let mut render_result = RenderResult::new();
+
// _______ Initialization happens here
// /
// vvvvvvv
let res = res.get_ref();
for (key, value) in &res.data {
- r_println!("{}: {}", key, value);
+ writeln!(render_result, "{}: {}", key, value).ok();
}
+ render_result
}
// When not using LazyRes<ResLargeData>, it will not be initialized
#[renderer]
-fn render_entry_none(_args: EntryNone) {
- r_println!("None");
+fn render_entry_none(_args: EntryNone) -> RenderResult {
+ let mut render_result = RenderResult::new();
+ writeln!(render_result, "None").ok();
+ render_result
}
gen_program!();
diff --git a/examples/example-outside-type/src/main.rs b/examples/example-outside-type/src/main.rs
index 7cf4d40..925878a 100644
--- a/examples/example-outside-type/src/main.rs
+++ b/examples/example-outside-type/src/main.rs
@@ -19,6 +19,7 @@
//! ```
use mingling::{macros::group, prelude::*};
+use std::io::Write;
use std::{io::ErrorKind::Other, num::ParseIntError};
dispatcher!("parse");
@@ -61,8 +62,10 @@ fn parse_number(args: EntryParse) -> Next {
// _____________ Using std::num::ParseIntError as a chain input
// /
#[renderer] // vvvvvvvvvvvv
-fn render_number(num: ParsedNumber) {
- r_println!("Parsed number: {}", *num);
+fn render_number(num: ParsedNumber) -> RenderResult {
+ let mut render_result = RenderResult::new();
+ write!(render_result, "Parsed number: {}", *num).ok();
+ render_result
}
/// Renderer for parse errors — using the outside `ParseIntError` type.
@@ -70,16 +73,20 @@ fn render_number(num: ParsedNumber) {
/// The `ParseIntError` type is registered via `group!` above, so it implements
/// `Groupped<ThisProgram>` and can be used directly in a `#[renderer]` function.
#[renderer]
-fn render_parse_error(err: ParseIntError) {
- r_println!("Parse error: {}", err);
+fn render_parse_error(err: ParseIntError) -> RenderResult {
+ let mut render_result = RenderResult::new();
+ write!(render_result, "Parse error: {}", err).ok();
+ render_result
}
/// Renderer for IO errors — using `std::io::Error` registered as `ErrorIo`.
// ________ Must use alias `ErrorIo` here, not bare `std::io::Error`
// /
#[renderer] // vvvvvvv
-fn render_error_io(err: ErrorIo) {
- r_println!("IO_ERROR: {}", err.to_string());
+fn render_error_io(err: ErrorIo) -> RenderResult {
+ let mut render_result = RenderResult::new();
+ write!(render_result, "IO_ERROR: {}", err).ok();
+ render_result
}
fn main() {
diff --git a/examples/example-pack-err/src/main.rs b/examples/example-pack-err/src/main.rs
index 8716333..5bf5066 100644
--- a/examples/example-pack-err/src/main.rs
+++ b/examples/example-pack-err/src/main.rs
@@ -28,6 +28,7 @@
use mingling::prelude::*;
use mingling::setup::StructuralRendererSetup;
+use std::io::Write;
use std::path::PathBuf;
dispatcher!("find", CMDFind => EntryFind);
@@ -100,32 +101,42 @@ fn handle_find_structural(args: EntryFindStructural) -> Next {
/// Renders the successful result with the found directory path.
#[renderer]
-fn render_result_path(path: ResultPath) {
- r_println!("Found directory: {}", path.display());
+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) {
- r_println!("Search path not provided");
+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) {
- r_println!("Not a directory: {}", err.info.display());
+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) {
- r_println!("Search path not provided");
+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) {
- r_println!("Not a directory: {}", err.info.display());
+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!();
diff --git a/examples/example-panic-unwind/src/main.rs b/examples/example-panic-unwind/src/main.rs
index ed032c5..a829158 100644
--- a/examples/example-panic-unwind/src/main.rs
+++ b/examples/example-panic-unwind/src/main.rs
@@ -16,6 +16,7 @@
//! ```
use mingling::{hook::ProgramHook, prelude::*};
+use std::io::Write;
dispatcher!("panic", CMDPanic => EntryPanic);
pack!(NotPanic = ());
@@ -51,9 +52,12 @@ fn handle_panic(prev: EntryPanic) -> Next {
}
/// Renders the message when no panic occurs.
+/// Renders the message when no panic occurs.
#[renderer]
-fn render(_: NotPanic) {
- r_println!("Program not panic");
+pub fn render(_: NotPanic) -> RenderResult {
+ let mut render_result = RenderResult::new();
+ writeln!(render_result, "Program not panic").ok();
+ render_result
}
gen_program!();
diff --git a/examples/example-pathfinder/src/sub/mod.rs b/examples/example-pathfinder/src/sub/mod.rs
index ef10a75..6d15930 100644
--- a/examples/example-pathfinder/src/sub/mod.rs
+++ b/examples/example-pathfinder/src/sub/mod.rs
@@ -1,5 +1,6 @@
-use mingling::prelude::*;
use crate::Next;
+use mingling::prelude::*;
+use std::io::Write;
dispatcher!("greet", CMDGreet => EntryGreet);
pack!(ResultName = String);
@@ -15,7 +16,11 @@ pub fn handle_greet(args: EntryGreet) -> Next {
name
}
+/// Renders the name.
#[renderer]
-pub fn render_name(name: ResultName) {
- r_println!("Hello, {}!", *name);
+// But renderers cannot use the `async` keyword
+pub fn render_name(name: ResultName) -> RenderResult {
+ let mut render_result = RenderResult::new();
+ writeln!(render_result, "Hello, {}!", *name).ok();
+ render_result
}
diff --git a/examples/example-repl-basic/src/main.rs b/examples/example-repl-basic/src/main.rs
index 8df8c22..d15319e 100644
--- a/examples/example-repl-basic/src/main.rs
+++ b/examples/example-repl-basic/src/main.rs
@@ -14,6 +14,7 @@ use mingling::{
setup::{BasicREPLOutputSetup, BasicREPLPromptSetup, BasicREPLReadlineSetup},
this,
};
+use std::io::Write;
use std::{env::current_dir, path::PathBuf};
// Resource to store the current directory
@@ -136,10 +137,12 @@ fn handle_ls(_prev: EntryLs, current_dir: &ResCurrentDir) -> Next {
/// Render ResultList data
#[renderer]
-fn render_list(list: ResultList) {
+fn render_list(list: ResultList) -> RenderResult {
+ let mut render_result = RenderResult::new();
for item in list.inner {
- r_println!("{}", item);
+ writeln!(render_result, "{}", item).ok();
}
+ render_result
}
// Handle exit command event
@@ -161,15 +164,24 @@ fn handle_clear(_prev: EntryClear) {
/// Handle path not found event
#[renderer]
-fn render_error_directory_not_exist(err: ErrorDirectoryNotExist) {
- r_println!("Directory not found: {}", err.inner.display())
+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();
+ render_result
}
/// Handle dispatcher not found event
/// Renders the error when a command is not found.
#[renderer]
-fn dispatcher_not_found(prev: ErrorDispatcherNotFound) {
- r_println!("Command not found: \"{}\"", prev.join(", "))
+fn dispatcher_not_found(prev: ErrorDispatcherNotFound) -> RenderResult {
+ let mut render_result = RenderResult::new();
+ writeln!(render_result, "Command not found: \"{}\"", prev.join(", ")).ok();
+ render_result
}
gen_program!();
diff --git a/examples/example-resources/src/main.rs b/examples/example-resources/src/main.rs
index 6c5bf84..b08ee26 100644
--- a/examples/example-resources/src/main.rs
+++ b/examples/example-resources/src/main.rs
@@ -14,9 +14,9 @@
//! Current directory: /home/alice/mingling/src
//! ```
-use std::path::PathBuf;
-
use mingling::prelude::*;
+use std::io::Write;
+use std::path::PathBuf;
// Create resource
// ______________ Resource needs to
@@ -58,8 +58,15 @@ fn render_modify_current(args: EntryModifyCurrent, current_dir: &mut ResCurrentD
// /
/// Renders the current directory path. |
#[renderer] // vvvvvvvvvvvvvv
-fn render_current(_: EntryCurrent, current_dir: &ResCurrentDir) {
- r_println!("Current directory: {}", current_dir.current_dir.display());
+fn render_current(_: EntryCurrent, current_dir: &ResCurrentDir) -> RenderResult {
+ let mut render_result = RenderResult::new();
+ write!(
+ render_result,
+ "Current directory: {}",
+ current_dir.current_dir.display()
+ )
+ .ok();
+ render_result
}
gen_program!();
diff --git a/examples/example-structural-renderer/src/main.rs b/examples/example-structural-renderer/src/main.rs
index 21077e7..13c4c84 100644
--- a/examples/example-structural-renderer/src/main.rs
+++ b/examples/example-structural-renderer/src/main.rs
@@ -18,8 +18,9 @@
//! ```
use mingling::prelude::*;
-use mingling::{parser::Picker, setup::StructuralRendererSetup, StructuralData, Groupped};
+use mingling::{Groupped, StructuralData, parser::Picker, setup::StructuralRendererSetup};
use serde::Serialize;
+use std::io::Write;
dispatcher!("render", CMDRender => EntryRender);
@@ -64,8 +65,10 @@ fn parse_render(prev: EntryRender) -> Next {
/// Implement default renderer for when structural_renderer is not specified
#[renderer]
-fn render_info(prev: Info) {
- r_println!("{} is {} years old", prev.name, prev.age);
+fn render_info(prev: Info) -> RenderResult {
+ let mut render_result = RenderResult::new();
+ writeln!(render_result, "{} is {} years old", prev.name, prev.age).ok();
+ render_result
}
gen_program!();
diff --git a/examples/example-unit-test/src/main.rs b/examples/example-unit-test/src/main.rs
index b89c629..b85ff01 100644
--- a/examples/example-unit-test/src/main.rs
+++ b/examples/example-unit-test/src/main.rs
@@ -7,6 +7,7 @@
//! ```
use mingling::prelude::*;
+use std::io::Write;
#[cfg(test)]
mod tests {
@@ -41,25 +42,25 @@ mod tests {
#[test]
fn test_render_result_name() {
let r = render_result_name(ResultName::new("Peter".into()));
- assert_eq!(r, "Hello, Peter!\n")
+ assert_eq!(r.to_string().as_str(), "Hello, Peter!\n")
}
#[test]
fn test_render_error_no_name_provided() {
let r = render_error_no_name_provided(ErrorNoNameProvided::default());
- assert_eq!(r, "No name provided\n")
+ assert_eq!(r.to_string().as_str(), "No name provided\n")
}
#[test]
fn test_render_error_name_not_available() {
let r = render_error_name_not_available(ErrorNameNotAvailable::default());
- assert_eq!(r, "Name not available\n")
+ assert_eq!(r.to_string().as_str(), "Name not available\n")
}
#[test]
fn test_render_error_name_too_long() {
let r = render_error_name_too_long(ErrorNameTooLong::new(17));
- assert_eq!(r, "Name too long: 17 > 10\n")
+ assert_eq!(r.to_string().as_str(), "Name too long: 17 > 10\n")
}
// --------- IMPORTANT ---------
}
@@ -93,32 +94,47 @@ fn handle_hello(args: EntryHello) -> Next {
/// Renders a successful greeting with the given name.
#[renderer]
-fn render_result_name(name: ResultName) -> String {
- r_println!("Hello, {}!", *name);
+fn render_result_name(name: ResultName) -> RenderResult {
+ let mut render_result = RenderResult::new();
+ writeln!(render_result, "Hello, {}!", *name).ok();
+ render_result
}
/// Renders the error when no name is provided.
#[renderer]
-fn render_error_no_name_provided(_: ErrorNoNameProvided) -> String {
- r_println!("No name provided");
+fn render_error_no_name_provided(_: ErrorNoNameProvided) -> RenderResult {
+ let mut render_result = RenderResult::new();
+ writeln!(render_result, "No name provided").ok();
+ render_result
}
/// Renders the error when the name is already taken.
#[renderer]
-fn render_error_name_not_available(_: ErrorNameNotAvailable) -> String {
- r_println!("Name not available");
+fn render_error_name_not_available(_: ErrorNameNotAvailable) -> RenderResult {
+ let mut render_result = RenderResult::new();
+ writeln!(render_result, "Name not available").ok();
+ render_result
}
/// Renders the error when the name exceeds the maximum length.
#[renderer]
-fn render_error_name_too_long(len: ErrorNameTooLong) -> String {
- r_println!("Name too long: {} > 10", *len);
+fn render_error_name_too_long(len: ErrorNameTooLong) -> RenderResult {
+ let mut render_result = RenderResult::new();
+ writeln!(render_result, "Name too long: {} > 10", *len).ok();
+ render_result
}
/// Renders the error when the dispatcher (subcommand) is not found.
#[renderer]
-fn render_dispatcher_not_found(err: ErrorDispatcherNotFound) {
- r_println!("Command not found: \"{}\"", err.inner.join(" "));
+fn render_dispatcher_not_found(err: ErrorDispatcherNotFound) -> RenderResult {
+ let mut render_result = RenderResult::new();
+ writeln!(
+ render_result,
+ "Command not found: \"{}\"",
+ err.inner.join(" ")
+ )
+ .ok();
+ render_result
}
gen_program!();
diff --git a/examples/full-todolist/src/help.rs b/examples/full-todolist/src/help.rs
index ab33176..2f8228a 100644
--- a/examples/full-todolist/src/help.rs
+++ b/examples/full-todolist/src/help.rs
@@ -1,15 +1,16 @@
//! This module provides help information for the `todolist` command line program
-use mingling::macros::{help, r_println};
-
use crate::{EntryAdd, EntryClean, EntryComplete, EntryList, ErrorDispatcherNotFound};
+use mingling::{RenderResult, macros::help};
+use std::io::Write;
+/// Shows the global help message.
#[help]
-pub fn help_global(_p: ErrorDispatcherNotFound) {
- r_println!(
- "{}",
- r"
-Usage: todolist [command] [args]
+pub fn help_global(_p: ErrorDispatcherNotFound) -> RenderResult {
+ let mut render_result = RenderResult::new();
+ writeln!(
+ render_result,
+ r"Usage: todolist [command] [args]
Commands:
add -- Add a new task
@@ -20,74 +21,78 @@ Commands:
Args:
-h, --help -- Show this help message
-V, --version -- Show the version
- -A, --all -- All tasks (Clean all / List all)
- "
- .trim()
- );
+ -A, --all -- All tasks (Clean all / List all)"
+ )
+ .ok();
+ render_result
}
+/// Shows help for the `add` command.
#[help]
-pub fn help_add(_p: EntryAdd) {
- r_println!(
- "{}",
- r"
-Usage: todolist add [task description]
+pub fn help_add(_p: EntryAdd) -> RenderResult {
+ let mut render_result = RenderResult::new();
+ writeln!(
+ render_result,
+ r"Usage: todolist add [task description]
Add a new task to the todo list.
Example:
todolist add 'Buy groceries'
- todolist add 'Finish Rust project'
- "
- .trim()
- );
+ todolist add 'Finish Rust project'"
+ )
+ .ok();
+ render_result
}
+/// Shows help for the `list` command.
#[help]
-pub fn help_list(_p: EntryList) {
- r_println!(
- "{}",
- r"
-Usage: todolist list
+pub fn help_list(_p: EntryList) -> RenderResult {
+ let mut render_result = RenderResult::new();
+ writeln!(
+ render_result,
+ r"Usage: todolist list
List all tasks.
Example:
- todolist list
- "
- .trim()
- );
+ todolist list"
+ )
+ .ok();
+ render_result
}
+/// Shows help for the `complete` command.
#[help]
-pub fn help_complete(_p: EntryComplete) {
- r_println!(
- "{}",
- r"
-Usage: todolist complete [task_id]
+pub fn help_complete(_p: EntryComplete) -> RenderResult {
+ let mut render_result = RenderResult::new();
+ writeln!(
+ render_result,
+ r"Usage: todolist complete [task_id]
Mark a task as complete by its ID.
Example:
todolist complete 1
- todolist complete 3
- "
- .trim()
- );
+ todolist complete 3"
+ )
+ .ok();
+ render_result
}
+/// Shows help for the `clean` command.
#[help]
-pub fn help_clean(_p: EntryClean) {
- r_println!(
- "{}",
- r"
-Usage: todolist clean
+pub fn help_clean(_p: EntryClean) -> RenderResult {
+ let mut render_result = RenderResult::new();
+ writeln!(
+ render_result,
+ r"Usage: todolist clean
Remove all completed tasks from the list.
Example:
- todolist clean
- "
- .trim()
- );
+ todolist clean"
+ )
+ .ok();
+ render_result
}
diff --git a/examples/full-todolist/src/main.rs b/examples/full-todolist/src/main.rs
index e4c5aa6..0748832 100644
--- a/examples/full-todolist/src/main.rs
+++ b/examples/full-todolist/src/main.rs
@@ -7,12 +7,13 @@
//! > This is truly a cliché example, as common as `Hello World`!
use mingling::{
+ LazyInit, LazyRes,
macros::route,
prelude::*,
res::ResExitCode,
- setup::{ExitCodeSetup, StructuralRendererSetup, HelpFlagSetup},
- LazyInit, LazyRes,
+ setup::{ExitCodeSetup, HelpFlagSetup, StructuralRendererSetup},
};
+use std::io::Write;
mod help;
pub use help::*;
@@ -160,38 +161,47 @@ fn handle_clean(
}
}
+/// Renders error when no task description is provided.
#[renderer]
-fn render_error_no_task_description_provided(
+pub fn render_error_no_task_description_provided(
_err: ErrorNoTaskDescriptionProvided,
// ExitCode
ec: &mut ResExitCode,
-) {
- r_println!("No task description provided!");
- r_println!("");
- r_println!("Use `todolist add <desc>` to add a task");
+) -> RenderResult {
+ let mut render_result = RenderResult::new();
+ writeln!(render_result, "No task description provided!").ok();
+ writeln!(render_result).ok();
+ writeln!(render_result, "Use `todolist add <desc>` to add a task").ok();
ec.exit_code = 1;
+ render_result
}
+/// Renders error when no index is provided.
#[renderer]
-fn render_error_no_index_provided(
+pub fn render_error_no_index_provided(
_err: ErrorNoIndexProvided,
// ExitCode
ec: &mut ResExitCode,
-) {
- r_println!("No index provided!");
- r_println!("");
- r_println!("Use `todolist list` to query indexes");
+) -> RenderResult {
+ let mut render_result = RenderResult::new();
+ writeln!(render_result, "No index provided!").ok();
+ writeln!(render_result).ok();
+ writeln!(render_result, "Use `todolist list` to query indexes").ok();
ec.exit_code = 2;
+ render_result
}
+/// Renders error when index is out of bounds.
#[renderer]
-fn render_error_index_out_of_bounds(
+pub fn render_error_index_out_of_bounds(
_err: ErrorIndexOutOfBounds,
// ExitCode
ec: &mut ResExitCode,
-) {
- r_println!("Index out of bounds!");
+) -> RenderResult {
+ let mut render_result = RenderResult::new();
+ writeln!(render_result, "Index out of bounds!").ok();
ec.exit_code = 3;
+ render_result
}
gen_program!();
diff --git a/examples/full-todolist/src/todolist.rs b/examples/full-todolist/src/todolist.rs
index e447f5d..71338c3 100644
--- a/examples/full-todolist/src/todolist.rs
+++ b/examples/full-todolist/src/todolist.rs
@@ -1,10 +1,8 @@
//! Data structures, read and write logic for the todo list
-use mingling::{
- macros::{r_println, renderer},
- Groupped,
-};
+use mingling::{Groupped, RenderResult, macros::renderer};
use serde::{Deserialize, Serialize};
+use std::io::Write;
use std::{env::current_dir, path::PathBuf};
use crate::ResProgramFlags;
@@ -37,22 +35,30 @@ pub fn read_todo_list() -> ResTodoList {
serde_json::from_reader(reader).unwrap_or_default()
}
+/// Renders the todo list.
#[renderer]
-pub fn render_res_todo_list(todo_list: ResTodoList, program_flags: &ResProgramFlags) {
+pub fn render_res_todo_list(
+ todo_list: ResTodoList,
+ program_flags: &ResProgramFlags,
+) -> RenderResult {
+ let mut render_result = RenderResult::new();
let mut idx = 0;
- r_println!("TODO: ");
+ writeln!(render_result, "TODO: ").ok();
for item in &todo_list.items {
if item.completed && !program_flags.all {
idx += 1;
continue;
}
- r_println!(
+ writeln!(
+ render_result,
" {idx}. [{}] - \"{}\"",
if item.completed { "x" } else { " " },
item.item
- );
+ )
+ .ok();
idx += 1;
}
+ render_result
}
pub fn write_todo_list(todo_list: ResTodoList) {
diff --git a/mingling/src/example_docs.rs b/mingling/src/example_docs.rs
index 92b13a0..4b34d0d 100644
--- a/mingling/src/example_docs.rs
+++ b/mingling/src/example_docs.rs
@@ -39,6 +39,7 @@
/// Source code (./src/main.rs)
/// ```ignore
/// use mingling::{macros::route, prelude::*};
+/// use std::io::Write;
///
/// dispatcher!("transfer", CMDTransfer => EntryTransfer);
/// dispatcher!("strict-transfer", CMDStrictTransfer => EntryStrictTransfer);
@@ -91,20 +92,26 @@
///
/// /// Renders the parsed transfer result (file/dir, size, name).
/// #[renderer]
-/// fn render_result_file(result: ResultFile) {
+/// fn render_result_file(result: ResultFile) -> RenderResult {
/// let (is_dir, size, name) = result.into();
-/// r_println!(
+/// let mut result = RenderResult::new();
+/// writeln!(
+/// result,
/// "{}: {} ({})",
/// if is_dir { "dir" } else { "file" },
/// name,
/// size
/// )
+/// .ok();
+/// result
/// }
///
/// /// Renders the error when no name is provided.
/// #[renderer]
-/// fn render_error_no_name_provided(_: ErrorNoNameProvided) {
-/// r_println!("Error: name is not provided")
+/// fn render_error_no_name_provided(_: ErrorNoNameProvided) -> RenderResult {
+/// let mut result = RenderResult::new();
+/// writeln!(result, "Error: name is not provided").ok();
+/// result
/// }
///
/// gen_program!();
@@ -166,6 +173,7 @@ pub mod example_argument_parse {}
/// Source code (./src/main.rs)
/// ```ignore
/// use mingling::{hook::ProgramHook, prelude::*};
+/// use std::io::Write;
///
/// #[tokio::main]
/// async fn main() {
@@ -197,8 +205,10 @@ pub mod example_argument_parse {}
/// /// Renders the downloaded file name.
/// #[renderer]
/// // But renderers cannot use the `async` keyword
-/// pub fn render_downloaded(result: ResultDownloaded) {
-/// r_println!("\"{}\" downloaded.", *result);
+/// pub fn render_downloaded(result: ResultDownloaded) -> RenderResult {
+/// let mut render_result = RenderResult::new();
+/// writeln!(render_result, "\"{}\" downloaded.", *result).ok();
+/// render_result
/// }
/// // --------- IMPORTANT ---------
///
@@ -241,6 +251,7 @@ pub mod example_async_support {}
/// ```ignore
/// // Import commonly used Mingling modules
/// use mingling::prelude::*;
+/// use std::io::Write;
///
/// // Define the `greet` subcommand
/// // _____________________________ subcmd name, can be nested (e.g. "remote.add" "remote.rm")
@@ -287,8 +298,10 @@ pub mod example_async_support {}
/// // Define renderer `render_name`, used to render `ResultName`
/// /// Renders the greeting message with the provided name.
/// #[renderer]
-/// fn render_name(name: ResultName) {
-/// r_println!("Hello, {}!", *name);
+/// fn render_name(name: ResultName) -> RenderResult {
+/// let mut render_result = RenderResult::new();
+/// writeln!(render_result, "Hello, {}!", *name).ok();
+/// render_result
/// }
///
/// // Note: This macro generates the program entry point.
@@ -365,7 +378,8 @@ pub mod example_basic {}
///
/// Source code (./src/main.rs)
/// ```ignore
-/// use mingling::{macros::dispatcher_clap, prelude::*, setup::BasicProgramSetup, Groupped};
+/// use mingling::{Groupped, macros::dispatcher_clap, prelude::*, setup::BasicProgramSetup};
+/// use std::io::Write;
///
/// fn main() {
/// let mut program = ThisProgram::new();
@@ -416,24 +430,29 @@ pub mod example_basic {}
///
/// /// Renders the greet output with optional repetition.
/// #[renderer]
-/// fn render_greet(greet: EntryGreet) {
+/// fn render_greet(greet: EntryGreet) -> RenderResult {
/// let name = greet.name;
/// let count = greet.repeat.max(0) as usize;
///
-/// r_print!("Hello, ");
+/// let mut render_result = RenderResult::default();
+/// write!(render_result, "Hello, ").ok();
/// for i in 0..count {
-/// r_print!("{name}");
+/// write!(render_result, "{name}").ok();
/// if i < count - 1 {
-/// r_print!(", ");
+/// write!(render_result, ", ").ok();
/// }
/// }
-/// r_println!("!");
+/// writeln!(render_result, "!").ok();
+/// render_result
/// }
///
/// /// Renders the error message when greet argument parsing fails.
/// #[renderer]
-/// fn render_greet_parse_failed(err: ErrorGreetParsed) {
-/// r_println!("{}", *err);
+/// // renderers can return a RenderResult instead of using r_println!
+/// pub fn render_greet_parse_failed(err: ErrorGreetParsed) -> RenderResult {
+/// let mut render_result = RenderResult::default();
+/// writeln!(render_result, "{}", *err).ok();
+/// render_result
/// }
///
/// gen_program!();
@@ -584,6 +603,7 @@ pub mod example_combine_pathf_dispatch_tree {}
/// Source code (./src/main.rs)
/// ```ignore
/// use mingling::{macros::suggest, prelude::*, ShellContext, Suggest};
+/// use std::io::Write;
///
/// fn main() {
/// let mut program = ThisProgram::new();
@@ -657,13 +677,15 @@ pub mod example_combine_pathf_dispatch_tree {}
///
/// /// Renders the greeting with the result name and repeat count.
/// #[renderer]
-/// fn render_name(result: ResultName) {
+/// fn render_name(result: ResultName) -> RenderResult {
/// let (repeat, name) = result.inner;
+/// let mut render_result = RenderResult::new();
/// let mut parts = Vec::with_capacity(repeat as usize);
/// for _ in 0..repeat {
/// parts.push(name.clone());
/// }
-/// r_println!("Hello, {}!", parts.join(", "));
+/// writeln!(render_result, "Hello, {}!", parts.join(", ")).ok();
+/// render_result
/// }
///
/// gen_program!();
@@ -703,6 +725,7 @@ pub mod example_completion {}
/// Source code (./src/main.rs)
/// ```ignore
/// use mingling::{macros::route, parser::Pickable, prelude::*, Groupped};
+/// use std::io::Write;
///
/// // Define types that can be recognized by Mingling
/// // ________________________ `Pickable` trait needs to implement Default
@@ -740,14 +763,18 @@ pub mod example_completion {}
///
/// /// Renders the connected address.
/// #[renderer]
-/// fn render_address(addr: Address) {
-/// r_println!("Connected to \"{}\"", addr.to_string());
+/// pub fn render_address(addr: Address) -> RenderResult {
+/// let mut render_result = RenderResult::new();
+/// write!(render_result, "Connected to \"{}\"", addr.to_string()).ok();
+/// render_result
/// }
///
/// /// Renders the error message when address parsing fails.
/// #[renderer]
-/// fn render_error_parse_address_failed(_: ErrorParseAddressFailed) {
-/// r_println!("Failed to parse address");
+/// pub fn render_error_parse_address_failed(_: ErrorParseAddressFailed) -> RenderResult {
+/// let mut render_result = RenderResult::new();
+/// write!(render_result, "Failed to parse address").ok();
+/// render_result
/// }
///
/// gen_program!();
@@ -856,6 +883,7 @@ pub mod example_custom_pickable {}
/// Source code (./src/main.rs)
/// ```ignore
/// use mingling::prelude::*;
+/// use std::io::Write;
///
/// // --------- IMPORTANT ---------
/// // You have a large number of subcommands
@@ -888,8 +916,10 @@ pub mod example_custom_pickable {}
///
/// /// Renders the confirmation message for the `cmd5` command.
/// #[renderer]
-/// fn render_cmd5(_: Entry5) {
-/// r_println!("It's works!");
+/// fn render_cmd5(_: Entry5) -> RenderResult {
+/// let mut render_result = RenderResult::new();
+/// writeln!(render_result, "It's works!").ok();
+/// render_result
/// }
///
/// gen_program!();
@@ -936,6 +966,7 @@ pub mod example_dispatch_tree {}
/// macros::suggest_enum, parser::PickableEnum, prelude::*, EnumTag, Groupped, ShellContext,
/// Suggest,
/// };
+/// use std::io::Write;
///
/// // Define the enum and derive the EnumTag trait
/// // ________ adds metadata to the enum, enabling it to:
@@ -1000,10 +1031,11 @@ pub mod example_dispatch_tree {}
///
/// /// Renders the selected programming language with its name and description.
/// #[renderer]
-/// fn render_programming_language(lang: ProgrammingLanguages) {
-/// // You can use `enum_info()` to get the name and description of the current enum
+/// pub fn render_programming_language(lang: ProgrammingLanguages) -> RenderResult {
+/// let mut render_result = RenderResult::new();
/// let (name, desc) = lang.enum_info();
-/// r_println!("Selected: {} ({})", name, desc)
+/// writeln!(render_result, "Selected: {} ({})", name, desc).ok();
+/// render_result
/// }
///
/// #[completion(EntryLanguageSelection)]
@@ -1060,6 +1092,7 @@ pub mod example_enum_tag {}
/// Source code (./src/main.rs)
/// ```ignore
/// use mingling::prelude::*;
+/// use std::io::Write;
///
/// // In Mingling, instead of using ? to propagate errors upward,
/// // errors are treated as branches that continue execution.
@@ -1100,36 +1133,47 @@ pub mod example_enum_tag {}
///
/// /// Renders a successful greeting with the given name.
/// #[renderer]
-/// fn render_result_name(name: ResultName) {
-/// r_println!("Hello, {}", *name);
+/// fn render_result_name(name: ResultName) -> RenderResult {
+/// let mut render_result = RenderResult::new();
+/// writeln!(render_result, "Hello, {}", *name).ok();
+/// render_result
/// }
///
/// /// Renders the error when no name is provided.
/// #[renderer]
-/// fn render_error_no_name_provided(_: ErrorNoNameProvided) {
-/// // Prompt when no name is provided
-/// r_println!("No name provided");
+/// fn render_error_no_name_provided(_: ErrorNoNameProvided) -> RenderResult {
+/// let mut render_result = RenderResult::new();
+/// writeln!(render_result, "No name provided").ok();
+/// render_result
/// }
///
/// /// Renders the error when the name is already taken.
/// #[renderer]
-/// fn render_error_name_not_available(_: ErrorNameNotAvailable) {
-/// // Prompt when name is already taken
-/// r_println!("Name not available");
+/// fn render_error_name_not_available(_: ErrorNameNotAvailable) -> RenderResult {
+/// let mut render_result = RenderResult::new();
+/// writeln!(render_result, "Name not available").ok();
+/// render_result
/// }
///
/// /// Renders the error when the name exceeds the maximum length.
/// #[renderer]
-/// fn render_error_name_too_long(len: ErrorNameTooLong) {
-/// // Prompt when name is too long, showing actual length
-/// r_println!("Name too long: {} > 10", *len);
+/// fn render_error_name_too_long(len: ErrorNameTooLong) -> RenderResult {
+/// let mut render_result = RenderResult::new();
+/// writeln!(render_result, "Name too long: {} > 10", *len).ok();
+/// render_result
/// }
///
/// /// Renders the error when the dispatcher (subcommand) is not found.
/// #[renderer]
-/// fn render_dispatcher_not_found(err: ErrorDispatcherNotFound) {
-/// // Prompt when command is not found, showing the input command
-/// r_println!("Command not found: \"{}\"", err.inner.join(" "));
+/// fn render_dispatcher_not_found(err: ErrorDispatcherNotFound) -> RenderResult {
+/// let mut render_result = RenderResult::new();
+/// writeln!(
+/// render_result,
+/// "Command not found: \"{}\"",
+/// err.inner.join(" ")
+/// )
+/// .ok();
+/// render_result
/// }
///
/// gen_program!();
@@ -1178,6 +1222,7 @@ pub mod example_error_handling {}
/// res::ResExitCode,
/// setup::{BasicProgramSetup, ExitCodeSetup},
/// };
+/// use std::io::Write;
///
/// fn main() {
/// let mut program = ThisProgram::new();
@@ -1210,25 +1255,32 @@ pub mod example_error_handling {}
///
/// /// Renders a successful greeting with the given name.
/// #[renderer]
-/// fn render_result_name(name: ResultName) {
-/// r_println!("Hello, {}", *name);
+/// fn render_result_name(name: ResultName) -> RenderResult {
+/// let mut result = RenderResult::new();
+/// writeln!(result, "Hello, {}", *name).ok();
+/// result
/// }
///
/// #[help]
-/// fn help_hello(_p: EntryHello, ec: &mut ResExitCode) {
-/// r_println!("Usage: hello <NAME>");
+/// fn help_hello(_p: EntryHello, ec: &mut ResExitCode) -> RenderResult {
+/// let mut result = RenderResult::new();
+/// writeln!(result, "Usage: hello <NAME>").ok();
/// ec.exit_code = 2;
+/// result
/// }
///
/// // Define renderer, render error message _______________ Inject exit code resource
/// // /
/// /// Renders the error when no name is provided |
/// #[renderer] // vvvvvvvvvvvvvvvv
-/// fn render_error_no_name_provided(_: ErrorNoNameProvided, ec: &mut ResExitCode) {
+/// fn render_error_no_name_provided(_: ErrorNoNameProvided, ec: &mut ResExitCode) -> RenderResult {
/// ec.exit_code = 1;
///
+/// let mut result = RenderResult::new();
+///
/// // Prompt when no name is provided
-/// r_println!("No name provided (with exit code 1)");
+/// writeln!(result, "No name provided (with exit code 1)").ok();
+/// result
/// }
///
/// gen_program!();
@@ -1265,14 +1317,17 @@ pub mod example_exitcode {}
/// Source code (./src/main.rs)
/// ```ignore
/// use mingling::{macros::help, prelude::*, setup::BasicProgramSetup};
+/// use std::io::Write;
///
/// dispatcher!("greet", CMDGreet => EntryGreet);
///
/// // Define help _________ When `program.user_context.help` is `true`
/// // / the command will not enter `#[chain]` / `#[renderer]`
/// #[help] // vvvvvvvvvv but instead enter this `#[help]` function
-/// fn help_greet(_prev: EntryGreet) {
-/// r_println!("Usage: greet <NAME>");
+/// fn help_greet(_prev: EntryGreet) -> RenderResult {
+/// let mut render_result = RenderResult::new();
+/// writeln!(render_result, "Usage: greet <NAME>").ok();
+/// render_result
/// }
///
/// fn main() {
@@ -1333,6 +1388,7 @@ pub mod example_help {}
/// hook::{ProgramControlUnit, ProgramHook},
/// prelude::*,
/// };
+/// use std::io::Write;
///
/// dispatcher!("greet", CMDGreet => EntryGreet);
///
@@ -1376,9 +1432,12 @@ pub mod example_help {}
/// }
///
/// /// Renders the greeting message with the provided name.
+/// /// Renders the greeting message with the provided name.
/// #[renderer]
-/// fn render_name(name: ResultName) {
-/// r_println!("Hello, {}!", *name);
+/// fn render_name(name: ResultName) -> RenderResult {
+/// let mut render_result = RenderResult::new();
+/// writeln!(render_result, "Hello, {}!", *name).ok();
+/// render_result
/// }
///
/// gen_program!();
@@ -1465,6 +1524,7 @@ pub mod example_implicit_dispatcher {}
/// Source code (./src/main.rs)
/// ```ignore
/// use std::collections::BTreeMap;
+/// use std::io::Write;
///
/// use mingling::{LazyInit, LazyRes, prelude::*};
///
@@ -1516,20 +1576,25 @@ pub mod example_implicit_dispatcher {}
/// // | _____________________ Use LazyRes<ResLargeData>
/// // | / instead of ResLargeData
/// #[renderer] // vvvv vvvvvvvvvvvvvvvvvvvvv
-/// fn render_entry_show(_args: EntryShow, res: &mut LazyRes<ResLargeData>) {
+/// fn render_entry_show(_args: EntryShow, res: &mut LazyRes<ResLargeData>) -> RenderResult {
+/// let mut render_result = RenderResult::new();
+///
/// // _______ Initialization happens here
/// // /
/// // vvvvvvv
/// let res = res.get_ref();
/// for (key, value) in &res.data {
-/// r_println!("{}: {}", key, value);
+/// writeln!(render_result, "{}: {}", key, value).ok();
/// }
+/// render_result
/// }
///
/// // When not using LazyRes<ResLargeData>, it will not be initialized
/// #[renderer]
-/// fn render_entry_none(_args: EntryNone) {
-/// r_println!("None");
+/// fn render_entry_none(_args: EntryNone) -> RenderResult {
+/// let mut render_result = RenderResult::new();
+/// writeln!(render_result, "None").ok();
+/// render_result
/// }
///
/// gen_program!();
@@ -1574,6 +1639,7 @@ pub mod example_lazy_resources {}
/// Source code (./src/main.rs)
/// ```ignore
/// use mingling::{macros::group, prelude::*};
+/// use std::io::Write;
/// use std::{io::ErrorKind::Other, num::ParseIntError};
///
/// dispatcher!("parse");
@@ -1616,8 +1682,10 @@ pub mod example_lazy_resources {}
/// // _____________ Using std::num::ParseIntError as a chain input
/// // /
/// #[renderer] // vvvvvvvvvvvv
-/// fn render_number(num: ParsedNumber) {
-/// r_println!("Parsed number: {}", *num);
+/// fn render_number(num: ParsedNumber) -> RenderResult {
+/// let mut render_result = RenderResult::new();
+/// write!(render_result, "Parsed number: {}", *num).ok();
+/// render_result
/// }
///
/// /// Renderer for parse errors — using the outside `ParseIntError` type.
@@ -1625,16 +1693,20 @@ pub mod example_lazy_resources {}
/// /// The `ParseIntError` type is registered via `group!` above, so it implements
/// /// `Groupped<ThisProgram>` and can be used directly in a `#[renderer]` function.
/// #[renderer]
-/// fn render_parse_error(err: ParseIntError) {
-/// r_println!("Parse error: {}", err);
+/// fn render_parse_error(err: ParseIntError) -> RenderResult {
+/// let mut render_result = RenderResult::new();
+/// write!(render_result, "Parse error: {}", err).ok();
+/// render_result
/// }
///
/// /// Renderer for IO errors — using `std::io::Error` registered as `ErrorIo`.
/// // ________ Must use alias `ErrorIo` here, not bare `std::io::Error`
/// // /
/// #[renderer] // vvvvvvv
-/// fn render_error_io(err: ErrorIo) {
-/// r_println!("IO_ERROR: {}", err.to_string());
+/// fn render_error_io(err: ErrorIo) -> RenderResult {
+/// let mut render_result = RenderResult::new();
+/// write!(render_result, "IO_ERROR: {}", err.to_string()).ok();
+/// render_result
/// }
///
/// fn main() {
@@ -1699,6 +1771,7 @@ pub mod example_outside_type {}
/// ```ignore
/// use mingling::prelude::*;
/// use mingling::setup::StructuralRendererSetup;
+/// use std::io::Write;
/// use std::path::PathBuf;
///
/// dispatcher!("find", CMDFind => EntryFind);
@@ -1771,32 +1844,42 @@ pub mod example_outside_type {}
///
/// /// Renders the successful result with the found directory path.
/// #[renderer]
-/// fn render_result_path(path: ResultPath) {
-/// r_println!("Found directory: {}", path.display());
+/// 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) {
-/// r_println!("Search path not provided");
+/// 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) {
-/// r_println!("Not a directory: {}", err.info.display());
+/// 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) {
-/// r_println!("Search path not provided");
+/// 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) {
-/// r_println!("Not a directory: {}", err.info.display());
+/// 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!();
@@ -1853,6 +1936,7 @@ pub mod example_pack_err {}
/// Source code (./src/main.rs)
/// ```ignore
/// use mingling::{hook::ProgramHook, prelude::*};
+/// use std::io::Write;
///
/// dispatcher!("panic", CMDPanic => EntryPanic);
/// pack!(NotPanic = ());
@@ -1888,9 +1972,12 @@ pub mod example_pack_err {}
/// }
///
/// /// Renders the message when no panic occurs.
+/// /// Renders the message when no panic occurs.
/// #[renderer]
-/// fn render(_: NotPanic) {
-/// r_println!("Program not panic");
+/// pub fn render(_: NotPanic) -> RenderResult {
+/// let mut render_result = RenderResult::new();
+/// writeln!(render_result, "Program not panic").ok();
+/// render_result
/// }
///
/// gen_program!();
@@ -1994,6 +2081,7 @@ pub mod example_pathfinder {}
/// setup::{BasicREPLOutputSetup, BasicREPLPromptSetup, BasicREPLReadlineSetup},
/// this,
/// };
+/// use std::io::Write;
/// use std::{env::current_dir, path::PathBuf};
///
/// // Resource to store the current directory
@@ -2116,10 +2204,12 @@ pub mod example_pathfinder {}
///
/// /// Render ResultList data
/// #[renderer]
-/// fn render_list(list: ResultList) {
+/// fn render_list(list: ResultList) -> RenderResult {
+/// let mut render_result = RenderResult::new();
/// for item in list.inner {
-/// r_println!("{}", item);
+/// writeln!(render_result, "{}", item).ok();
/// }
+/// render_result
/// }
///
/// // Handle exit command event
@@ -2141,15 +2231,24 @@ pub mod example_pathfinder {}
///
/// /// Handle path not found event
/// #[renderer]
-/// fn render_error_directory_not_exist(err: ErrorDirectoryNotExist) {
-/// r_println!("Directory not found: {}", err.inner.display())
+/// 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();
+/// render_result
/// }
///
/// /// Handle dispatcher not found event
/// /// Renders the error when a command is not found.
/// #[renderer]
-/// fn dispatcher_not_found(prev: ErrorDispatcherNotFound) {
-/// r_println!("Command not found: \"{}\"", prev.join(", "))
+/// fn dispatcher_not_found(prev: ErrorDispatcherNotFound) -> RenderResult {
+/// let mut render_result = RenderResult::new();
+/// writeln!(render_result, "Command not found: \"{}\"", prev.join(", ")).ok();
+/// render_result
/// }
///
/// gen_program!();
@@ -2187,9 +2286,9 @@ pub mod example_repl_basic {}
///
/// Source code (./src/main.rs)
/// ```ignore
-/// use std::path::PathBuf;
-///
/// use mingling::prelude::*;
+/// use std::io::Write;
+/// use std::path::PathBuf;
///
/// // Create resource
/// // ______________ Resource needs to
@@ -2231,8 +2330,15 @@ pub mod example_repl_basic {}
/// // /
/// /// Renders the current directory path. |
/// #[renderer] // vvvvvvvvvvvvvv
-/// fn render_current(_: EntryCurrent, current_dir: &ResCurrentDir) {
-/// r_println!("Current directory: {}", current_dir.current_dir.display());
+/// fn render_current(_: EntryCurrent, current_dir: &ResCurrentDir) -> RenderResult {
+/// let mut render_result = RenderResult::new();
+/// write!(
+/// render_result,
+/// "Current directory: {}",
+/// current_dir.current_dir.display()
+/// )
+/// .ok();
+/// render_result
/// }
///
/// gen_program!();
@@ -2330,8 +2436,9 @@ pub mod example_setup {}
/// Source code (./src/main.rs)
/// ```ignore
/// use mingling::prelude::*;
-/// use mingling::{parser::Picker, setup::StructuralRendererSetup, StructuralData, Groupped};
+/// use mingling::{Groupped, StructuralData, parser::Picker, setup::StructuralRendererSetup};
/// use serde::Serialize;
+/// use std::io::Write;
///
/// dispatcher!("render", CMDRender => EntryRender);
///
@@ -2376,8 +2483,10 @@ pub mod example_setup {}
///
/// /// Implement default renderer for when structural_renderer is not specified
/// #[renderer]
-/// fn render_info(prev: Info) {
-/// r_println!("{} is {} years old", prev.name, prev.age);
+/// fn render_info(prev: Info) -> RenderResult {
+/// let mut render_result = RenderResult::new();
+/// writeln!(render_result, "{} is {} years old", prev.name, prev.age).ok();
+/// render_result
/// }
///
/// gen_program!();
@@ -2407,6 +2516,7 @@ pub mod example_structural_renderer {}
/// Source code (./src/main.rs)
/// ```ignore
/// use mingling::prelude::*;
+/// use std::io::Write;
///
/// #[cfg(test)]
/// mod tests {
@@ -2441,25 +2551,25 @@ pub mod example_structural_renderer {}
/// #[test]
/// fn test_render_result_name() {
/// let r = render_result_name(ResultName::new("Peter".into()));
-/// assert_eq!(r, "Hello, Peter!\n")
+/// assert_eq!(r.to_string().as_str(), "Hello, Peter!\n")
/// }
///
/// #[test]
/// fn test_render_error_no_name_provided() {
/// let r = render_error_no_name_provided(ErrorNoNameProvided::default());
-/// assert_eq!(r, "No name provided\n")
+/// assert_eq!(r.to_string().as_str(), "No name provided\n")
/// }
///
/// #[test]
/// fn test_render_error_name_not_available() {
/// let r = render_error_name_not_available(ErrorNameNotAvailable::default());
-/// assert_eq!(r, "Name not available\n")
+/// assert_eq!(r.to_string().as_str(), "Name not available\n")
/// }
///
/// #[test]
/// fn test_render_error_name_too_long() {
/// let r = render_error_name_too_long(ErrorNameTooLong::new(17));
-/// assert_eq!(r, "Name too long: 17 > 10\n")
+/// assert_eq!(r.to_string().as_str(), "Name too long: 17 > 10\n")
/// }
/// // --------- IMPORTANT ---------
/// }
@@ -2493,32 +2603,47 @@ pub mod example_structural_renderer {}
///
/// /// Renders a successful greeting with the given name.
/// #[renderer]
-/// fn render_result_name(name: ResultName) -> String {
-/// r_println!("Hello, {}!", *name);
+/// fn render_result_name(name: ResultName) -> RenderResult {
+/// let mut render_result = RenderResult::new();
+/// writeln!(render_result, "Hello, {}!", *name).ok();
+/// render_result
/// }
///
/// /// Renders the error when no name is provided.
/// #[renderer]
-/// fn render_error_no_name_provided(_: ErrorNoNameProvided) -> String {
-/// r_println!("No name provided");
+/// fn render_error_no_name_provided(_: ErrorNoNameProvided) -> RenderResult {
+/// let mut render_result = RenderResult::new();
+/// writeln!(render_result, "No name provided").ok();
+/// render_result
/// }
///
/// /// Renders the error when the name is already taken.
/// #[renderer]
-/// fn render_error_name_not_available(_: ErrorNameNotAvailable) -> String {
-/// r_println!("Name not available");
+/// fn render_error_name_not_available(_: ErrorNameNotAvailable) -> RenderResult {
+/// let mut render_result = RenderResult::new();
+/// writeln!(render_result, "Name not available").ok();
+/// render_result
/// }
///
/// /// Renders the error when the name exceeds the maximum length.
/// #[renderer]
-/// fn render_error_name_too_long(len: ErrorNameTooLong) -> String {
-/// r_println!("Name too long: {} > 10", *len);
+/// fn render_error_name_too_long(len: ErrorNameTooLong) -> RenderResult {
+/// let mut render_result = RenderResult::new();
+/// writeln!(render_result, "Name too long: {} > 10", *len).ok();
+/// render_result
/// }
///
/// /// Renders the error when the dispatcher (subcommand) is not found.
/// #[renderer]
-/// fn render_dispatcher_not_found(err: ErrorDispatcherNotFound) {
-/// r_println!("Command not found: \"{}\"", err.inner.join(" "));
+/// fn render_dispatcher_not_found(err: ErrorDispatcherNotFound) -> RenderResult {
+/// let mut render_result = RenderResult::new();
+/// writeln!(
+/// render_result,
+/// "Command not found: \"{}\"",
+/// err.inner.join(" ")
+/// )
+/// .ok();
+/// render_result
/// }
///
/// gen_program!();
diff --git a/mingling_macros/src/dispatcher_clap.rs b/mingling_macros/src/dispatcher_clap.rs
index 5f06fb4..b89dbad 100644
--- a/mingling_macros/src/dispatcher_clap.rs
+++ b/mingling_macros/src/dispatcher_clap.rs
@@ -1,9 +1,8 @@
use proc_macro::TokenStream;
use quote::quote;
use syn::{
- Ident, ItemStruct, LitBool, LitStr, Token,
parse::{Parse, ParseStream},
- parse_macro_input,
+ parse_macro_input, Ident, ItemStruct, LitBool, LitStr, Token,
};
/// Parsed key-value options after the first positional arguments
@@ -144,7 +143,7 @@ pub fn dispatcher_clap_attr(attr: TokenStream, item: TokenStream) -> TokenStream
Some(quote! {
#[allow(non_snake_case)]
#[::mingling::macros::help]
- pub fn #help_fn_name(_prev: #struct_name) {
+ pub fn #help_fn_name(_prev: #struct_name) -> ::mingling::RenderResult {
use std::io::Write;
use clap::ColorChoice;
@@ -154,11 +153,14 @@ pub fn dispatcher_clap_attr(attr: TokenStream, item: TokenStream) -> TokenStream
let mut cmd = <#struct_name as ::clap::CommandFactory>::command()
.color(ColorChoice::Always);
let styled = cmd.render_help();
- write!(__renderer_inner_result, "{}", styled.ansi()).unwrap();
+ let mut result = ::mingling::RenderResult::new();
+ let _ = write!(result, "{}", styled.ansi());
+ result
}
::mingling::ClapHelpPrintBehaviour::PrintDirectly => {
let mut command = <#struct_name as ::clap::CommandFactory>::command();
command.print_help().unwrap();
+ ::mingling::RenderResult::new()
}
}
}