From 85ee549f68449bc70a7f1271a93ad26a8207ee40 Mon Sep 17 00:00:00 2001 From: 魏曹先生 <1992414357@qq.com> Date: Tue, 28 Apr 2026 22:39:59 +0800 Subject: Rebuild and rewrite the documentation site infrastructure --- docs/pages/2-basic/1-program.md | 114 ---------------------------- docs/pages/2-basic/2-setup.md | 150 ------------------------------------- docs/pages/2-basic/3-dispatcher.md | 95 ----------------------- docs/pages/2-basic/4-chain.md | 75 ------------------- docs/pages/2-basic/5-renderer.md | 73 ------------------ 5 files changed, 507 deletions(-) delete mode 100644 docs/pages/2-basic/1-program.md delete mode 100644 docs/pages/2-basic/2-setup.md delete mode 100644 docs/pages/2-basic/3-dispatcher.md delete mode 100644 docs/pages/2-basic/4-chain.md delete mode 100644 docs/pages/2-basic/5-renderer.md (limited to 'docs/pages/2-basic') diff --git a/docs/pages/2-basic/1-program.md b/docs/pages/2-basic/1-program.md deleted file mode 100644 index ae22896..0000000 --- a/docs/pages/2-basic/1-program.md +++ /dev/null @@ -1,114 +0,0 @@ -

Program

-

- Mingling's Basic Components -

- ---- - -## Intro - -`Program` is the data structure that holds the state for **Mingling** CLI programs. It manages the user's context and enables type-based dispatch. - -`Program` needs to implement the `ProgramCollect` trait, - -> but, you don't have to do this manually — - -The `mingling_macros` crate provides the `gen_program!()` macro, which can auto collect resources defined by the `dispatcher!`, `chain!`, and the `completion!` macro of the `comp` feature. - -```rust -// Define Dispatcher -dispatcher!("hello", HelloCommand => HelloEntry); - -// Define Renderer -#[renderer] -fn render_hello(_prev: HelloEntry) { - r_println!("Hello, World!") -} - -// Collect all resources here and generate ThisProgram -gen_program!(); - -// You can also explicitly declare a Program -// with a different name like this: -// gen_program!(MyProgram); -``` - -## Adding Setup - -You can use the `with_setup` function to add preset [Setup](pages/2-basic/2-setup) to your program, which provide reusable functionality. - -For example, you can use the following code to add parsing for global flags like `--confirm` / `--help` / `--quiet` to your program: - -```rust -use mingling::{ - macros::gen_program, - setup::BasicProgramSetup -}; - -fn main() { - let mut program = ThisProgram::new(); - // Add `BasicProgramSetup` - program.with_setup(BasicProgramSetup); - program.exec(); -} - -// Generate `ThisProgram` -gen_program!(); -``` - -## Adding Dispatcher - -You can use `with_dispatcher` or `with_dispatchers` to add [Dispatchers](pages/2-basic/3-dispatcher) to your program to make it work: - -```rust -// Define two Dispatchers using `dispatcher!` -dispatcher!("member.add", - AddMemberCommand => AddMemberEntry); -dispatcher!("member.rm", - RemoveMemberCommand => RemoveMemberEntry); - -fn main() { - let mut program = ThisProgram::new(); - - // Register Dispatchers - program.with_dispatcher(AddMemberCommand); - program.with_dispatcher(RemoveMemberCommand); - - // Or use `with_dispatchers` - program.with_dispatchers(( - AddMemberCommand, - RemoveMemberCommand - )); - - program.exec(); -} -``` - -## Parsing Global Args - -You can extract global arguments before the program runs to control the global state of the `Program`: - -```rust -fn main() { - let mut program = ThisProgram::new(); - - let mut output = current_dir().unwrap(); - - // Pick the "--quiet" or "-q" flag - program.global_flag(["--quiet", "-q"], |p| { - // Disable render output - p.stdout_setting.render_output = false; - }); - - // Pick the "--output" or "-O" flag, write to output - program.global_argument( - ["--output", "-O"], - |_, v| output = PathBuf::from(v) - ); - - program.exec(); -} -``` - -## 💡 Next Page -> **Basic Component** - Setup [Go](./pages/2-basic/2-setup) diff --git a/docs/pages/2-basic/2-setup.md b/docs/pages/2-basic/2-setup.md deleted file mode 100644 index 102e213..0000000 --- a/docs/pages/2-basic/2-setup.md +++ /dev/null @@ -1,150 +0,0 @@ -

