diff options
| -rw-r--r-- | .vscode/settings.json | 18 | ||||
| -rw-r--r-- | .zed/settings.json | 34 | ||||
| -rw-r--r-- | CHANGELOG.md | 334 | ||||
| -rw-r--r-- | CONTRIBUTING.md | 54 | ||||
| -rw-r--r-- | Cargo.lock | 38 | ||||
| -rw-r--r-- | Cargo.toml | 9 | ||||
| -rw-r--r-- | arg_picker/Cargo.toml | 17 | ||||
| -rw-r--r-- | arg_picker/README.md (renamed from mingling_picker/README.md) | 10 | ||||
| -rw-r--r-- | arg_picker/src/arg.rs (renamed from mingling_picker/src/arg.rs) | 0 | ||||
| -rw-r--r-- | arg_picker/src/builtin.rs (renamed from mingling_picker/src/builtin.rs) | 0 | ||||
| -rw-r--r-- | arg_picker/src/builtin/pick_bool.rs (renamed from mingling_picker/src/builtin/pick_bool.rs) | 0 | ||||
| -rw-r--r-- | arg_picker/src/builtin/pick_flag.rs (renamed from mingling_picker/src/builtin/pick_flag.rs) | 0 | ||||
| -rw-r--r-- | arg_picker/src/builtin/pick_numbers.rs (renamed from mingling_picker/src/builtin/pick_numbers.rs) | 0 | ||||
| -rw-r--r-- | arg_picker/src/builtin/pick_string.rs (renamed from mingling_picker/src/builtin/pick_string.rs) | 0 | ||||
| -rw-r--r-- | arg_picker/src/corebind.rs (renamed from mingling_picker/src/corebind.rs) | 0 | ||||
| -rw-r--r-- | arg_picker/src/corebind/entry_picker.rs (renamed from mingling_picker/src/corebind/entry_picker.rs) | 0 | ||||
| -rw-r--r-- | arg_picker/src/infos.rs (renamed from mingling_picker/src/infos.rs) | 22 | ||||
| -rw-r--r-- | arg_picker/src/lib.rs (renamed from mingling_picker/src/lib.rs) | 6 | ||||
| -rw-r--r-- | arg_picker/src/parselib.rs (renamed from mingling_picker/src/parselib.rs) | 0 | ||||
| -rw-r--r-- | arg_picker/src/parselib/arg_matcher.rs (renamed from mingling_picker/src/parselib/arg_matcher.rs) | 0 | ||||
| -rw-r--r-- | arg_picker/src/parselib/flag_matcher.rs (renamed from mingling_picker/src/parselib/flag_matcher.rs) | 0 | ||||
| -rw-r--r-- | arg_picker/src/parselib/multi_arg_matcher.rs (renamed from mingling_picker/src/parselib/multi_arg_matcher.rs) | 0 | ||||
| -rw-r--r-- | arg_picker/src/parselib/pos_matcher.rs (renamed from mingling_picker/src/parselib/pos_matcher.rs) | 0 | ||||
| -rw-r--r-- | arg_picker/src/parselib/single_matcher.rs (renamed from mingling_picker/src/parselib/single_matcher.rs) | 0 | ||||
| -rw-r--r-- | arg_picker/src/parselib/style.rs (renamed from mingling_picker/src/parselib/style.rs) | 10 | ||||
| -rw-r--r-- | arg_picker/src/parselib/utils.rs (renamed from mingling_picker/src/parselib/utils.rs) | 0 | ||||
| -rw-r--r-- | arg_picker/src/pickable.rs (renamed from mingling_picker/src/pickable.rs) | 0 | ||||
| -rw-r--r-- | arg_picker/src/pickable/multi_pickable.rs (renamed from mingling_picker/src/pickable/multi_pickable.rs) | 0 | ||||
| -rw-r--r-- | arg_picker/src/pickable/single_pickable.rs (renamed from mingling_picker/src/pickable/single_pickable.rs) | 0 | ||||
| -rw-r--r-- | arg_picker/src/picker.rs (renamed from mingling_picker/src/picker.rs) | 2 | ||||
| -rw-r--r-- | arg_picker/src/picker/parse.rs (renamed from mingling_picker/src/picker/parse.rs) | 2 | ||||
| -rw-r--r-- | arg_picker/src/picker/patterns.rs (renamed from mingling_picker/src/picker/patterns.rs) | 2 | ||||
| -rw-r--r-- | arg_picker/src/picker/result.rs (renamed from mingling_picker/src/picker/result.rs) | 2 | ||||
| -rw-r--r-- | arg_picker/src/value.rs (renamed from mingling_picker/src/value.rs) | 0 | ||||
| -rw-r--r-- | arg_picker/src/value/flag.rs (renamed from mingling_picker/src/value/flag.rs) | 6 | ||||
| -rw-r--r-- | arg_picker/src/value/vec_until.rs (renamed from mingling_picker/src/value/vec_until.rs) | 0 | ||||
| -rw-r--r-- | arg_picker/test/Cargo.lock (renamed from mingling_picker/test/Cargo.lock) | 36 | ||||
| -rw-r--r-- | arg_picker/test/Cargo.toml (renamed from mingling_picker/test/Cargo.toml) | 4 | ||||
| -rw-r--r-- | arg_picker/test/src/lib.rs (renamed from mingling_picker/test/src/lib.rs) | 2 | ||||
| -rw-r--r-- | arg_picker/test/src/test.rs (renamed from mingling_picker/test/src/test.rs) | 0 | ||||
| -rw-r--r-- | arg_picker/test/src/test/arg_matcher_test.rs (renamed from mingling_picker/test/src/test/arg_matcher_test.rs) | 4 | ||||
| -rw-r--r-- | arg_picker/test/src/test/basic_test.rs (renamed from mingling_picker/test/src/test/basic_test.rs) | 2 | ||||
| -rw-r--r-- | arg_picker/test/src/test/multi_arg_test.rs (renamed from mingling_picker/test/src/test/multi_arg_test.rs) | 25 | ||||
| -rw-r--r-- | arg_picker/test/src/test/multi_value_test.rs (renamed from mingling_picker/test/src/test/multi_value_test.rs) | 4 | ||||
| -rw-r--r-- | arg_picker/test/src/test/pos_matcher_test.rs (renamed from mingling_picker/test/src/test/pos_matcher_test.rs) | 4 | ||||
| -rw-r--r-- | arg_picker/test/src/test/priority_test.rs (renamed from mingling_picker/test/src/test/priority_test.rs) | 4 | ||||
| -rw-r--r-- | arg_picker/test/src/test/route_test.rs (renamed from mingling_picker/test/src/test/route_test.rs) | 2 | ||||
| -rw-r--r-- | arg_picker/test/src/test/style_test.rs (renamed from mingling_picker/test/src/test/style_test.rs) | 8 | ||||
| -rw-r--r-- | arg_picker/test/src/test/value_flag_test.rs (renamed from mingling_picker/test/src/test/value_flag_test.rs) | 4 | ||||
| -rw-r--r-- | arg_picker/test/src/test/value_string_test.rs (renamed from mingling_picker/test/src/test/value_string_test.rs) | 2 | ||||
| -rw-r--r-- | arg_picker_macros/Cargo.toml (renamed from mingling_picker_macros/Cargo.toml) | 10 | ||||
| -rw-r--r-- | arg_picker_macros/README.md (renamed from mingling_picker_macros/README.md) | 0 | ||||
| -rw-r--r-- | arg_picker_macros/src/arg.rs (renamed from mingling_picker_macros/src/arg.rs) | 2 | ||||
| -rw-r--r-- | arg_picker_macros/src/internal_repeat.rs (renamed from mingling_picker_macros/src/internal_repeat.rs) | 0 | ||||
| -rw-r--r-- | arg_picker_macros/src/lib.rs (renamed from mingling_picker_macros/src/lib.rs) | 2 | ||||
| -rw-r--r-- | mingling/Cargo.toml | 4 | ||||
| -rw-r--r-- | mingling/src/lib.rs | 12 | ||||
| -rw-r--r-- | mingling_picker/Cargo.toml | 17 |
58 files changed, 360 insertions, 354 deletions
diff --git a/.vscode/settings.json b/.vscode/settings.json index 7472e1c..389a476 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,11 +1,11 @@ { - "rust-analyzer.check.command": "clippy", - "rust-analyzer.checkOnSave": true, - "rust-analyzer.linkedProjects": [ - ".run/Cargo.toml", - "mingling_picker/Cargo.toml", - "mingling_pathf/test/Cargo.toml", - "mingling_picker/test/Cargo.toml", - ], - "rust-analyzer.cargo.features": ["mingling_support"], + "rust-analyzer.check.command": "clippy", + "rust-analyzer.checkOnSave": true, + "rust-analyzer.linkedProjects": [ + ".run/Cargo.toml", + "mingling_pathf/test/Cargo.toml", + "arg_picker/Cargo.toml", + "arg_picker/test/Cargo.toml" + ], + "rust-analyzer.cargo.features": ["mingling_support"] } diff --git a/.zed/settings.json b/.zed/settings.json index 12c901e..103cc28 100644 --- a/.zed/settings.json +++ b/.zed/settings.json @@ -1,19 +1,19 @@ { - "lsp": { - "rust-analyzer": { - "initialization_options": { - "checkOnSave": true, - "check": { "command": "clippy" }, - "linkedProjects": [ - ".run/Cargo.toml", - "mingling_picker/Cargo.toml", - "mingling_pathf/test/Cargo.toml", - "mingling_picker/test/Cargo.toml", - ], - "cargo": { - "features": ["mingling_support"], - }, - }, - }, - }, + "lsp": { + "rust-analyzer": { + "initialization_options": { + "checkOnSave": true, + "check": { "command": "clippy" }, + "linkedProjects": [ + ".run/Cargo.toml", + "mingling_pathf/test/Cargo.toml", + "arg_picker/Cargo.toml", + "arg_picker/test/Cargo.toml" + ], + "cargo": { + "features": ["mingling_support"] + } + } + } + } } diff --git a/CHANGELOG.md b/CHANGELOG.md index ab4a170..ac00643 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -64,68 +64,68 @@ None 1. **[`core`]** Added `RenderResult::new()` method for creating a new `RenderResult` with default values (empty text and exit code 0). This provides a more explicit and discoverable constructor compared to `RenderResult::default()`, making it clearer when a fresh result is being created for use with `write!`/`writeln!`. - ```rust - let mut result = RenderResult::new(); - writeln!(result, "Hello!").ok(); - result - ``` + ```rust + let mut result = RenderResult::new(); + writeln!(result, "Hello!").ok(); + result + ``` - The method is equivalent to `RenderResult::default()` but serves as a more idiomatic entry point for renderer functions. + The method is equivalent to `RenderResult::default()` but serves as a more idiomatic entry point for renderer functions. 2. **[`core`]** **[`macros`]** Added `core` and `macros` features to the `mingling` crate, both enabled by default. These features allow selective exclusion of `mingling_core` and `mingling_macros` dependencies respectively. - - When `core` is **disabled** (`default-features = false, features = ["macros"]`), the `mingling` crate only re-exports proc-macros and macro-related items, without linking `mingling_core`. - - When `macros` is **disabled** (`default-features = false, features = ["core"]`), the `mingling` crate only provides runtime types and traits without any proc-macro re-exports. - - When **both are disabled** (`default-features = false`), the `mingling` crate provides a minimal re-export surface. + - When `core` is **disabled** (`default-features = false, features = ["macros"]`), the `mingling` crate only re-exports proc-macros and macro-related items, without linking `mingling_core`. + - When `macros` is **disabled** (`default-features = false, features = ["core"]`), the `mingling` crate only provides runtime types and traits without any proc-macro re-exports. + - When **both are disabled** (`default-features = false`), the `mingling` crate provides a minimal re-export surface. - This enables downstream projects to fine-tune dependency weight — e.g., a library crate that only uses `mingling_macros` can disable `core` to avoid pulling in unused runtime types. + This enables downstream projects to fine-tune dependency weight — e.g., a library crate that only uses `mingling_macros` can disable `core` to avoid pulling in unused runtime types. 3. **[`picker`]** Added the new `picker` system — a **non‑breaking companion** to the existing `parser` feature, not a replacement. The `picker` feature provides a chained argument parsing API and a parsing function library (`parselib`) for analyzing command-line argument structure. Key components: - - **Chained Argument Parser with `.pick()`** — A chained-call API for declaring and extracting arguments: + - **Chained Argument Parser with `.pick()`** — A chained-call API for declaring and extracting arguments: - ```rust - use mingling_picker::prelude::*; + ```rust + use arg_picker::prelude::*; - let args: Vec<&str> = vec!["--name", "Bob", "--age", "24"]; + let args: Vec<&str> = vec!["--name", "Bob", "--age", "24"]; - let (name, age) = args - .pick(&arg![name: String]) - .or(|| "Alice".to_string()) - .pick(&arg![age: i32]) - .or(|| 24) - .post(|num| num.clamp(0, 120)) - .unwrap(); - ``` + let (name, age) = args + .pick(&arg![name: String]) + .or(|| "Alice".to_string()) + .pick(&arg![age: i32]) + .or(|| 24) + .post(|num| num.clamp(0, 120)) + .unwrap(); + ``` - - **Pure function library `parselib`** — Provides utility functions for analyzing command-line argument structure: + - **Pure function library `parselib`** — Provides utility functions for analyzing command-line argument structure: - ```rust - use mingling_picker::parselib::*; - ``` + ```rust + use arg_picker::parselib::*; + ``` - The `picker` system is **additive** — the old `parser` feature remains fully functional and is **not deprecated**. Users may choose either or both systems in the same project. The `picker` feature is available both as the `mingling/picker` feature (enabled by default) and as a standalone `mingling_picker` crate. + The `picker` system is **additive** — the old `parser` feature remains fully functional and is **not deprecated**. Users may choose either or both systems in the same project. The `picker` feature is available both as the `mingling/picker` feature (enabled by default) and as a standalone `arg_picker` crate. - _No migration is required for existing `parser` users — the old API continues to work unchanged._ + _No migration is required for existing `parser` users — the old API continues to work unchanged._ #### **BREAKING CHANGES** (API CHANGES): 1. **[`macros:renderer`]** **[`macros:help`]** Removed `r_println!` and `r_print!` macros. The `#[renderer]` and `#[help]` macros no longer implicitly inject an internal `RenderResult` variable or provide `r_println!` / `r_print!` macros. - Renderers and help functions must now explicitly create and return a `RenderResult`: + Renderers and help functions must now explicitly create and return a `RenderResult`: - ```rust - use mingling::prelude::*; + ```rust + use mingling::prelude::*; - #[renderer] - fn render_greeting(greeting: ResultGreeting) -> RenderResult { - let mut result = RenderResult::new(); - writeln!(result, "Hello, {}!", *greeting).ok(); - result - } - ``` + #[renderer] + fn render_greeting(greeting: ResultGreeting) -> RenderResult { + let mut result = RenderResult::new(); + writeln!(result, "Hello, {}!", *greeting).ok(); + result + } + ``` - All examples, docs, and test cases across the repository have been updated to use the new pattern: creating a `RenderResult` with `RenderResult::new()` or `RenderResult::default()`, writing with `write!`/`writeln!` from `std::io::Write`, and returning the result. + All examples, docs, and test cases across the repository have been updated to use the new pattern: creating a `RenderResult` with `RenderResult::new()` or `RenderResult::default()`, writing with `write!`/`writeln!` from `std::io::Write`, and returning the result. --- @@ -160,7 +160,7 @@ None `"=> EntryList"` would incorrectly match as a substring of `"=> EntryListAlias,"`, causing a false duplicate registration detection. Now changed to use `find` + trailing character boundary validation, ensuring the character immediately after the match is not an identifier character (letter/digit/underscore). - Affected scope: Deduplication logic for `#[chain]`, `#[renderer]`, `#[help]`, and `#[completion]` registration. + Affected scope: Deduplication logic for `#[chain]`, `#[renderer]`, `#[help]`, and `#[completion]` registration. #### Optimizations: @@ -189,36 +189,36 @@ None 1. **[`core`]** - **Added complete unit test coverage**, adding `#[cfg(test)]` test modules for 23 modules in `mingling_core` that previously lacked tests, covering: - - **Core types** (`any.rs`): `AnyOutput` creation, downcast, type judgment, route routing, restore deserialization; `ChainProcess` type conversion; `NextProcess` formatting - - **Dispatcher** (`dispatcher.rs`): Conversion of `Dispatchers` from 1~7 tuples, Vec, Box; Deref dereferencing; clone behavior - - **Node** (`node.rs`): Construction, join, kebab-case conversion, equality comparison, sorting - - **Global resource** (`global_resource.rs`): `GlobalResource` new, Deref, AsRef; three default implementations of `ResourceMarker` - - **Lazy resource** (`lazy_resource.rs`): Coverage of all 18+ methods of `LazyRes`, including initialization triggering, get_ref/get_mut/get_clone, into_inner/unwrap, Drop callback, `ResourceMarker` integration - - **Error types** (`chain/error.rs`, `program/error.rs`): All Display, Error source, From conversions - - **Configuration structs** (`config.rs`): Default values for `ProgramStdoutSetting`, `ProgramUserContext`; FromStr parsing and Display output of `StructuralRendererSetting` (feature-gated) - - **Flag system** (`flag.rs`): Added 8 From conversions, Deref, AsRef for `Flag` - - **String wrapper** (`string_vec.rs`): 6 From conversions, Deref, Into\<Vec\> - - **Render result** (`render_result.rs`): print/println/clear/is_empty, Write trait, Display, Deref, From conversions - - **Render error** (`structural/error.rs`): Construction, From, Deref, Into\<String\> - - **Structural renderer** (`structural.rs`): Rendering in Disable/JSON/YAML/TOML/RON formats (feature-gated) - - **Completion suggestions** (`suggest.rs`): All construction, access, modification, sorting, and conversion methods for `Suggest` and `SuggestItem` - - **Shell context** (`shell_ctx.rs`): Added `filling_argument`, `filling_argument_first`, `typing_argument`, `strip_typed_argument`, `get_typed_arguments` - - **Hook system** (`hook.rs`): `ProgramHook::empty` and all 8 builder methods - - **Singleton management** (`single_instance.rs`): `ProgramCell` set/get_raw/take/double-set-panic - - **Program setup** (`setup.rs`): Verification of `with_setup` invocation - - **Completion detection** (`comp_ctx.rs`): Three scenarios for `is_completing` - - **Build script** (`builds/comp.rs`): `get_tmpl` for four Shells and Other fallback + - **Core types** (`any.rs`): `AnyOutput` creation, downcast, type judgment, route routing, restore deserialization; `ChainProcess` type conversion; `NextProcess` formatting + - **Dispatcher** (`dispatcher.rs`): Conversion of `Dispatchers` from 1~7 tuples, Vec, Box; Deref dereferencing; clone behavior + - **Node** (`node.rs`): Construction, join, kebab-case conversion, equality comparison, sorting + - **Global resource** (`global_resource.rs`): `GlobalResource` new, Deref, AsRef; three default implementations of `ResourceMarker` + - **Lazy resource** (`lazy_resource.rs`): Coverage of all 18+ methods of `LazyRes`, including initialization triggering, get_ref/get_mut/get_clone, into_inner/unwrap, Drop callback, `ResourceMarker` integration + - **Error types** (`chain/error.rs`, `program/error.rs`): All Display, Error source, From conversions + - **Configuration structs** (`config.rs`): Default values for `ProgramStdoutSetting`, `ProgramUserContext`; FromStr parsing and Display output of `StructuralRendererSetting` (feature-gated) + - **Flag system** (`flag.rs`): Added 8 From conversions, Deref, AsRef for `Flag` + - **String wrapper** (`string_vec.rs`): 6 From conversions, Deref, Into\<Vec\> + - **Render result** (`render_result.rs`): print/println/clear/is_empty, Write trait, Display, Deref, From conversions + - **Render error** (`structural/error.rs`): Construction, From, Deref, Into\<String\> + - **Structural renderer** (`structural.rs`): Rendering in Disable/JSON/YAML/TOML/RON formats (feature-gated) + - **Completion suggestions** (`suggest.rs`): All construction, access, modification, sorting, and conversion methods for `Suggest` and `SuggestItem` + - **Shell context** (`shell_ctx.rs`): Added `filling_argument`, `filling_argument_first`, `typing_argument`, `strip_typed_argument`, `get_typed_arguments` + - **Hook system** (`hook.rs`): `ProgramHook::empty` and all 8 builder methods + - **Singleton management** (`single_instance.rs`): `ProgramCell` set/get_raw/take/double-set-panic + - **Program setup** (`setup.rs`): Verification of `with_setup` invocation + - **Completion detection** (`comp_ctx.rs`): Three scenarios for `is_completing` + - **Build script** (`builds/comp.rs`): `get_tmpl` for four Shells and Other fallback 2. **[`core`]** - **Added 6 integration test crates**, testing public APIs under different feature combinations: - - `test-basic`: Basic type tests with default features (Node, Flag, RenderResult, NextProcess, StringVec) - - `test-comp`: ShellContext, Suggest, SuggestItem, is_completing with `comp + builds` features - - `test-structural-renderer`: StructuralRenderer output in various formats with `structural_renderer_full + parser` features - - `test-repl`: ResREPL and basic types with `repl + extra_macros` features - - `test-dispatch-tree`: Basic types with `dispatch_tree` feature - - `test-all`: Comprehensive testing with all feature combinations (ShellContext, Suggest, ResREPL, StructuralRenderer, Hooks, basic types, etc.) + - `test-basic`: Basic type tests with default features (Node, Flag, RenderResult, NextProcess, StringVec) + - `test-comp`: ShellContext, Suggest, SuggestItem, is_completing with `comp + builds` features + - `test-structural-renderer`: StructuralRenderer output in various formats with `structural_renderer_full + parser` features + - `test-repl`: ResREPL and basic types with `repl + extra_macros` features + - `test-dispatch-tree`: Basic types with `dispatch_tree` feature + - `test-all`: Comprehensive testing with all feature combinations (ShellContext, Suggest, ResREPL, StructuralRenderer, Hooks, basic types, etc.) - These crates are located in `mingling_core/tests/test-*/`, each marked as an independent workspace via `[workspace]`, isolated from the main workspace. + These crates are located in `mingling_core/tests/test-*/`, each marked as an independent workspace via `[workspace]`, isolated from the main workspace. 3. **[`workspace`]** - **Added workspace exclude rules for the 6 test crates in the root `Cargo.toml`**, ensuring that integration test crates are not captured by the workspace's implicit member rules. @@ -229,33 +229,33 @@ None 2. **[`core:comp`]** Fixed `default_completion` jumping to the next subcommand level on partial input (e.g. typing `b` for `bind` would skip `bind` and directly suggest third-level commands `add`/`ls`/`rm`). Now if the last input word is only a partial match (`starts_with` but not equal), the current-level word is suggested instead of skipping ahead 3. **[`core`]** Replaced `OnceLock<Option<Box<dyn Any>>>` with a custom `ProgramCell` type backed by `UnsafeCell` and `AtomicBool`. The new `ProgramCell` replaces `OnceLock`'s `get_or_init` / `get` / `as_ref` calls with a direct `set` / `get_raw` / `take` API. This change: - - Eliminates the double indirection (`OnceLock<Option<Box<...>>>` → `UnsafeCell<Option<Box<...>>>`) - - Allows the program instance to be **taken** (moved out) via an `unsafe fn take()` after execution completes, enabling proper cleanup before `std::process::exit()` in `exec_and_exit` - - Is paired with corresponding simplifications in `once_exec.rs` and `repl_exec.rs` that switch from `THIS_PROGRAM.get().unwrap().as_ref()` to `THIS_PROGRAM.get_raw().unwrap()` + - Eliminates the double indirection (`OnceLock<Option<Box<...>>>` → `UnsafeCell<Option<Box<...>>>`) + - Allows the program instance to be **taken** (moved out) via an `unsafe fn take()` after execution completes, enabling proper cleanup before `std::process::exit()` in `exec_and_exit` + - Is paired with corresponding simplifications in `once_exec.rs` and `repl_exec.rs` that switch from `THIS_PROGRAM.get().unwrap().as_ref()` to `THIS_PROGRAM.get_raw().unwrap()` 4. **[`macros:dispatcher_clap`]** Added `dispatch_tree` feature integration for `#[dispatcher_clap]`. When the `dispatch_tree` feature is enabled, `#[dispatcher_clap]` will now automatically register the dispatcher and entry in the dispatch tree via `register_dispatcher!`, matching the behavior already present in the `dispatcher!` macro. When the feature is disabled, no additional code is generated. 5. **[`macros`]** The four macros `#[chain]`, `#[renderer]`, `#[help]`, and `#[completion]` now support using fully qualified type paths with `::` (e.g. `crate::EntryFine`) as type inputs. Previously, these macros required types to be bare single-segment idents (e.g. `EntryFine`), rejecting reasonable paths like `crate::EntryFine`. Specific changes: - - `res_injection::extract_args_info` (shared by `#[chain]` and `#[renderer]`): Removed the single-segment validation for the first parameter type - - `#[renderer]` / `#[help]`: Removed respective `check_single_segment_type` calls - - `#[completion]`: Attribute parameter parsing changed from `Ident` to `TypePath`, supporting `#[completion(crate::EntryFine)]` - - Fixed code generation in `build_chain_arm`, `build_chain_exist_arm`, `build_renderer_entry`, `build_renderer_exist_entry`, `build_general_renderer_entry`, and completion entry: `Self::#variant` match arms now only take the last segment ident of the type path (e.g. `Self::EntryFine`), rather than concatenating the full path directly (which would generate invalid syntax like `Self::crate::EntryFine`), while `downcast::<T>()` and `type Previous = T` still use the full path to ensure correct type resolution + - `res_injection::extract_args_info` (shared by `#[chain]` and `#[renderer]`): Removed the single-segment validation for the first parameter type + - `#[renderer]` / `#[help]`: Removed respective `check_single_segment_type` calls + - `#[completion]`: Attribute parameter parsing changed from `Ident` to `TypePath`, supporting `#[completion(crate::EntryFine)]` + - Fixed code generation in `build_chain_arm`, `build_chain_exist_arm`, `build_renderer_entry`, `build_renderer_exist_entry`, `build_general_renderer_entry`, and completion entry: `Self::#variant` match arms now only take the last segment ident of the type path (e.g. `Self::EntryFine`), rather than concatenating the full path directly (which would generate invalid syntax like `Self::crate::EntryFine`), while `downcast::<T>()` and `type Previous = T` still use the full path to ensure correct type resolution 6. **[`macros:register`]** Added compile-time duplicate variant detection for chain, renderer, help, and completion registrations. When two `#[chain]` (or `#[renderer]`, `#[help]`, `#[completion]`) functions register the same type variant, the compiler now emits a clear error at the registration site (e.g. `fn handle_state_prev1(_p: StatePrev1)`) instead of silently producing an unreachable match arm that only manifests as dead code in the generated `do_chain()`/`render()` dispatch. - Affected registration points: - - `register_chain` — checks `CHAINS` set for existing entries with the same variant - - `register_renderer` — checks `RENDERERS` set - - `help_attr` (via `#[help]`) + `register_help` — checks `HELP_REQUESTS`; `register_help` also serves as a public escape hatch for manual help registration, automatically skipping the duplicate check when the exact same entry was pre-inserted by `#[help]` - - `completion_attr` (via `#[completion]`) — checks `COMPLETIONS` set + Affected registration points: + - `register_chain` — checks `CHAINS` set for existing entries with the same variant + - `register_renderer` — checks `RENDERERS` set + - `help_attr` (via `#[help]`) + `register_help` — checks `HELP_REQUESTS`; `register_help` also serves as a public escape hatch for manual help registration, automatically skipping the duplicate check when the exact same entry was pre-inserted by `#[help]` + - `completion_attr` (via `#[completion]`) — checks `COMPLETIONS` set 7. **[`macros:dispatch_tree`]** Fixed the static name generation for dispatch tree nodes to use `snake_case` conversion instead of simple `.` → `_` replacement, and fixed the `__comp` completion dispatcher static name from `__internal_dispatcher___comp` (triple underscore) to `__internal_dispatcher_comp` (double underscore), resolving a mismatch between the name generated by `register_dispatcher!` and the name used in `program_comp_gen`. 8. **[`core`]** Changed the `exec_without_render` and `exec` methods' behavior: when `stdout_setting.render_output` is `false` or the result is empty, the exit code from the result is now returned instead of hardcoded `0`. This ensures that programs which set a non-zero exit code without producing renderable output (e.g., via `ExitCodeSetup` or `ProgramControlUnit::OverrideExitCode`) will exit with the correct code. Specific changes in `once_exec.rs`: - - `exec()` (async) and `exec_without_render_and_print()` (sync): The `exit_code` is now read from the result before the render check, and returned as the fallback value instead of `0` when output is not printed. - - This means `ExitCode` / `ProgramControls` overrides are now respected regardless of whether any output is rendered. + - `exec()` (async) and `exec_without_render_and_print()` (sync): The `exit_code` is now read from the result before the render check, and returned as the fallback value instead of `0` when output is not printed. + - This means `ExitCode` / `ProgramControls` overrides are now respected regardless of whether any output is rendered. #### Optimizations: @@ -457,20 +457,20 @@ fn main() { The pathfinder system consists of: - **`mingling_pathf` sub-crate** — A standalone crate for build-time source analysis: - - `module_pathf::analyze()` — Scans the crate's source tree and infers module paths from the directory structure - - `pattern_analyzer::init()` — Creates a `PatternAnalyzer` registered with all supported Mingling patterns - - `analyze_and_build_type_mapping()` / `analyze_and_build_type_mapping_for()` — Convenience functions for build scripts - - **Pattern matchers** — Individual pattern implementations for each Mingling macro: - - `PackPattern` — Matches `pack!`, `pack_err!`, `pack_structural!`, `pack_err_structural!` invocations - - `GroupPattern` — Matches `group!` and `group_structural!` invocations - - `GrouppedDerivePattern` — Matches `#[derive(Groupped)]` and `#[derive(GrouppedSerialize)]` - - `ChainPattern` — Matches `#[chain]` functions, extracts `__internal_chain_*` names - - `RendererPattern` — Matches `#[renderer]` functions, extracts `__internal_renderer_*` names - - `HelpPattern` — Matches `#[help]` functions, extracts `__internal_help_*` names - - `CompletionPattern` — Matches `#[completion(T)]` functions, extracts `__internal_completion_*` names - - `DispatcherPattern` — Matches `dispatcher!` invocations, extracts entry type names (supports both explicit and implicit forms) - - `DispatcherClapPattern` — Matches `#[dispatcher_clap]` structs, extracts struct names - - `type_mapping_builder` — Assembles the mapping from all analyzed files and writes `MAPPING` and `type_using.rs` output files + - `module_pathf::analyze()` — Scans the crate's source tree and infers module paths from the directory structure + - `pattern_analyzer::init()` — Creates a `PatternAnalyzer` registered with all supported Mingling patterns + - `analyze_and_build_type_mapping()` / `analyze_and_build_type_mapping_for()` — Convenience functions for build scripts + - **Pattern matchers** — Individual pattern implementations for each Mingling macro: + - `PackPattern` — Matches `pack!`, `pack_err!`, `pack_structural!`, `pack_err_structural!` invocations + - `GroupPattern` — Matches `group!` and `group_structural!` invocations + - `GrouppedDerivePattern` — Matches `#[derive(Groupped)]` and `#[derive(GrouppedSerialize)]` + - `ChainPattern` — Matches `#[chain]` functions, extracts `__internal_chain_*` names + - `RendererPattern` — Matches `#[renderer]` functions, extracts `__internal_renderer_*` names + - `HelpPattern` — Matches `#[help]` functions, extracts `__internal_help_*` names + - `CompletionPattern` — Matches `#[completion(T)]` functions, extracts `__internal_completion_*` names + - `DispatcherPattern` — Matches `dispatcher!` invocations, extracts entry type names (supports both explicit and implicit forms) + - `DispatcherClapPattern` — Matches `#[dispatcher_clap]` structs, extracts struct names + - `type_mapping_builder` — Assembles the mapping from all analyzed files and writes `MAPPING` and `type_using.rs` output files - **Integration with `gen_program!()`** — When the `pathf` feature is enabled, `gen_program!()` includes the generated `type_using.rs` file via `include!()`, making all type paths available in scope for the generated dispatch code. @@ -504,29 +504,29 @@ The following explicit syntaxes are **removed**: 1. **[`core`]** **[`structural_renderer`]** Renamed the `general_renderer` feature to `structural_renderer`. All associated types, structs, and APIs have been renamed accordingly: - - Feature flag: `general_renderer` → `structural_renderer` - - Setup struct: `GeneralRendererSetup` → `StructuralRendererSetup` - - Simple setup struct: `GeneralRendererSimpleSetup` → `StructuralRendererSimpleSetup` - - Renderer type: `GeneralRenderer` → `StructuralRenderer` - - Setting enum: `GeneralRendererSetting` → `StructuralRendererSetting` - - Error type: `GeneralRendererSerializeError` → `StructuralRendererSerializeError` - - Field name: `program.general_renderer_name` → `program.structural_renderer_name` - - Trait method: `ProgramCollect::general_render()` → `ProgramCollect::structural_render()` - - Internal module: `mingling_core::renderer::general` → `mingling::renderer::structural` - - Internal static: `GENERAL_RENDERERS` → `STRUCTURAL_RENDERERS` - - Feature gate attributes: `#[cfg(feature = "general_renderer")]` → `#[cfg(feature = "structural_renderer")]` - - Sub-features: `general_renderer_empty` → `structural_renderer_empty`, `general_renderer_full` → `structural_renderer_full` - - Runtime feature constant: `MINGLING_GENERAL_RENDERER` → `MINGLING_STRUCTURAL_RENDERER` (and similarly for `_EMPTY` and `_FULL`) - - Derive macro feature gate: `#[cfg(feature = "general_renderer")]` on `#[derive(StructuralData)]` and `#[derive(GrouppedSerialize)]` → `#[cfg(feature = "structural_renderer")]` - - Example project: `example-general-renderer` renamed to `example-structural-renderer` - - Test crate: `test-general-renderer` renamed to `test-structural-renderer` + - Feature flag: `general_renderer` → `structural_renderer` + - Setup struct: `GeneralRendererSetup` → `StructuralRendererSetup` + - Simple setup struct: `GeneralRendererSimpleSetup` → `StructuralRendererSimpleSetup` + - Renderer type: `GeneralRenderer` → `StructuralRenderer` + - Setting enum: `GeneralRendererSetting` → `StructuralRendererSetting` + - Error type: `GeneralRendererSerializeError` → `StructuralRendererSerializeError` + - Field name: `program.general_renderer_name` → `program.structural_renderer_name` + - Trait method: `ProgramCollect::general_render()` → `ProgramCollect::structural_render()` + - Internal module: `mingling_core::renderer::general` → `mingling::renderer::structural` + - Internal static: `GENERAL_RENDERERS` → `STRUCTURAL_RENDERERS` + - Feature gate attributes: `#[cfg(feature = "general_renderer")]` → `#[cfg(feature = "structural_renderer")]` + - Sub-features: `general_renderer_empty` → `structural_renderer_empty`, `general_renderer_full` → `structural_renderer_full` + - Runtime feature constant: `MINGLING_GENERAL_RENDERER` → `MINGLING_STRUCTURAL_RENDERER` (and similarly for `_EMPTY` and `_FULL`) + - Derive macro feature gate: `#[cfg(feature = "general_renderer")]` on `#[derive(StructuralData)]` and `#[derive(GrouppedSerialize)]` → `#[cfg(feature = "structural_renderer")]` + - Example project: `example-general-renderer` renamed to `example-structural-renderer` + - Test crate: `test-general-renderer` renamed to `test-structural-renderer` 2. **[`core`]** Changed the signature of `ProgramSetup::setup` from `fn setup(&mut self, program: &mut Program<C>) -> S` to `fn setup(self, program: &mut Program<C>)`, consuming `self` instead of taking a mutable reference. Correspondingly, `Program::with_setup` now accepts `S` by value (`&mut self, setup: S`) instead of by mutable reference (`&mut self, setup: &mut S`). 3. **[`core`]** Consolidated resource naming for `ExitCode` and `REPL`: - - Renamed `ExitCode` to `ResExitCode` and moved `ResREPL` from the `mingling` root to `mingling::res::ResREPL` (the `mingling::ResREPL` re-export is removed). - - This aligns with the naming convention where resources are prefixed with `Res`. - - The corresponding setup `ExitCodeSetup` and resource injection remain unchanged. + - Renamed `ExitCode` to `ResExitCode` and moved `ResREPL` from the `mingling` root to `mingling::res::ResREPL` (the `mingling::ResREPL` re-export is removed). + - This aligns with the naming convention where resources are prefixed with `Res`. + - The corresponding setup `ExitCodeSetup` and resource injection remain unchanged. ```rust // Before @@ -538,25 +538,25 @@ use mingling::{res::ResExitCode, res::ResREPL}; 4. **[`core`]** **[`macros`]** Migrated `to_chain()` and `to_render()` methods from being generated individually per type by `#[derive(Groupped)]` and `pack!` macros, to being provided as default trait methods on the `Groupped` trait itself. - Previously, each packed or derived type had its own inherent `to_chain()` and `to_render()` methods generated by the macros. Now, these methods are defined on the `Groupped<Group>` trait with default implementations, making them available to all types that implement the trait without redundant code generation. + Previously, each packed or derived type had its own inherent `to_chain()` and `to_render()` methods generated by the macros. Now, these methods are defined on the `Groupped<Group>` trait with default implementations, making them available to all types that implement the trait without redundant code generation. - ```rust - // Before (generated per type by macros): - impl MyType { - pub fn to_chain(self) -> ChainProcess<Group> { - AnyOutput::new(self).route_chain() - } - pub fn to_render(self) -> ChainProcess<Group> { - AnyOutput::new(self).route_renderer() - } - } + ```rust + // Before (generated per type by macros): + impl MyType { + pub fn to_chain(self) -> ChainProcess<Group> { + AnyOutput::new(self).route_chain() + } + pub fn to_render(self) -> ChainProcess<Group> { + AnyOutput::new(self).route_renderer() + } + } - // After (provided by Groupped trait default methods): - // just ensure Groupped is implemented — to_chain() and to_render() - // are automatically available - ``` + // After (provided by Groupped trait default methods): + // just ensure Groupped is implemented — to_chain() and to_render() + // are automatically available + ``` - Removed the per-type inherent method generation from both `groupped.rs` and `pack.rs` in `mingling_macros`. + Removed the per-type inherent method generation from both `groupped.rs` and `pack.rs` in `mingling_macros`. 5. **[`macros`]** Changed the `route!()` macro's error branch from `return e` to `return ::mingling::Groupped::to_chain(e)`, so that the error type no longer needs to be pre-converted to `ChainProcess` via `.to_chain()` or `.to_render()`. The macro now accepts any type implementing `Groupped` in the error position and automatically converts it. @@ -570,43 +570,43 @@ let value = route!(prev.pick_or_route((), Error::default()).unpack()); 6. **[`core`]** **[`hook`]** Refactored the hook system to use structured info types and return `ProgramControls<C>` instead of raw values. - The hook system has been redesigned for better type safety, extensibility, and control flow management: + The hook system has been redesigned for better type safety, extensibility, and control flow management: - - **All hook callbacks now receive structured info types** (e.g., `&HookPreDispatchInfo`, `&HookPostChainInfo<C>`) instead of raw tuples or bare values. Each hook event has a dedicated info struct with named fields, making hook signatures self-documenting and easier to evolve. + - **All hook callbacks now receive structured info types** (e.g., `&HookPreDispatchInfo`, `&HookPostChainInfo<C>`) instead of raw tuples or bare values. Each hook event has a dedicated info struct with named fields, making hook signatures self-documenting and easier to evolve. - - Hook signatures changed from `fn(...)` to `Box<dyn Fn(&InfoType) -> R>`, with `R: Into<ProgramControls<C>>`. Closures that return `()`are automatically converted to`ProgramControls::Empty`via the`From<()>` impl. + - Hook signatures changed from `fn(...)` to `Box<dyn Fn(&InfoType) -> R>`, with `R: Into<ProgramControls<C>>`. Closures that return `()`are automatically converted to`ProgramControls::Empty`via the`From<()>` impl. - ```rust - // Before - .on_begin(|| println!("Program started")) - .on_pre_dispatch(|args| println!("Dispatching: {args:?}")) - .on_finish(|| 0) // returns i32 as exit code + ```rust + // Before + .on_begin(|| println!("Program started")) + .on_pre_dispatch(|args| println!("Dispatching: {args:?}")) + .on_finish(|| 0) // returns i32 as exit code - // After - .on_begin::<_, ()>(|_| println!("Program started")) - .on_pre_dispatch(|info| println!("Dispatching: {}", info.arguments.join(" "))) - .on_finish(|_| ProgramControlUnit::OverrideExitCode(0)) - ``` + // After + .on_begin::<_, ()>(|_| println!("Program started")) + .on_pre_dispatch(|info| println!("Dispatching: {}", info.arguments.join(" "))) + .on_finish(|_| ProgramControlUnit::OverrideExitCode(0)) + ``` - - **Added `ProgramControls<C>` and `ProgramControlUnit<C>`** — a new control flow system that replaces the previous approach where only the `finish` hook could return a value (exit code). Now any hook can issue control instructions: - - `ProgramControlUnit::OverrideExitCode(i32)` — override the program's exit code - - `ProgramControlUnit::RouteToChain(AnyOutput<C>)` — route to another chain processor - - `ProgramControlUnit::RouteToRender(AnyOutput<C>)` — route directly to the renderer - - `ProgramControlUnit::RouteToHelp(AnyOutput<C>)` — route to help display + - **Added `ProgramControls<C>` and `ProgramControlUnit<C>`** — a new control flow system that replaces the previous approach where only the `finish` hook could return a value (exit code). Now any hook can issue control instructions: + - `ProgramControlUnit::OverrideExitCode(i32)` — override the program's exit code + - `ProgramControlUnit::RouteToChain(AnyOutput<C>)` — route to another chain processor + - `ProgramControlUnit::RouteToRender(AnyOutput<C>)` — route directly to the renderer + - `ProgramControlUnit::RouteToHelp(AnyOutput<C>)` — route to help display - - **Added `handle_program_control` function** in `exec.rs` that processes `ProgramControls` returned by hooks, updating the current execution state (exit code, current `AnyOutput`) or triggering early returns (e.g., routing to render/help). + - **Added `handle_program_control` function** in `exec.rs` that processes `ProgramControls` returned by hooks, updating the current execution state (exit code, current `AnyOutput`) or triggering early returns (e.g., routing to render/help). - - **`ExitCodeSetup` updated** — its `on_finish` hook now returns `ProgramControlUnit::OverrideExitCode(this.exit_code)` instead of just `this.exit_code`. + - **`ExitCodeSetup` updated** — its `on_finish` hook now returns `ProgramControlUnit::OverrideExitCode(this.exit_code)` instead of just `this.exit_code`. - - **`HookPostReadlineInfo` now wraps `line: &mut String`** — the `repl_post_readline` hook receives a structured info object instead of a raw `&mut String`. + - **`HookPostReadlineInfo` now wraps `line: &mut String`** — the `repl_post_readline` hook receives a structured info object instead of a raw `&mut String`. - - **`HookOnReceiveResultInfo` now wraps `result: &RenderResult`** — the `repl_on_receive_result` hook receives the result through an info struct with a `.result` field instead of directly. + - **`HookOnReceiveResultInfo` now wraps `result: &RenderResult`** — the `repl_on_receive_result` hook receives the result through an info struct with a `.result` field instead of directly. - - **`hook` module made public** — moved from `#[doc(hidden)]` to a documented public module (`pub mod hook`), along with all associated info types and control unit types. + - **`hook` module made public** — moved from `#[doc(hidden)]` to a documented public module (`pub mod hook`), along with all associated info types and control unit types. - - **Added `dispatch_args_trie` default method** on `ProgramCollect` (behind `#[cfg(not(feature = "dispatch_tree"))]`) that calls `unreachable!()` by default, avoiding `#[cfg]` gymnastics in `exec.rs`. + - **Added `dispatch_args_trie` default method** on `ProgramCollect` (behind `#[cfg(not(feature = "dispatch_tree"))]`) that calls `unreachable!()` by default, avoiding `#[cfg]` gymnastics in `exec.rs`. - - **Examples and internal callers updated** throughout the codebase to use the new hook API patterns. + - **Examples and internal callers updated** throughout the codebase to use the new hook API patterns. 7. **[`core`]** **[`structural_renderer`]** Added the `pack_err_structural!`, `pack_structural!`, and `group_structural!` macros for creating types that support structured output (JSON/YAML/TOML/RON). These are like `pack_err!`, `pack!`, and `group!` respectively, but also mark the type with the `StructuralData` trait, enabling the `StructuralRenderer` to serialize them. @@ -634,8 +634,8 @@ When the `structural_renderer` feature is enabled, `ResultEmpty` also derives `S #### Fixes: 1. **[`macros:dispatcher_clap`]** Fixed the issue where clap error messages (`DisplayHelp` and parse errors from `try_parse_from`) could not output ANSI - - For error paths, use `e.render().ansi()` instead of `e.to_string()` to prevent ANSI codes from being stripped by `strip_str` in `StyledStr::Display` - - For help info paths, use with `BasicProgramSetup`, output ANSI-colored help content through the mingling framework's `render_help` flow + - For error paths, use `e.render().ansi()` instead of `e.to_string()` to prevent ANSI codes from being stripped by `strip_str` in `StyledStr::Display` + - For help info paths, use with `BasicProgramSetup`, output ANSI-colored help content through the mingling framework's `render_help` flow #### Optimizations: @@ -675,8 +675,8 @@ fn handle_path_pick(prev: PathPick) { ``` 3. **[`macros`]** Extended the `#[renderer]` attribute to support custom return types. Previously, `#[renderer]` functions could only return `()`, and the generated helper function always returned `RenderResult`. Now: - - **`fn foo(x: T)` / `fn foo(x: T) -> ()`** → The generated helper function returns `()`. If the internal `RenderResult` (`dummy_r`) is non-empty, it is automatically printed to stdout. - - **`fn foo(x: T) -> U`** → The generated helper function returns `U`. The internal `RenderResult` is converted via `dummy_r.into()`, and no automatic printing occurs. + - **`fn foo(x: T)` / `fn foo(x: T) -> ()`** → The generated helper function returns `()`. If the internal `RenderResult` (`dummy_r`) is non-empty, it is automatically printed to stdout. + - **`fn foo(x: T) -> U`** → The generated helper function returns `U`. The internal `RenderResult` is converted via `dummy_r.into()`, and no automatic printing occurs. 4. **[`macros`]** Resource injection is now shared between `#[chain]` and `#[renderer]`. Extracted the common resource injection infrastructure (`ResourceInjection`, `extract_args_info`, `generate_immut_resource_bindings`, `wrap_body_with_mut_resources`) from `chain.rs` into a new `res_injection.rs` module. Both `#[chain]` and `#[renderer]` now reuse the same logic. @@ -823,10 +823,10 @@ None 1. **[`core`]** The core library no longer depends on `thiserror` 2. **[`mingling`]** Split the monolithic `general_renderer` feature into separate format-specific features: - - `general_renderer` now only includes core serialization support without any specific format - - `general_renderer_full` bundles all available serialization formats - - Individual format features: `json_serde_fmt`, `yaml_serde_fmt`, `toml_serde_fmt`, `ron_serde_fmt` - - A meta feature `all_serde_fmt` enables all format features at once + - `general_renderer` now only includes core serialization support without any specific format + - `general_renderer_full` bundles all available serialization formats + - Individual format features: `json_serde_fmt`, `yaml_serde_fmt`, `toml_serde_fmt`, `ron_serde_fmt` + - A meta feature `all_serde_fmt` enables all format features at once #### Features: @@ -946,9 +946,9 @@ fn my_chain(prev: Prev) -> Next { 1. **[`core`]** The signature of `exec` has been changed to `exec(self) -> i32` (previously was `exec(self)`) 2. **[`macros`]** All proc macros that accept a program/group name parameter (e.g. `pack!`, `dispatcher!`, `#[chain]`, `#[program_setup]`, `#[dispatcher_clap]`, `#[derive(Groupped)]`) now parse the name as a `syn::Path` instead of a bare `Ident`. This means: - - You can now use paths like `crate::MyProgram` or `my_crate::MyProgram` in addition to plain `MyProgram`. - - The default program name `ThisProgram` is no longer re-exported or required as an import — generated code references `crate::ThisProgram` directly. - - If you previously imported `ThisProgram` from `crate` only for macro use, that import is no longer needed and can be removed. + - You can now use paths like `crate::MyProgram` or `my_crate::MyProgram` in addition to plain `MyProgram`. + - The default program name `ThisProgram` is no longer re-exported or required as an import — generated code references `crate::ThisProgram` directly. + - If you previously imported `ThisProgram` from `crate` only for macro use, that import is no longer needed and can be removed. ```rust use crate::ThisProgram; // Can be removed if not used directly @@ -1125,9 +1125,9 @@ gen_program!(); ``` 6. **[`picker`]** Simplified `Picker` logic: - - `Picker` no longer requires the generic parameter `<G>` by default; it only needs it when using `pick_or_route` or `after_or_route` + - `Picker` no longer requires the generic parameter `<G>` by default; it only needs it when using `pick_or_route` or `after_or_route` - - Additionally, if no `or_route` operations are used, the `unpack_directly` function is no longer available; `unpack` will directly extract the inner value + - Additionally, if no `or_route` operations are used, the `unpack_directly` function is no longer available; `unpack` will directly extract the inner value ```rust // Before diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b10e96d..e729295 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -6,22 +6,22 @@ Before contributing, we recommend reading [README](README.md) to get an overview ## 1. Project Structure 📦 -| Category | Path/Name | Description | -| --------------------------- | ------------------------- | ------------------------------------------------------------------ | -| **Entry crate** | `mingling/` | Project entry point | -| **Core library** | `mingling_core/` | Imported as an external dependency | -| **Macro library** | `mingling_macros/` | Imported as an external dependency | -| **Mingling Pathfinder** | `mingling_pathf/` | Build-time module path resolution for types | -| **Mingling Picker2** | `mingling_picker/` | Mingling Arguments Parser | -| **Mingling Picker2 Macros** | `mingling_picker_macros/` | Mingling Arguments Parser Macros | -| **Scaffolding tool** | `mling/` | Scaffolding tool `mingling-cli` | -| **Examples** | `examples/` | To add expected output tests, modify `examples/test-examples.toml` | -| **Documents** | `docs/` | All documents | -| **Dev Documents** | `docs/dev/` | Internal documents | -| **Resources** | `docs/res/` | All resources | -| **Development tools** | `.run/src/bin` | Contains scripts and Rust tools | -| **CI** | `.run/src/bin/ci.rs` | Can be invoked directly via `cargo ci` | -| **Temporary files** | `.temp/` | Ignored by `.gitignore` | +| Category | Path/Name | Description | +| --------------------------- | -------------------- | ------------------------------------------------------------------ | +| **Entry crate** | `mingling/` | Project entry point | +| **Core library** | `mingling_core/` | Imported as an external dependency | +| **Macro library** | `mingling_macros/` | Imported as an external dependency | +| **Mingling Pathfinder** | `mingling_pathf/` | Build-time module path resolution for types | +| **Mingling Picker2** | `arg_picker/` | Mingling Arguments Parser | +| **Mingling Picker2 Macros** | `arg_picker_macros/` | Mingling Arguments Parser Macros | +| **Scaffolding tool** | `mling/` | Scaffolding tool `mingling-cli` | +| **Examples** | `examples/` | To add expected output tests, modify `examples/test-examples.toml` | +| **Documents** | `docs/` | All documents | +| **Dev Documents** | `docs/dev/` | Internal documents | +| **Resources** | `docs/res/` | All resources | +| **Development tools** | `.run/src/bin` | Contains scripts and Rust tools | +| **CI** | `.run/src/bin/ci.rs` | Can be invoked directly via `cargo ci` | +| **Temporary files** | `.temp/` | Ignored by `.gitignore` | ## 2. How to Contribute @@ -113,28 +113,28 @@ No strict requirements here — just modify the relevant `*.html` files. Preview ## 3. Submission Guide 🖊 1. **Pull Request** - - Submit a GitHub Pull Request and @Reviewer **[Weicao-CatilGrass](https://github.com/Weicao-CatilGrass)** for review - - Or send patches to **catil_grass@qq.com** + - Submit a GitHub Pull Request and @Reviewer **[Weicao-CatilGrass](https://github.com/Weicao-CatilGrass)** for review + - Or send patches to **catil_grass@qq.com** 2. **Commit Messages** - - Clearly and concisely describe the changes, no stringent requirements - - Provide more detail for complex changes, keep it brief for simple changes - - But: if you use [Conventional Commits](https://www.conventionalcommits.org/), it would make me even happier :) + - Clearly and concisely describe the changes, no stringent requirements + - Provide more detail for complex changes, keep it brief for simple changes + - But: if you use [Conventional Commits](https://www.conventionalcommits.org/), it would make me even happier :) 3. **CHANGELOG** - - If the submission includes functional changes or fixes, **the PR must include modifications to CHANGELOG.md** to describe the changes - - For minor changes like typo fixes, **CHANGELOG.md modification is not required**, and we will merge faster + - If the submission includes functional changes or fixes, **the PR must include modifications to CHANGELOG.md** to describe the changes + - For minor changes like typo fixes, **CHANGELOG.md modification is not required**, and we will merge faster 4. **Multi-commit PR** - - A PR can contain multiple commits - - However, at least one commit must modify CHANGELOG.md + - A PR can contain multiple commits + - However, at least one commit must modify CHANGELOG.md 5. **Review** - - After submission, please notify [Weicao-CatilGrass](https://github.com/Weicao-CatilGrass) for review — this is the most efficient way to get feedback + - After submission, please notify [Weicao-CatilGrass](https://github.com/Weicao-CatilGrass) for review — this is the most efficient way to get feedback 6. **Binary Resources** - - For binary resource files (images, etc.), please be cautious about adding them to avoid repository bloat + - For binary resource files (images, etc.), please be cautious about adding them to avoid repository bloat ## 4. Documentation Contribution 📕 @@ -71,6 +71,24 @@ dependencies = [ ] [[package]] +name = "arg-picker" +version = "0.1.0" +dependencies = [ + "arg-picker-macros", + "just_fmt 0.2.0", + "mingling_core", +] + +[[package]] +name = "arg-picker-macros" +version = "0.1.0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] name = "autocfg" version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -409,10 +427,10 @@ checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" name = "mingling" version = "0.3.0" dependencies = [ + "arg-picker", "mingling", "mingling_core", "mingling_macros", - "mingling_picker", "serde", "size", "tokio", @@ -468,24 +486,6 @@ dependencies = [ ] [[package]] -name = "mingling_picker" -version = "0.3.0" -dependencies = [ - "just_fmt 0.2.0", - "mingling_core", - "mingling_picker_macros", -] - -[[package]] -name = "mingling_picker_macros" -version = "0.3.0" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] name = "mio" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -10,8 +10,8 @@ members = [ "mingling_pathf", # Picker2 - "mingling_picker", - "mingling_picker_macros", + "arg_picker", + "arg_picker_macros", # Scaffolding tool "mling" @@ -36,8 +36,9 @@ exclude = [ mingling_core = { path = "mingling_core", default-features = false } mingling_macros = { path = "mingling_macros", default-features = false } mingling_pathf = { path = "mingling_pathf", default-features = false } -mingling_picker = { path = "mingling_picker", default-features = false } -mingling_picker_macros = { path = "mingling_picker_macros", default-features = false } + +arg-picker = { path = "arg_picker", default-features = false } +arg-picker-macros = { path = "arg_picker_macros", default-features = false } just_fmt = "0.2.0" just_template = "0.2.0" diff --git a/arg_picker/Cargo.toml b/arg_picker/Cargo.toml new file mode 100644 index 0000000..f7672c1 --- /dev/null +++ b/arg_picker/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "arg-picker" +version = "0.1.0" +edition = "2024" +license = "MIT OR Apache-2.0" +repository = "https://github.com/mingling-rs/mingling/tree/main/arg-picker" +authors = ["Weicao-CatilGrass"] +readme = "README.md" +description = "A lightweight, type-safe CLI argument parser" + +[features] +mingling_support = ["dep:mingling_core", "arg-picker-macros/mingling_support"] + +[dependencies] +mingling_core = { workspace = true, optional = true } +arg-picker-macros.workspace = true +just_fmt.workspace = true diff --git a/mingling_picker/README.md b/arg_picker/README.md index db67825..14051f3 100644 --- a/mingling_picker/README.md +++ b/arg_picker/README.md @@ -1,4 +1,4 @@ -# Mingling Picker +# Argument Picker A command-line argument parser for [Mingling](https://github.com/mingling-rs/mingling), enabled by the `mingling/picker` feature. @@ -10,11 +10,11 @@ features = [ ] ``` -Of course, you can also use it as a standalone crate by replacing `mingling::picker` with `mingling_picker`: +Of course, you can also use it as a standalone crate by replacing `mingling::picker` with `arg_picker`: ```toml [dependencies] -mingling_picker = "0.3.0" +arg-picker = "0.1.0" ``` ## Chained Argument Parser @@ -22,7 +22,7 @@ mingling_picker = "0.3.0" Provides a clean chained-call API for declaring arguments to parse: ```rust -use mingling_picker::prelude::*; +use arg_picker::prelude::*; let args: Vec<&str> = vec!["--name", "Bob", "--age", "24"]; @@ -43,5 +43,5 @@ assert_eq!(age, 24); Provides a pure function library `parselib` for analyzing the structure of command-line arguments. ```rust -use mingling_picker::parselib::*; +use arg_picker::parselib::*; ``` diff --git a/mingling_picker/src/arg.rs b/arg_picker/src/arg.rs index 78ad539..78ad539 100644 --- a/mingling_picker/src/arg.rs +++ b/arg_picker/src/arg.rs diff --git a/mingling_picker/src/builtin.rs b/arg_picker/src/builtin.rs index e855b08..e855b08 100644 --- a/mingling_picker/src/builtin.rs +++ b/arg_picker/src/builtin.rs diff --git a/mingling_picker/src/builtin/pick_bool.rs b/arg_picker/src/builtin/pick_bool.rs index ccc4424..ccc4424 100644 --- a/mingling_picker/src/builtin/pick_bool.rs +++ b/arg_picker/src/builtin/pick_bool.rs diff --git a/mingling_picker/src/builtin/pick_flag.rs b/arg_picker/src/builtin/pick_flag.rs index b642a9a..b642a9a 100644 --- a/mingling_picker/src/builtin/pick_flag.rs +++ b/arg_picker/src/builtin/pick_flag.rs diff --git a/mingling_picker/src/builtin/pick_numbers.rs b/arg_picker/src/builtin/pick_numbers.rs index a5ab0a9..a5ab0a9 100644 --- a/mingling_picker/src/builtin/pick_numbers.rs +++ b/arg_picker/src/builtin/pick_numbers.rs diff --git a/mingling_picker/src/builtin/pick_string.rs b/arg_picker/src/builtin/pick_string.rs index c96f667..c96f667 100644 --- a/mingling_picker/src/builtin/pick_string.rs +++ b/arg_picker/src/builtin/pick_string.rs diff --git a/mingling_picker/src/corebind.rs b/arg_picker/src/corebind.rs index 3581871..3581871 100644 --- a/mingling_picker/src/corebind.rs +++ b/arg_picker/src/corebind.rs diff --git a/mingling_picker/src/corebind/entry_picker.rs b/arg_picker/src/corebind/entry_picker.rs index 69bc4d8..69bc4d8 100644 --- a/mingling_picker/src/corebind/entry_picker.rs +++ b/arg_picker/src/corebind/entry_picker.rs diff --git a/mingling_picker/src/infos.rs b/arg_picker/src/infos.rs index d2a0fce..074539a 100644 --- a/mingling_picker/src/infos.rs +++ b/arg_picker/src/infos.rs @@ -51,7 +51,7 @@ impl<Type> PickerArgResult<Type> { /// # Examples /// /// ``` - /// use mingling_picker::PickerArgResult; + /// use arg_picker::PickerArgResult; /// /// let result: PickerArgResult<i32> = PickerArgResult::Parsed(42); /// assert!(result.is_parsed()); @@ -70,7 +70,7 @@ impl<Type> PickerArgResult<Type> { /// # Examples /// /// ``` - /// use mingling_picker::PickerArgResult; + /// use arg_picker::PickerArgResult; /// /// let result: PickerArgResult<i32> = PickerArgResult::Parsed(42); /// assert!(result.is_found()); @@ -87,7 +87,7 @@ impl<Type> PickerArgResult<Type> { /// # Examples /// /// ``` - /// use mingling_picker::PickerArgResult; + /// use arg_picker::PickerArgResult; /// /// let result: PickerArgResult<i32> = PickerArgResult::Unparsed; /// assert!(result.is_err()); @@ -104,7 +104,7 @@ impl<Type> PickerArgResult<Type> { /// # Examples /// /// ``` - /// use mingling_picker::PickerArgResult; + /// use arg_picker::PickerArgResult; /// /// let result: PickerArgResult<i32> = PickerArgResult::Parsed(42); /// assert_eq!(result.parsed(), Some(&42)); @@ -128,7 +128,7 @@ impl<Type> PickerArgResult<Type> { /// # Examples /// /// ```should_panic - /// use mingling_picker::PickerArgResult; + /// use arg_picker::PickerArgResult; /// /// let result: PickerArgResult<i32> = PickerArgResult::NotFound; /// result.expect("expected a parsed value"); @@ -148,14 +148,14 @@ impl<Type> PickerArgResult<Type> { /// # Examples /// /// ``` - /// use mingling_picker::PickerArgResult; + /// use arg_picker::PickerArgResult; /// /// let result: PickerArgResult<i32> = PickerArgResult::Parsed(42); /// assert_eq!(result.unwrap(), 42); /// ``` /// /// ```should_panic - /// use mingling_picker::PickerArgResult; + /// use arg_picker::PickerArgResult; /// /// let result: PickerArgResult<i32> = PickerArgResult::NotFound; /// result.unwrap(); @@ -177,7 +177,7 @@ impl<Type> PickerArgResult<Type> { /// # Examples /// /// ``` - /// use mingling_picker::PickerArgResult; + /// use arg_picker::PickerArgResult; /// /// let result: PickerArgResult<i32> = PickerArgResult::Parsed(42); /// assert_eq!(result.unwrap_or(0), 42); @@ -197,7 +197,7 @@ impl<Type> PickerArgResult<Type> { /// # Examples /// /// ``` - /// use mingling_picker::PickerArgResult; + /// use arg_picker::PickerArgResult; /// /// let result: PickerArgResult<i32> = PickerArgResult::Parsed(42); /// assert_eq!(result.unwrap_or_else(|| 0), 42); @@ -217,7 +217,7 @@ impl<Type> PickerArgResult<Type> { /// # Examples /// /// ``` - /// use mingling_picker::PickerArgResult; + /// use arg_picker::PickerArgResult; /// /// let result: PickerArgResult<i32> = PickerArgResult::Parsed(42); /// assert_eq!(result.unwrap_or_default(), 42); @@ -242,7 +242,7 @@ impl<Type> PickerArgResult<Type> { /// # Examples /// /// ``` - /// use mingling_picker::PickerArgResult; + /// use arg_picker::PickerArgResult; /// /// let result: PickerArgResult<i32> = PickerArgResult::Parsed(42); /// assert_eq!(result.to_option(), Some(42)); diff --git a/mingling_picker/src/lib.rs b/arg_picker/src/lib.rs index deb266e..21a0d35 100644 --- a/mingling_picker/src/lib.rs +++ b/arg_picker/src/lib.rs @@ -26,7 +26,7 @@ pub mod value; /// This module is intended to be imported with a wildcard import: /// /// ``` -/// use mingling_picker::prelude::*; +/// use arg_picker::prelude::*; /// ``` pub mod prelude { pub use crate::macros::arg; @@ -38,9 +38,9 @@ pub mod prelude { pub use crate::corebind::EntryPicker; } -/// Re-export of the `mingling_picker_macros` crate +/// Re-export of the `arg_picker_macros` crate pub mod macros { - pub use mingling_picker_macros::arg; + pub use arg_picker_macros::arg; } /// Provides the types necessary for implementing the `Pickable` trait diff --git a/mingling_picker/src/parselib.rs b/arg_picker/src/parselib.rs index 7fbd606..7fbd606 100644 --- a/mingling_picker/src/parselib.rs +++ b/arg_picker/src/parselib.rs diff --git a/mingling_picker/src/parselib/arg_matcher.rs b/arg_picker/src/parselib/arg_matcher.rs index 38bb9cc..38bb9cc 100644 --- a/mingling_picker/src/parselib/arg_matcher.rs +++ b/arg_picker/src/parselib/arg_matcher.rs diff --git a/mingling_picker/src/parselib/flag_matcher.rs b/arg_picker/src/parselib/flag_matcher.rs index e93d35a..e93d35a 100644 --- a/mingling_picker/src/parselib/flag_matcher.rs +++ b/arg_picker/src/parselib/flag_matcher.rs diff --git a/mingling_picker/src/parselib/multi_arg_matcher.rs b/arg_picker/src/parselib/multi_arg_matcher.rs index 748b1be..748b1be 100644 --- a/mingling_picker/src/parselib/multi_arg_matcher.rs +++ b/arg_picker/src/parselib/multi_arg_matcher.rs diff --git a/mingling_picker/src/parselib/pos_matcher.rs b/arg_picker/src/parselib/pos_matcher.rs index 279e01e..279e01e 100644 --- a/mingling_picker/src/parselib/pos_matcher.rs +++ b/arg_picker/src/parselib/pos_matcher.rs diff --git a/mingling_picker/src/parselib/single_matcher.rs b/arg_picker/src/parselib/single_matcher.rs index 25c4741..25c4741 100644 --- a/mingling_picker/src/parselib/single_matcher.rs +++ b/arg_picker/src/parselib/single_matcher.rs diff --git a/mingling_picker/src/parselib/style.rs b/arg_picker/src/parselib/style.rs index dd01125..36ba8f0 100644 --- a/mingling_picker/src/parselib/style.rs +++ b/arg_picker/src/parselib/style.rs @@ -40,7 +40,7 @@ impl<'a> ParserStyle<'a> { /// # Examples /// /// ``` - /// # use mingling_picker::parselib::{ParserStyle, FlagStr, UNIX_STYLE}; + /// # use arg_picker::parselib::{ParserStyle, FlagStr, UNIX_STYLE}; /// let style = &UNIX_STYLE; /// /// assert_eq!(style.flag_string('v'), "-v"); @@ -76,7 +76,7 @@ impl<'a> ParserStyle<'a> { /// # Examples /// /// ``` -/// use mingling_picker::parselib::FlagStr; +/// use arg_picker::parselib::FlagStr; /// /// let short: FlagStr = 'v'.into(); /// let long: FlagStr = "verbose".into(); @@ -117,8 +117,8 @@ impl<'a> From<&'a String> for FlagStr<'a> { /// # Examples /// /// ``` -/// # use mingling_picker::IntoPicker; -/// use mingling_picker::parselib::ParserStyleNamingCase; +/// # use arg_picker::IntoPicker; +/// use arg_picker::parselib::ParserStyleNamingCase; /// /// let case = ParserStyleNamingCase::Kebab; /// assert_eq!( @@ -174,7 +174,7 @@ impl ParserStyleNamingCase { /// # Examples /// /// ``` - /// use mingling_picker::parselib::ParserStyleNamingCase; + /// use arg_picker::parselib::ParserStyleNamingCase; /// /// let camel = ParserStyleNamingCase::Camel; /// assert_eq!(camel.convert("brew_coffee".to_string()), "brewCoffee"); diff --git a/mingling_picker/src/parselib/utils.rs b/arg_picker/src/parselib/utils.rs index 47c5b55..47c5b55 100644 --- a/mingling_picker/src/parselib/utils.rs +++ b/arg_picker/src/parselib/utils.rs diff --git a/mingling_picker/src/pickable.rs b/arg_picker/src/pickable.rs index 758ae9a..758ae9a 100644 --- a/mingling_picker/src/pickable.rs +++ b/arg_picker/src/pickable.rs diff --git a/mingling_picker/src/pickable/multi_pickable.rs b/arg_picker/src/pickable/multi_pickable.rs index 84a8068..84a8068 100644 --- a/mingling_picker/src/pickable/multi_pickable.rs +++ b/arg_picker/src/pickable/multi_pickable.rs diff --git a/mingling_picker/src/pickable/single_pickable.rs b/arg_picker/src/pickable/single_pickable.rs index 8a5b3e6..8a5b3e6 100644 --- a/mingling_picker/src/pickable/single_pickable.rs +++ b/arg_picker/src/pickable/single_pickable.rs diff --git a/mingling_picker/src/picker.rs b/arg_picker/src/picker.rs index 7cf1525..ecab648 100644 --- a/mingling_picker/src/picker.rs +++ b/arg_picker/src/picker.rs @@ -320,7 +320,7 @@ pub trait IntoPicker<'a> { /// # Examples /// /// ``` - /// use mingling_picker::{IntoPicker, Picker}; + /// use arg_picker::{IntoPicker, Picker}; /// /// let args: Picker = (&["hello", "world"][..]).to_picker(); /// assert_eq!(args.len(), 2); diff --git a/mingling_picker/src/picker/parse.rs b/arg_picker/src/picker/parse.rs index 698baac..366028b 100644 --- a/mingling_picker/src/picker/parse.rs +++ b/arg_picker/src/picker/parse.rs @@ -11,7 +11,7 @@ #![allow(clippy::type_complexity)] use crate::{Pickable, PickerArgAttr, PickerArgInfo, PickerArgResult, PickerArgs, TagPhaseContext}; -use mingling_picker_macros::internal_repeat; +use arg_picker_macros::internal_repeat; internal_repeat!(1..=32 => { use crate::PickerPattern$; diff --git a/mingling_picker/src/picker/patterns.rs b/arg_picker/src/picker/patterns.rs index 78ae2b0..5806605 100644 --- a/mingling_picker/src/picker/patterns.rs +++ b/arg_picker/src/picker/patterns.rs @@ -1,4 +1,4 @@ -use mingling_picker_macros::internal_repeat; +use arg_picker_macros::internal_repeat; use crate::{Pickable, PickerArg, PickerArgResult, PickerArgs}; diff --git a/mingling_picker/src/picker/result.rs b/arg_picker/src/picker/result.rs index 9cd78ae..83ca2cd 100644 --- a/mingling_picker/src/picker/result.rs +++ b/arg_picker/src/picker/result.rs @@ -1,6 +1,6 @@ #![allow(clippy::type_complexity)] // Aha, Type Gymnastics! -use mingling_picker_macros::internal_repeat; +use arg_picker_macros::internal_repeat; internal_repeat!(1..=32 => { #[doc(hidden)] diff --git a/mingling_picker/src/value.rs b/arg_picker/src/value.rs index 995aa00..995aa00 100644 --- a/mingling_picker/src/value.rs +++ b/arg_picker/src/value.rs diff --git a/mingling_picker/src/value/flag.rs b/arg_picker/src/value/flag.rs index ee0d6ee..c0673bd 100644 --- a/mingling_picker/src/value/flag.rs +++ b/arg_picker/src/value/flag.rs @@ -26,7 +26,7 @@ use std::{ /// directly in boolean contexts: /// /// ``` -/// # use mingling_picker::value::Flag; +/// # use arg_picker::value::Flag; /// let flag = Flag::Active; /// if *flag { /* runs */ } /// ``` @@ -72,7 +72,7 @@ impl Flag { /// # Examples /// /// ``` - /// # use mingling_picker::value::Flag; + /// # use arg_picker::value::Flag; /// assert!(Flag::Active.bool()); /// assert!(!Flag::Inactive.bool()); /// ``` @@ -116,7 +116,7 @@ impl From<Flag> for bool { /// # Examples /// /// ``` -/// # use mingling_picker::value::Flag; +/// # use arg_picker::value::Flag; /// let flag = Flag::Active; /// if *flag { /// println!("flag is set"); diff --git a/mingling_picker/src/value/vec_until.rs b/arg_picker/src/value/vec_until.rs index 1b79641..1b79641 100644 --- a/mingling_picker/src/value/vec_until.rs +++ b/arg_picker/src/value/vec_until.rs diff --git a/mingling_picker/test/Cargo.lock b/arg_picker/test/Cargo.lock index 0fef84b..5d44838 100644 --- a/mingling_picker/test/Cargo.lock +++ b/arg_picker/test/Cargo.lock @@ -3,22 +3,16 @@ version = 4 [[package]] -name = "just_fmt" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6170dccbc3ea15dfb7f2da964097f814aba1dd8f746d4ffc56f33245c38e6d96" - -[[package]] -name = "mingling_picker" -version = "0.3.0" +name = "arg-picker" +version = "0.1.0" dependencies = [ + "arg-picker-macros", "just_fmt", - "mingling_picker_macros", ] [[package]] -name = "mingling_picker_macros" -version = "0.3.0" +name = "arg-picker-macros" +version = "0.1.0" dependencies = [ "proc-macro2", "quote", @@ -26,6 +20,19 @@ dependencies = [ ] [[package]] +name = "arg-picker-test" +version = "0.1.0" +dependencies = [ + "arg-picker", +] + +[[package]] +name = "just_fmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6170dccbc3ea15dfb7f2da964097f814aba1dd8f746d4ffc56f33245c38e6d96" + +[[package]] name = "proc-macro2" version = "1.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -55,13 +62,6 @@ dependencies = [ ] [[package]] -name = "test-mingling-picker" -version = "0.1.0" -dependencies = [ - "mingling_picker", -] - -[[package]] name = "unicode-ident" version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" diff --git a/mingling_picker/test/Cargo.toml b/arg_picker/test/Cargo.toml index 127546c..2c366c7 100644 --- a/mingling_picker/test/Cargo.toml +++ b/arg_picker/test/Cargo.toml @@ -1,9 +1,9 @@ [package] -name = "test-mingling-picker" +name = "arg-picker-test" version = "0.1.0" edition = "2024" [workspace] [dependencies] -mingling_picker = { path = "../" } +arg-picker = { path = "../" } diff --git a/mingling_picker/test/src/lib.rs b/arg_picker/test/src/lib.rs index eac6cad..0cfa575 100644 --- a/mingling_picker/test/src/lib.rs +++ b/arg_picker/test/src/lib.rs @@ -7,7 +7,7 @@ #[cfg(test)] mod test; -use mingling_picker::parselib::MaskedArg; +use arg_picker::parselib::MaskedArg; /// Create a single `MaskedArg` from a raw string and its original index. pub fn make_masked(raw: &str, idx: usize) -> MaskedArg<'_> { diff --git a/mingling_picker/test/src/test.rs b/arg_picker/test/src/test.rs index 9c53514..9c53514 100644 --- a/mingling_picker/test/src/test.rs +++ b/arg_picker/test/src/test.rs diff --git a/mingling_picker/test/src/test/arg_matcher_test.rs b/arg_picker/test/src/test/arg_matcher_test.rs index 7b37bc8..d1d363e 100644 --- a/mingling_picker/test/src/test/arg_matcher_test.rs +++ b/arg_picker/test/src/test/arg_matcher_test.rs @@ -1,5 +1,5 @@ -use mingling_picker::PickerArgInfo; -use mingling_picker::parselib::{ArgMatcher, Matcher, POWERSHELL_STYLE, UNIX_STYLE}; +use arg_picker::parselib::{ArgMatcher, Matcher, POWERSHELL_STYLE, UNIX_STYLE}; +use arg_picker::PickerArgInfo; use crate::make_args; diff --git a/mingling_picker/test/src/test/basic_test.rs b/arg_picker/test/src/test/basic_test.rs index 78b154e..b01adb6 100644 --- a/mingling_picker/test/src/test/basic_test.rs +++ b/arg_picker/test/src/test/basic_test.rs @@ -1,4 +1,4 @@ -use mingling_picker::{IntoPicker, macros::arg}; +use arg_picker::{macros::arg, IntoPicker}; // Basic bool flag — present / absent diff --git a/mingling_picker/test/src/test/multi_arg_test.rs b/arg_picker/test/src/test/multi_arg_test.rs index 377357e..49517f1 100644 --- a/mingling_picker/test/src/test/multi_arg_test.rs +++ b/arg_picker/test/src/test/multi_arg_test.rs @@ -1,5 +1,5 @@ -use mingling_picker::parselib::{Matcher, MultiArgMatcher, UNIX_STYLE}; -use mingling_picker::PickerArgInfo; +use arg_picker::parselib::{Matcher, MultiArgMatcher, UNIX_STYLE}; +use arg_picker::PickerArgInfo; use crate::make_args; @@ -72,8 +72,12 @@ fn test_multi_all_two_occurrences() { let mut info = PickerArgInfo::new(); info.set_long("val"); let args = make_args(&[ - ("--val", 0), ("a", 1), ("b", 2), - ("--val", 3), ("c", 4), ("d", 5), + ("--val", 0), + ("a", 1), + ("b", 2), + ("--val", 3), + ("c", 4), + ("d", 5), ]); let result = MultiArgMatcher::on_match_all(&args, &UNIX_STYLE, &info); assert_eq!(result, vec![0, 1, 2, 3, 4, 5]); @@ -85,9 +89,12 @@ fn test_multi_all_skips_non_matching_args() { let mut info = PickerArgInfo::new(); info.set_long("val"); let args = make_args(&[ - ("--val", 0), ("a", 1), - ("--other", 2), ("b", 3), - ("--val", 4), ("c", 5), + ("--val", 0), + ("a", 1), + ("--other", 2), + ("b", 3), + ("--val", 4), + ("c", 5), ]); let result = MultiArgMatcher::on_match_all(&args, &UNIX_STYLE, &info); assert_eq!(result, vec![0, 1, 4, 5]); @@ -120,9 +127,7 @@ fn test_multi_all_mixed_eq_and_regular() { // --val=a b --val c d let mut info = PickerArgInfo::new(); info.set_long("val"); - let args = make_args(&[ - ("--val=a", 0), ("b", 1), ("--val", 2), ("c", 3), ("d", 4), - ]); + let args = make_args(&[("--val=a", 0), ("b", 1), ("--val", 2), ("c", 3), ("d", 4)]); let result = MultiArgMatcher::on_match_all(&args, &UNIX_STYLE, &info); assert_eq!(result, vec![0, 1, 2, 3, 4]); } diff --git a/mingling_picker/test/src/test/multi_value_test.rs b/arg_picker/test/src/test/multi_value_test.rs index 0f56517..cbae645 100644 --- a/mingling_picker/test/src/test/multi_value_test.rs +++ b/arg_picker/test/src/test/multi_value_test.rs @@ -1,5 +1,5 @@ -use mingling_picker::value::{Flag, VecUntil}; -use mingling_picker::{IntoPicker, macros::arg}; +use arg_picker::value::{Flag, VecUntil}; +use arg_picker::{macros::arg, IntoPicker}; #[test] fn test_vec_until_i16_named() { diff --git a/mingling_picker/test/src/test/pos_matcher_test.rs b/arg_picker/test/src/test/pos_matcher_test.rs index b5319f5..0d4f87e 100644 --- a/mingling_picker/test/src/test/pos_matcher_test.rs +++ b/arg_picker/test/src/test/pos_matcher_test.rs @@ -1,5 +1,5 @@ -use mingling_picker::PickerArgInfo; -use mingling_picker::parselib::{MaskedArg, Matcher, PositionalMatcher, UNIX_STYLE, WINDOWS_STYLE}; +use arg_picker::parselib::{MaskedArg, Matcher, PositionalMatcher, UNIX_STYLE, WINDOWS_STYLE}; +use arg_picker::PickerArgInfo; fn make_args<'a>(pairs: &'a [(&'a str, usize)]) -> Vec<MaskedArg<'a>> { pairs diff --git a/mingling_picker/test/src/test/priority_test.rs b/arg_picker/test/src/test/priority_test.rs index 8179389..8f0a452 100644 --- a/mingling_picker/test/src/test/priority_test.rs +++ b/arg_picker/test/src/test/priority_test.rs @@ -1,5 +1,5 @@ -use mingling_picker::value::Flag; -use mingling_picker::{IntoPicker, macros::arg}; +use arg_picker::value::Flag; +use arg_picker::{macros::arg, IntoPicker}; // Same flag name, different Pickable types // diff --git a/mingling_picker/test/src/test/route_test.rs b/arg_picker/test/src/test/route_test.rs index 9261db1..7594c6e 100644 --- a/mingling_picker/test/src/test/route_test.rs +++ b/arg_picker/test/src/test/route_test.rs @@ -1,4 +1,4 @@ -use mingling_picker::{IntoPicker, macros::arg}; +use arg_picker::{macros::arg, IntoPicker}; // Route mechanism — or_route diff --git a/mingling_picker/test/src/test/style_test.rs b/arg_picker/test/src/test/style_test.rs index 3c337b9..b470d4f 100644 --- a/mingling_picker/test/src/test/style_test.rs +++ b/arg_picker/test/src/test/style_test.rs @@ -1,8 +1,8 @@ -use mingling_picker::PickerArgInfo; -use mingling_picker::parselib::{ - FlagMatcher, Matcher, POWERSHELL_STYLE, ParserStyle, ParserStyleNamingCase, UNIX_STYLE, - WINDOWS_STYLE, build_possible_flags, +use arg_picker::parselib::{ + build_possible_flags, FlagMatcher, Matcher, ParserStyle, ParserStyleNamingCase, + POWERSHELL_STYLE, UNIX_STYLE, WINDOWS_STYLE, }; +use arg_picker::PickerArgInfo; use crate::make_masked; diff --git a/mingling_picker/test/src/test/value_flag_test.rs b/arg_picker/test/src/test/value_flag_test.rs index d267a27..3df053e 100644 --- a/mingling_picker/test/src/test/value_flag_test.rs +++ b/arg_picker/test/src/test/value_flag_test.rs @@ -1,5 +1,5 @@ -use mingling_picker::value::Flag; -use mingling_picker::{IntoPicker, macros::arg}; +use arg_picker::value::Flag; +use arg_picker::{macros::arg, IntoPicker}; // Basic Flag — present / absent diff --git a/mingling_picker/test/src/test/value_string_test.rs b/arg_picker/test/src/test/value_string_test.rs index b1e5c0b..2c3b50b 100644 --- a/mingling_picker/test/src/test/value_string_test.rs +++ b/arg_picker/test/src/test/value_string_test.rs @@ -1,4 +1,4 @@ -use mingling_picker::{IntoPicker, macros::arg}; +use arg_picker::{macros::arg, IntoPicker}; // Basic named String — present / absent diff --git a/mingling_picker_macros/Cargo.toml b/arg_picker_macros/Cargo.toml index 58488ea..c83cb9e 100644 --- a/mingling_picker_macros/Cargo.toml +++ b/arg_picker_macros/Cargo.toml @@ -1,9 +1,9 @@ [package] -name = "mingling_picker_macros" -version.workspace = true -edition.workspace = true -license.workspace = true -repository.workspace = true +name = "arg-picker-macros" +version = "0.1.0" +edition = "2024" +license = "MIT OR Apache-2.0" +repository = "https://github.com/mingling-rs/mingling/tree/main/arg-picker" authors = ["Weicao-CatilGrass"] readme = "README.md" description = "Mingling's lightweight argument parser macros" diff --git a/mingling_picker_macros/README.md b/arg_picker_macros/README.md index 5a3f220..5a3f220 100644 --- a/mingling_picker_macros/README.md +++ b/arg_picker_macros/README.md diff --git a/mingling_picker_macros/src/arg.rs b/arg_picker_macros/src/arg.rs index 70b27b0..55860c4 100644 --- a/mingling_picker_macros/src/arg.rs +++ b/arg_picker_macros/src/arg.rs @@ -73,7 +73,7 @@ pub(crate) fn arg(input: TokenStream) -> TokenStream { let import = quote! { ::mingling::picker::PickerArg }; #[cfg(not(feature = "mingling_support"))] - let import = quote! { ::mingling_picker::PickerArg }; + let import = quote! { ::arg_picker::PickerArg }; if ty.is_some() { quote! { #import::<#ty_ts> } diff --git a/mingling_picker_macros/src/internal_repeat.rs b/arg_picker_macros/src/internal_repeat.rs index 4b2242b..4b2242b 100644 --- a/mingling_picker_macros/src/internal_repeat.rs +++ b/arg_picker_macros/src/internal_repeat.rs diff --git a/mingling_picker_macros/src/lib.rs b/arg_picker_macros/src/lib.rs index a12e3ed..18cce84 100644 --- a/mingling_picker_macros/src/lib.rs +++ b/arg_picker_macros/src/lib.rs @@ -18,7 +18,7 @@ pub fn internal_repeat(input: TokenStream) -> TokenStream { /// # Syntax /// /// ```ignore -/// use mingling_picker_macros::flag; +/// use arg_picker_macros::flag; /// /// let basic = arg![name: String]; /// let with_short_name = arg![name: String, 'n']; diff --git a/mingling/Cargo.toml b/mingling/Cargo.toml index c3f9511..adf900f 100644 --- a/mingling/Cargo.toml +++ b/mingling/Cargo.toml @@ -50,7 +50,7 @@ dispatch_tree = ["mingling_core/dispatch_tree", "mingling_macros/dispatch_tree"] repl = ["mingling_core/repl", "mingling_macros/repl"] comp = ["mingling_core/comp", "mingling_macros/comp"] parser = ["dep:size"] -picker = ["dep:mingling_picker", "mingling_picker/mingling_support"] +picker = ["dep:arg-picker", "arg-picker/mingling_support"] pathf = ["mingling_core/pathf", "mingling_macros/pathf"] structural_renderer = [ @@ -90,6 +90,6 @@ extra_macros = ["mingling_macros/extra_macros"] [dependencies] mingling_core = { workspace = true, optional = true } mingling_macros = { workspace = true, optional = true } -mingling_picker = { workspace = true, optional = true } +arg-picker = { workspace = true, optional = true } serde = { workspace = true, optional = true } size = { version = "0.5", optional = true } diff --git a/mingling/src/lib.rs b/mingling/src/lib.rs index ba87f85..44812d6 100644 --- a/mingling/src/lib.rs +++ b/mingling/src/lib.rs @@ -86,10 +86,10 @@ pub mod parser; /// `Mingling` argument parser (Picker2) #[cfg(feature = "picker")] pub mod picker { - pub use mingling_picker::*; + pub use arg_picker::*; pub mod parselib { - pub use mingling_picker::parselib::*; + pub use arg_picker::parselib::*; } } @@ -107,6 +107,9 @@ pub mod picker { #[allow(unused_imports)] #[cfg(feature = "macros")] pub mod macros { + /// New Parser provided by the `picker` feature + #[cfg(feature = "picker")] + pub use arg_picker::macros::*; /// `#[chain]` - Used to generate a struct implementing the `Chain` trait via a method pub use mingling_macros::chain; /// `#[completion(EntryType)]` - Used to generate completion entry @@ -177,9 +180,6 @@ pub mod macros { /// `suggest_enum!(EnumNames)` - Used to generate enum suggestions #[cfg(feature = "comp")] pub use mingling_macros::suggest_enum; - /// New Parser provided by the `picker` feature - #[cfg(feature = "picker")] - pub use mingling_picker::macros::*; } /// derive macro `EnumTag` @@ -286,7 +286,7 @@ pub mod prelude { pub use crate::parser::AsPicker; #[cfg(feature = "picker")] - pub use mingling_picker::prelude::*; + pub use arg_picker::prelude::*; /// Used to enable the `writeln!` macro for `RenderResult` #[cfg(feature = "core")] diff --git a/mingling_picker/Cargo.toml b/mingling_picker/Cargo.toml deleted file mode 100644 index ddab33c..0000000 --- a/mingling_picker/Cargo.toml +++ /dev/null @@ -1,17 +0,0 @@ -[package] -name = "mingling_picker" -version.workspace = true -edition.workspace = true -license.workspace = true -repository.workspace = true -authors = ["Weicao-CatilGrass"] -readme = "README.md" -description = "Mingling's lightweight argument parser" - -[features] -mingling_support = ["dep:mingling_core", "mingling_picker_macros/mingling_support"] - -[dependencies] -mingling_core = { workspace = true, optional = true } -mingling_picker_macros.workspace = true -just_fmt.workspace = true |
