From abbabd9c55daa79b07cd9ba81037568958794a91 Mon Sep 17 00:00:00 2001 From: 魏曹先生 <1992414357@qq.com> Date: Fri, 10 Jul 2026 16:23:18 +0800 Subject: chore(docs): rename dev-docs directory to dev Update sidebar link for remove-r-print-macro to use full description --- docs/dev-docs/pages/issues/.name | 1 - docs/dev-docs/pages/issues/remove-r-print-macro.md | 87 --------------------- docs/dev-docs/pages/issues/the-mod-pathfinder.md | 64 --------------- docs/dev-docs/pages/issues/the-shit-time.md | 90 ---------------------- 4 files changed, 242 deletions(-) delete mode 100644 docs/dev-docs/pages/issues/.name delete mode 100644 docs/dev-docs/pages/issues/remove-r-print-macro.md delete mode 100644 docs/dev-docs/pages/issues/the-mod-pathfinder.md delete mode 100644 docs/dev-docs/pages/issues/the-shit-time.md (limited to 'docs/dev-docs/pages/issues') diff --git a/docs/dev-docs/pages/issues/.name b/docs/dev-docs/pages/issues/.name deleted file mode 100644 index f99478d..0000000 --- a/docs/dev-docs/pages/issues/.name +++ /dev/null @@ -1 +0,0 @@ -Issues diff --git a/docs/dev-docs/pages/issues/remove-r-print-macro.md b/docs/dev-docs/pages/issues/remove-r-print-macro.md deleted file mode 100644 index e5ef4a6..0000000 --- a/docs/dev-docs/pages/issues/remove-r-print-macro.md +++ /dev/null @@ -1,87 +0,0 @@ -# Remove `r_print!` and `r_println!` Macros - -`r_print!` and `r_println!` are important macros in Mingling for use inside `#[help]` and `#[renderer]` functions, but their implementation is not clean: they implicitly introduce a `__renderer_inner_result` field. While this might look elegant at the API level, it is **incorrect** and even **objectionable**. - -## Why **Objectionable**? - -Because you can't define declarative macros with `macro_rules` that wrap them. - -This is because `r_println!` depends on the implicit variable `__renderer_inner_result` injected by the `#[renderer]` proc macro into the function body. However, when a `macro_rules` declarative macro expands, **its internal code is placed in the caller's context**, which does not contain `__renderer_inner_result` — that variable only exists within the direct scope of the function body processed by `#[renderer]`. - -Let's look at some code to see why: - -```rust -// Suppose you want to write a wrapper macro: -macro_rules! my_println { - ($($arg:tt)*) => { - // When expanded here, the context is the call site of my_println!, - // not the location where the renderer function's injected variables live. - // So __renderer_inner_result is NOT visible here! - r_println!("Custom: {}", format!($($arg)*)); - }; -} - -#[renderer] -fn render_something(_p: ResultSomething) { - // Although this function body has __renderer_inner_result injected, - // the code from my_println! does NOT expand "inside this function body" — - // macro_rules expansion is essentially text replacement. The replaced code - // lives at the line where my_println! is called, and any variables referenced - // inside that macro must resolve to identifiers accessible at the call site. - // __renderer_inner_result is not a public, path-accessible variable; - // it's a hygienic local variable generated by the `#[renderer]` macro, - // and external macros cannot directly access it by name. - my_println!("{}", box_val); // Compile error: cannot find __renderer_inner_result -} -``` - -## Deeper Issues - -I have to admit, this is an early design flaw. After re-examining the code, I found the problem goes beyond "can't be wrapped". - -This isn't just a "can't wrap" issue — it reflects that `r_println!`'s design fundamentally violates Rust's macro hygiene principles: - -- **Implicit dependency**: Users of the macro must know that a variable named `__renderer_inner_result` exists — but this variable is neither part of the public API nor explicitly documented anywhere. -- **Scope leakage**: Variables injected by a proc macro should be confined to the scope processed by that macro. But `r_println!` attempts to make that variable accessible across macro calls, which effectively breaks Rust's identifier hygiene. -- **Non-composable**: Any attempt to wrap `r_println!` will fail, because declarative macros cannot "pass through" access to implicit variables. Even using a proc macro to wrap it would encounter similar hygiene issues. - -## Desired New Syntax - -I've designed two alternative approaches and will choose based on actual needs. - -### Option 1: Explicit Return - -```rust -#[renderer] -fn render_something(prev: ResultSomething) -> RenderResult { - let mut result = RenderResult::new(); - result.println(prev.to_string()); - // or - write!(result, "{}", prev.to_string()); - - result // return here -} -``` - -Clear boundaries — the entire rendering process is confined within the function body decorated by `#[help]` or `#[renderer]`, without introducing extra out-of-scope dependencies. The trade-off is slightly more boilerplate compared to the original approach. - -### Option 2: Resource Injection - -```rust -#[renderer] -fn render_something(prev: ResultSomething, result: &mut ResRenderResult) { - result.println(prev.to_string()); - // or - write!(result, "{}", prev.to_string()); - - result // return here -} -``` - -More flexible, but blurs the boundary between logic functions like `#[chain]` and rendering functions like `#[help]`. - -### Preferred Direction - -I lean toward **Option 1 (Explicit Return)**. There's no need to turn `RenderResult` into `ResRenderResult` as a global resource. - -As for rendering in logic functions like `#[chain]`, that should be handled by a separate system — not discussed here. diff --git a/docs/dev-docs/pages/issues/the-mod-pathfinder.md b/docs/dev-docs/pages/issues/the-mod-pathfinder.md deleted file mode 100644 index 676251d..0000000 --- a/docs/dev-docs/pages/issues/the-mod-pathfinder.md +++ /dev/null @@ -1,64 +0,0 @@ -