Setup

-

- Mingling's Basic Components -

- ---- - -## Intro - -`Setup` is used to organize and package the initialization process of a `Program`, making the project easier to manage. - -## Usage - -It is defined as follows: - -```rust -struct MySetup; -impl ProgramSetup - for MySetup -{ - fn setup( - &mut self, - program: &mut Program - ) { - // Your setup logic - } -} -``` - -For example: - -```rust -use std::{env::current_dir, path::PathBuf}; - -use mingling::{ - Program, - macros::{dispatcher, gen_program, renderer}, - setup::ProgramSetup, -}; - -// Global state -static OUTPUT_PATH: std::sync::OnceLock - = std::sync::OnceLock::new(); - -fn main() { - let mut program = ThisProgram::new(); - program.with_setup(MySetup); - program.exec(); -} - -// Define two Dispatchers using `dispatcher!` -dispatcher!("member.add", - AddMemberCommand => AddMemberEntry); -dispatcher!("member.rm", - RemoveMemberCommand => RemoveMemberEntry); - -struct MySetup; -impl ProgramSetup for MySetup { - fn setup( - &mut self, program: &mut Program - ) { - // Register Dispatchers - program.with_dispatcher(AddMemberCommand); - program.with_dispatcher(RemoveMemberCommand); - - // Initialize global output once - OUTPUT_PATH.get_or_init(|| current_dir().unwrap()); - - // Pick the "--quiet" or "-q" flag - program.global_flag(["--quiet", "-q"], |p| { - // Disable render output - p.stdout_setting.render_output = false; - }); - - // Pick the "--output" or "-O" flag, write to output - program.global_argument(["--output", "-O"], |_, v| { - let _ = OUTPUT_PATH.set(PathBuf::from(v)); - }); - } -} - -gen_program!(); -``` - -## Simplified Syntax - -If you find the above declaration method too **verbose**, you can use the `program_setup!` macro to simplify it. The format is: - -```rust -#[program_setup] -fn my_setup( - program: &mut Program -) { - // Your setup logic -} -``` - -For example: - -```rust -use std::{env::current_dir, path::PathBuf}; - -use mingling::{ - Program, - macros::{ - dispatcher, - gen_program, - program_setup, - renderer - }, -}; - -static OUTPUT_PATH: std::sync::OnceLock - = std::sync::OnceLock::new(); - -#[tokio::main] -async fn main() { - let mut program = ThisProgram::new(); - program.with_setup(MySetup); - program.exec().await; -} - -dispatcher!("member.add", - AddMemberCommand => AddMemberEntry); -dispatcher!("member.rm", - RemoveMemberCommand => RemoveMemberEntry); - -#[program_setup] -fn my_setup( - program: &mut Program -) { - program.with_dispatcher(AddMemberCommand); - program.with_dispatcher(RemoveMemberCommand); - - OUTPUT_PATH.get_or_init(|| current_dir().unwrap()); - - program.global_flag(["--quiet", "-q"], |p| { - p.stdout_setting.render_output = false; - }); - - program.global_argument(["--output", "-O"], |_, v| { - let _ = OUTPUT_PATH.set(PathBuf::from(v)); - }); -} - -gen_program!(); -``` - -## 💡 Next Page -> **Basic Component** - Dispatcher [Go](./pages/2-basic/3-dispatcher) diff --git a/docs/pages/2-basic/3-dispatcher.md b/docs/pages/2-basic/3-dispatcher.md deleted file mode 100644 index 66e5c90..0000000 --- a/docs/pages/2-basic/3-dispatcher.md +++ /dev/null @@ -1,95 +0,0 @@ -

