aboutsummaryrefslogtreecommitdiff
path: root/docs/pages/2-basic
diff options
context:
space:
mode:
Diffstat (limited to 'docs/pages/2-basic')
-rw-r--r--docs/pages/2-basic/1-program.md114
-rw-r--r--docs/pages/2-basic/2-setup.md150
-rw-r--r--docs/pages/2-basic/3-dispatcher.md95
-rw-r--r--docs/pages/2-basic/4-chain.md75
-rw-r--r--docs/pages/2-basic/5-renderer.md73
5 files changed, 0 insertions, 507 deletions
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 @@
-<h1 align="center">Program</h1>
-<p align="center">
- Mingling's Basic Components
-</p>
-
----
-
-## 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 @@
-<h1 align="center">Setup</h1>
-<p align="center">
- Mingling's Basic Components
-</p>
-
----
-
-## 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<ThisProgram>
- for MySetup
-{
- fn setup(
- &mut self,
- program: &mut Program<ThisProgram>
- ) {
- // 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<PathBuf>
- = 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<ThisProgram, ThisProgram> for MySetup {
- fn setup(
- &mut self, program: &mut Program<ThisProgram, ThisProgram>
- ) {
- // 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<ThisProgram>
-) {
- // 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<PathBuf>
- = 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<ThisProgram>
-) {
- 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 @@
-<h1 align="center">Dispatcher</h1>
-<p align="center">
- Mingling's Basic Components
-</p>
-
----
-
-## 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<String>,
-}
-
-// Implement the Dispatcher trait
-impl Dispatcher<ThisProgram> 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<String>)
- -> ChainProcess<ThisProgram>
- {
- AnyOutput::new(AddMemberEntry { args }).route_chain()
- }
-
- // Used to implement the clone trait for this Dispatcher
- fn clone_dispatcher(&self)
- -> Box<dyn Dispatcher<ThisProgram>>
- {
- 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 @@
-<h1 align="center">Chain</h1>
-<p align="center">
- Mingling's Basic Components
-</p>
-
----
-
-## 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<ThisProgram>`.
-
-## 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<ThisProgram> for ParseHello {
- type Previous = HelloEntry;
- fn proc(prev: Self::Previous)
- -> ChainProcess<ThisProgram>
- {
- 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 @@
-<h1 align="center">Renderer</h1>
-<p align="center">
- Mingling's Basic Components
-</p>
-
----
-
-## 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);
-```