The Mod Pathfinder

-

- A build-time analyzer that computes full module paths for Mingling types, resolving path ambiguity in macros. -

- -## Background - -Currently, `gen_program!` requires all involved types to be `use`d within their module. Mingling lacks a complete module path analyzer — waiting for `proc-macro-span` to stabilize is clearly not practical, so a solution for obtaining module paths is needed. - -## Solution - -We plan to create an analyzer called `mingling-mod-pathf`, enabled via Mingling's `"pathf"` feature, to compute the full paths of all defined Mingling types. - -### Behavior When Enabled - -**`mingling_core`**: If the `builds` feature is enabled, introduces the `mingling::build::analyze_and_build_type_mapping()` method (analysis completed at Build-Time) - -**`mingling_macros`**: Modifies the behavior of the `gen_program!()` macro — automatically loads the mapping table from the analysis file generated by `mingling::build::analyze_and_build_type_mapping()`, and directly uses the full `mod::path` instead of `TypeName` (injected at Compile-Time) - -## Challenges - -`mingling-mod-pathf` needs to understand **all** Mingling syntax features. -Fortunately, Mingling's type creation is almost always explicit: - -```rust -mod sub { - mingling::macros::pack!(ResultMyName = String); // directly creates ..::sub::ResultMyName -} -``` - -There are a few exceptions, such as the implicit Dispatcher provided by `extra_macros`, but these can be inferred from the node name: - -```rust -dispatcher!("remote.add"); // although the type is unknown, we can infer CMDRemoteAdd and EntryRemoteAdd -``` - -And also `#[program_setup]`: - -```rust -#[program_setup] // can infer CustomSetup from the function name `custom_setup` -fn custom_setup(program: &mut Program) { - program.with_dispatchers((CMD1, CMD2, CMD3, CMD4, CMD5)); -} -``` - -## Pathf Output Format - -Uses TOML key-value pairs, formatted as follows: - -```toml -ResultRemoteAdd = "crate::mymod::ResultRemoteAdd" -``` - -Recommended storage location is under the target directory: - -``` -/target/{target}/{crate-name}/type-mapping.toml -``` - -## Other Issues - -This solution is limited to Mingling's own syntax system. If types like `dispatcher!`, `pack!` are indirectly expanded through macros, the analyzer will not be able to discover them. - -However, this approach solves the current main pain points, so this issue can be set aside for now and addressed later. diff --git a/docs/dev-docs/pages/issues/the-shit-time.md b/docs/dev-docs/pages/issues/the-shit-time.md deleted file mode 100644 index f524f42..0000000 --- a/docs/dev-docs/pages/issues/the-shit-time.md +++ /dev/null @@ -1,90 +0,0 @@ -

Some Situations Where You'd Be Like "Shit!"

-

- This document collects the discomforts currently experienced while using Mingling. -

- -This document collects the discomforts currently experienced while using Mingling. - -Of course, you can also contribute to this document. - ---- - -## Why is there no fallback completion logic? - -(completion) (fallback) - -Currently, Mingling's Completion only supports providing completion logic for specific subcommands, with no way to provide global completion. - -For example: - -``` -mycmd -completion: ---help -h --- Display helps ---version -V --- Display versions -``` - -Currently, there is no workaround. - -Ideal solution: - -```rust -#[completion(EntryGlobal)] -fn complete(ctx: &ShellContext) -> Suggest { - // ... -} -``` - ---- - -## Why can't I register descriptions for commands? - -(completion) (dispatcher) - -Currently, Mingling's Completion cannot register a description for each subcommand. - -For example: - -``` -mycmd -completion: -add rm list <--- You cannot register descriptions for commands -``` - -Expected behavior: - -``` -mycmd -completion: -add --- Add something -rm --- Remove something -list --- List something -``` - -Ideal solution: - -```rust -// It should be able to freely integrate with crates that provide i18n functionality, -// so the following approach cannot be used as a data source for descriptions. -dispatcher! { - /// Add Something <--- How to i18n? - "add", CMDAdd => EntryAdd -} - -// Ideally, it should satisfy the following two conditions: -// 1. No need to use `with_dispatcher`, because `with_dispatcher` is disabled in `dispatch_tree` mode -// 2. Must be able to accept String or &str at runtime - -// Current idea -#[inline(always)] -#[dispatcher_desc(EntryAdd)] -fn desc_add() -> String { - // If using rust_i18n - t!("cmd.add.desc") -} - -// Collected and generated by `gen_program!()` -// Generate something like get_dispatcher_desc(id: &ThisProgram) -> String -// Match the corresponding function using enum values inside ThisProgram -gen_program!() -``` -- cgit