Dispatcher

-

- Mingling's Basic Components -

- ---- - -## Intro - -`Dispatcher` is a core concept in **Mingling**, used to dispatch user-input arguments to corresponding types, which are then handled by [Chain](pages/2-basic/4-chain) or [Renderer](pages/2-basic/5-renderer). - -To define a `Dispatcher`, it is recommended to use the `dispatcher!` macro provided by `mingling_macros`: - -```rust -// User input: your_bin hello -// Will access HelloCommand and -// dispatch arguments to HelloEntry -dispatcher!("hello", - HelloCommand => HelloEntry); - -// User input: your_bin sub foo -// Will access FooCommand and -// dispatch arguments to FooEntry -dispatcher!("sub.foo", - FooCommand => FooEntry); - -// Same as above -dispatcher!("sub.bar", - BarCommand => BarEntry); -``` - -If you explicitly specify a name in the `gen_program!` macro, for example: - -```rust -gen_program!(MyProgram); -``` - -Then when using the `dispatcher!` macro, you must also explicitly specify the [Program](pages/2-basic/1-program): - -```rust -dispatcher!(MyProgram, "hello", - HelloCommand => HelloEntry); -``` - -**Tips:** Finally, add the `Dispatcher` you created to the [Program](pages/2-basic/1-program): - -```rust -fn main() { - let mut program = ThisProgram::new(); - program.with_dispatcher(HelloCommand); - program.with_dispatcher(SubFooCommand); - program.with_dispatcher(SubBarCommand); - program.exec(); -} -``` - -## Manual Impl - -You can also manually implement the basic `Dispatcher` for more fine-grained control. However, compared to the procmacro, it is more cumbersome and cannot intelligently introduce certain traits based on the state of feature flags. - -```rust -// Define AddMemberEntry -// Use the `Groupped` derive to -// mark AddMemberEntry as a member of ThisProgram -#[derive(Debug, Groupped)] -pub struct AddMemberEntry { - // Define arguments to store user input - pub(crate) args: Vec, -} - -// Implement the Dispatcher trait -impl Dispatcher for AddMemberCommand { - // Return the node name of this Dispatcher - fn node(&self) -> Node { - node!("member.add") - } - - // When executing this Dispatcher, output AddMemberEntry - fn begin(&self, args: Vec) - -> ChainProcess - { - AnyOutput::new(AddMemberEntry { args }).route_chain() - } - - // Used to implement the clone trait for this Dispatcher - fn clone_dispatcher(&self) - -> Box> - { - Box::new(AddMemberCommand) - } -} -``` - -## 💡 Next Page -> **Basic Component** - Chain [Go](./pages/2-basic/4-chain) diff --git a/docs/pages/2-basic/4-chain.md b/docs/pages/2-basic/4-chain.md deleted file mode 100644 index d47642a..0000000 --- a/docs/pages/2-basic/4-chain.md +++ /dev/null @@ -1,75 +0,0 @@ -

Chain

-

- Mingling's Basic Components -

