diff options
Diffstat (limited to 'docs/pages')
| -rw-r--r-- | docs/pages/1-creating-your-first-program.md | 56 | ||||
| -rw-r--r-- | docs/pages/2-implementing-fallbacks.md | 46 |
2 files changed, 51 insertions, 51 deletions
diff --git a/docs/pages/1-creating-your-first-program.md b/docs/pages/1-creating-your-first-program.md index f905d8a..75c5081 100644 --- a/docs/pages/1-creating-your-first-program.md +++ b/docs/pages/1-creating-your-first-program.md @@ -26,11 +26,11 @@ ```toml [dependencies] mingling = "0.1.7" - + # If you want the latest, try the version hosted on Github mingling = { git = "https://github.com/catilgrass/mingling", branch = "main" } ``` - + > [!NOTE] > > This version matches the **Mingling** version used when writing this doc. Check [crates.io](https://crates.io/crates/mingling) for the latest release! 😄 @@ -48,12 +48,12 @@ fn main() { // Create ThisProgram and run it ThisProgram::new().exec(); } - + // The gen_program! macro collects *all preceding* components & types // then generates the `ThisProgram` struct mingling::macros::gen_program!(); ``` - + > [!TIP] > > When `gen_program!()` expands, it gathers info from other components & types that were expanded before it. This means you must place `gen_program!()` at the very last expansion point in the crate. @@ -70,15 +70,15 @@ mingling::macros::gen_program!(); fn main() { // ... } - + // Create a dispatcher, binding GreetCommand to the "greet" sub-command // When the user specifies this command, send GreetEntry to the dispatcher dispatcher!("greet", GreetCommand => GreetEntry); - + // ... gen_program!(); ``` - + Don't be scared by the sudden macro and two new types! Let me explain what this macro does: ##### About the `dispatcher!` macro 💡 @@ -106,13 +106,13 @@ gen_program!(); ```rust fn main() { let mut program = ThisProgram::new(); - + // Register the dispatcher program.with_dispatcher(GreetCommand); program.exec(); } ``` - + Now `ThisProgram` recognizes the `"greet"` sub-command, but the framework still doesn't know what `"greet"` should do. That's where we implement the actual logic: @@ -124,24 +124,24 @@ fn main() { ```rust // ... dispatcher!("greet", GreetCommand => GreetEntry); - + // Declare a renderer `render_greet`, specifying the previous type as `GreetEntry` #[renderer] fn render_greet(_prev: GreetEntry) { r_println!("Hello, World!"); } - + // ... gen_program!(); // The renderer will be registered with the program ``` - + For functions marked with `#[renderer]`, **Mingling** strictly enforces only one function signature: ```rust #[renderer] fn renderer_name (_prev: PreviousType) { } ``` - + The macro reads the type of the first param and tells `gen_program!` that this function renders that type. ##### About `r_println!()` 💡 @@ -158,10 +158,10 @@ fn renderer_name (_prev: PreviousType) { } ```rust dispatcher!("greet", GreetCommand => GreetEntry); - + // Wrap the intermediate type `ResultGreetSomeone` pack!(ResultGreetSomeone = String); - + #[chain] fn handle_greet_entry(prev: GreetEntry) -> NextProcess { let args = prev.inner; @@ -169,18 +169,18 @@ fn handle_greet_entry(prev: GreetEntry) -> NextProcess { .first() .cloned() .unwrap_or_else(|| "World".to_string()); - + // Wrap into intermediate type ResultGreetSomeone::new(name) } - + #[renderer] fn render_greet_someone(prev: ResultGreetSomeone) { // Deref prev to get the raw type r_println!("Hello, {}!", *prev); } ``` - + Just like `#[renderer]`, we created a `#[chain]` that processes type `GreetEntry` and outputs `ResultGreetSomeone`. This inserts a `Chain` between the original `Dispatcher` and `Renderer`: it extracts the user's input params (or falls back to "World"), then passes them to the renderer to print to the terminal. @@ -204,7 +204,7 @@ fn render_greet_someone(prev: ResultGreetSomeone) { ```rust pack!(PackedType = RawType); ``` - + Note: `pack!` doesn't support types with lifetimes, because types are always moved (not borrowed) between dispatchers. @@ -215,33 +215,33 @@ pack!(PackedType = RawType); ```rust use mingling::macros::{chain, dispatcher, gen_program, pack, r_println, renderer}; - + fn main() { let mut program = ThisProgram::new(); program.with_dispatcher(GreetCommand); program.exec(); } - + dispatcher!("greet", GreetCommand => GreetEntry); - + pack!(ResultGreetSomeone = String); - + #[chain] fn handle_greet_entry(prev: GreetEntry) -> NextProcess { let args = prev.inner; let name = args.first().cloned().unwrap_or_else(|| "World".to_string()); - + ResultGreetSomeone::new(name) } - + #[renderer] fn render_greet_someone(prev: ResultGreetSomeone) { r_println!("Hello, {}!", *prev); } - + gen_program!(); ``` - + Output: ```bash @@ -250,7 +250,7 @@ Hello, World! ~> your-bin greet Alice Hello, Alice! ``` - + <p align="center" style="font-size: 0.85em; color: gray;"> Written by @Weicao-CatilGrass </p> diff --git a/docs/pages/2-implementing-fallbacks.md b/docs/pages/2-implementing-fallbacks.md index a376580..a820fa1 100644 --- a/docs/pages/2-implementing-fallbacks.md +++ b/docs/pages/2-implementing-fallbacks.md @@ -13,7 +13,7 @@ ~> your-bin hello ~> your-bin hello Alice ``` - + **It does nothing!** 👆 Let me explain why: **Mingling** doesn't presume to act; it will not output anything to the terminal no matter what happens (except for `panic!` under `unwind`) @@ -34,20 +34,20 @@ ```rust // 1. Define the `greet` command dispatcher!("greet", GreetCommand => GreetEntry); - + fn main() { // ->> User enters "hello Alice" let mut program = ThisProgram::new(); - + // 2. Import the `greet` command program.with_dispatcher(GreetCommand); - + // 3. Execute the program program.exec(); } - + // ... - + // 5. Receive the DispatcherNotFound dispatch #[renderer] fn dispatcher_not_found(prev: DispatcherNotFound) { @@ -57,22 +57,22 @@ fn dispatcher_not_found(prev: DispatcherNotFound) { prev.join(" ") ); } - + // 4. Cannot match any dispatcher named `hello` // Forward the user's arguments as-is to DispatcherNotFound gen_program!(); ``` - + The output of the above program is: ```bash ~> omg hello Cannot match any command! Current input: "hello" - + ~> omg hello Alice Cannot match any command! Current input: "hello Alice" ``` - + Now, if the user enters a command that doesn't match, **Mingling** will output the appropriate message! ## The `RendererNotFound` Type @@ -86,54 +86,54 @@ Cannot match any command! Current input: "hello Alice" ```rust dispatcher!("greet", GreetCommand => GreetEntry); - + fn main() { let mut program = ThisProgram::new(); - + program.with_dispatcher(GreetCommand); program.exec(); } - + pack!(ResultGreetSomeone = String); - + #[chain] fn handle_greet_entry(prev: GreetEntry) -> NextProcess { let args = prev.inner; let name = args.first().cloned().unwrap_or_else(|| "World".to_string()); - + ResultGreetSomeone::new(name) } - + // Let's intentionally remove the renderer implementation for `ResultGreetSomeone` // #[renderer] // fn render_greet_someone(prev: ResultGreetSomeone) { // r_println!("Hello, {}!", *prev); // } - + #[renderer] fn renderer_not_found(prev: RendererNotFound) { if *prev == "DispatcherNotFound" { return; // Exclude the "DispatcherNotFound" type } - + // Trigger `panic!` when a renderer is not found panic!("Renderer \"{}\" not found!", *prev); } - + gen_program!(); - + ``` - + The output of the above program is: ```bash ~> your-bin greet Alice - + thread 'main' (90772) panicked at src/bin/your-bin.rs:30:5: Renderer "ResultGreetSomeone" not found! note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace ``` - + <p align="center" style="font-size: 0.85em; color: gray;"> Written by @Weicao-CatilGrass </p> |