- ---- - -## Intro - -Like `Dispatcher`, `Chain` is also a core concept in building the entire **Mingling** framework. It is used to receive a dispatch of one type and convert it into another type. - -```rust -dispatcher!("hello", - HelloCommand => HelloEntry); - -// Define intermediate type ParsedHello, internally a String -pack!(ParsedHello = String); - -// Define chain parse_hello (expands to ParseHello) -// Declare conversion from HelloEntry -#[chain] -fn parse_hello(prev: HelloEntry) -> NextProcess { - // Take the inner reference of HelloEntry - let args = &*prev; - - // Extract the first argument, use default value "World" - // if it doesn't exist - let first = args.first().cloned().unwrap_or_else(|| "World".to_string()); - - // Pack the extracted argument into ParsedHello and - // dispatch to the next chain - ParsedHello::new(first).to_chain() -} -``` - -> [!Tip] -> `NextProcess` is a marker type in **Mingling**, from `mingling::marker`. -> -> It serves no functional purpose other than to simplify the declaration of chain functions. After the `chain!` macro expands, `NextProcess` will be replaced with `mingling::ChainProcess`. - -## Manual Impl - -You can also manually implement the basic `Chain` for finer control. - -However, please note that within the `chain!` macro, a `register_type!` macro is executed. This macro does not expand to any content; it only informs the `gen_program` context that this type exists. - -```rust -dispatcher!("hello", - HelloCommand => HelloEntry); - -pack!(ParsedHello = String); - -struct ParseHello; -impl Chain for ParseHello { - type Previous = HelloEntry; - fn proc(prev: Self::Previous) - -> ChainProcess - { - let args = &*prev; - let first = args - .first() - .cloned() - .unwrap_or_else(|| - "World".to_string() - ); - ParsedHello::new(first).to_chain() - } -} - -// Register chain to the context -register_chain!(HelloEntry, ParseHello); -``` - -## 💡 Next Page -> **Basic Component** - Renderer [Go](./pages/2-basic/5-renderer) diff --git a/docs/pages/2-basic/5-renderer.md b/docs/pages/2-basic/5-renderer.md deleted file mode 100644 index 2085d40..0000000 --- a/docs/pages/2-basic/5-renderer.md +++ /dev/null @@ -1,73 +0,0 @@ -

Renderer

-

- Mingling's Basic Components -

- ---- - -## Intro - -`Renderer` is similar to [Chain](pages/2-basic/4-chain) in that they both handle processing for a specific type. The difference is: [Chain](pages/2-basic/4-chain) transforms the type, while `Renderer` terminates the program and prints the information of that type to the terminal. - -A type can be processed by both [Chain](pages/2-basic/4-chain) and `Renderer`. If the type is `route_chain`ed, the system will search for a [Chain](pages/2-basic/4-chain) capable of handling that type. If none is found, it will automatically be routed to the `Renderer` to print the result of that type. - -The following example demonstrates how to handle rendering logic: - -```rust -dispatcher!("hello", - HelloCommand => HelloEntry); - -pack!(ParsedHello = String); - -// It's the Chain defined in the Dispatcher chapter -#[chain] -fn parse_hello(prev: HelloEntry) -> NextProcess { - let args = &*prev; - let first = args - .first() - .cloned() - .unwrap_or_else(|| - "World".to_string() - ); - - // Distribute the type to the Renderer - ParsedHello::new(first).to_render() -} - -// Define the renderer to -// handle rendering of ParsedHello -#[renderer] -fn render_hello(prev: ParsedHello) { - // Use r_println or r_print to - // render the content of ParsedHello - r_println!("Hello, {}!", *prev) -} -``` - -> [!Tip] -> `r_print!` can only be used inside a `Renderer`. This is because after the `renderer!` macro expands, it injects `r: &mut RenderResult` into the context. -> -> And `r_print!` directly writes content to the value `r`. -> This means: if there is no `&mut RenderResult` named `r` in the context, `r_print!` cannot be used. - -## Manual Impl - -Similarly, you can also manually implement `Renderer`, - -but note that inside the `renderer!` macro, a `register_type!` macro is executed. This macro itself does not expand into any content; it is only used to inform the `gen_program` context that the type exists: - -```rust -struct RenderHello; -impl Renderer for RenderHello { - type Previous = ParsedHello; - fn render( - prev: Self::Previous, - r: &mut RenderResult - ) { - r_println!("Hello, {}!", *prev) - } -} - -// Register renderer to the context -register_renderer!(ParsedHello, RenderHello); -``` -- cgit