diff options
Diffstat (limited to 'CHANGELOG.md')
| -rw-r--r-- | CHANGELOG.md | 137 |
1 files changed, 126 insertions, 11 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 3130abc..aa80b79 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ Any contributor making changes to the project must record their changes in this **- Milestone.1 "MVP" -** - [Unreleased](#unreleased) +- [Release 0.4.0 (Unreleased)](#release-040-unreleased) - [Release 0.3.0 (2026-07-27)](#release-030-2026-07-27) - [Release 0.2.2 (2026-07-10)](#release-022-2026-07-10) - [Release 0.2.1 (2026-07-01)](#release-021-2026-07-01) @@ -52,11 +53,29 @@ None ## Contents -### ?.?.? (Unreleased) +### 0.4.0 (Unreleased) #### Fixes: -None +1. **[`comps:zsh`]** Fixed zsh completion script to properly escape colons in completion descriptions. The zsh completion script generated for the `zsh` output format now escapes colon characters in completion items (`${item//:/\\:}`) and description parts (`${match[1]//:/\\:}`) so that descriptions containing colons don't break the `_describe` command's parsing. Additionally, fixed the simple-completions branch to iterate over the original `completions` array (with the colon-escaped format matching) rather than the already-parsed `parsed_completions` array, correctly extracting the completion item when no description is present. + +2. **[`comps:bash`]** Reworked the bash completion script template to fix word-index tracking when the cursor is in the middle of a word and to add colon-ltrimming for completion descriptions. The script now computes the current word (`cur`) using `COMP_LINE` truncated to `COMP_POINT` (taking the last whitespace-delimited token) rather than relying on `COMP_WORDS[COMP_CWORD]`, which fails when the cursor is in the middle of a word. The word index is derived from the count of words preceding the current cursor position (`before_words`), and `prev` is the last word in that preceding set. The option flags to the underlying completion engine are now passed as `-f value`/`-C value`/etc. (space-separated) instead of `-f=value`/`-C=value`/etc. (equals-separated), since the engine expects space-delimited argument pairs. Additionally, when the current word contains a colon and `COMP_WORDBREAKS` includes `:`, the completion items are trimmed of the colon prefix before being inserted into `COMPREPLY` — this prevents completions like `foo:bar` from being double-prefixed with the literal `foo:bar` when bash would otherwise append the full word. + +3. **[`core:comp`]** Fixed the completion engine to correctly resolve command nodes when global parameters (flags and their values) precede the subcommand. Previously, the engine matched the command tree starting from the first argument after the program name, treating every leading argument as part of the command path — so `prog [PARAM]... <subcommand>` style invocations would fail to match any node. Now: + + - A new helper `first_command_arg_index::<P>(args)` scans the argument list and returns the index of the first argument that matches the head of a registered command node (excluding node names starting with `_`). Everything before that index is treated as global parameters and skipped during command tree matching. + - In `CompletionHelper::complete`, the dispatch args are sliced to start at the first command-node match (`all_args[start..]`); if no node match is found, the args are empty (`Vec::new()`). + - In `default_completion`, the input path resolution skips the leading global-parameter arguments the same way, so `prog -v hello` correctly suggests the `hello` node even though `-v` precedes it. + - In the unmatched-dispatcher branch: when a command node _has_ been matched (`first_cmd_match.is_some()`), the `EntryFallback` handler is **skipped** and only `default_completion` runs, since global parameters do not warrant invoking the fallback. When no node was matched, the previous behavior is retained (fallback combined with default completion). + + This enables `prog [PARAM]... <subcommand>` style invocations to resolve the subcommand correctly, while a "broken" path such as `prog -v hello -a someone` still fails to match a `hello someone` node (since `-a someone` lies _after_ the first matched node and participates normally). + +4. **[`core:comp`]** Added `add_prefix()` and `add_suffix()` methods to `Suggest` for batch-transforming suggestion text: + + - **`add_prefix(self, prefix: impl Into<String>) -> Suggest`** — Takes the current `Suggest` value and prepends the given prefix to the suggestion text of every item. If the `Suggest` value is `Suggest::FileCompletion`, it is returned unchanged. For example, `["foo", "bar"]` with prefix `"--"` becomes `["--foo", "--bar"]`. + - **`add_suffix(self, suffix: impl Into<String>) -> Suggest`** — Takes the current `Suggest` value and appends the given suffix to the suggestion text of every item. If the `Suggest` value is `Suggest::FileCompletion`, it is returned unchanged. For example, `["foo", "bar"]` with suffix `"="` becomes `["foo=", "bar="]`. + + Both methods consume the original `Suggest` value and return a new one, enabling ergonomic chaining with the existing `combine()` method for transforming completion suggestion sets. #### Optimizations: @@ -71,6 +90,19 @@ None _No behavioral change for downstream code — all public items are re-exported with the same names. The `__this_program_impl` module is `#[doc(hidden)]` and not part of the public API._ +3. **[`core:comp`]** Added `add_suggest()` and `add_suggest_with_description()` methods to `Suggest` for batch-adding suggestion items: + + - **`add_suggest(&mut self, items: impl Into<Vec<String>>)`** — Wraps each item in `SuggestItem::Simple` and inserts it into the underlying `BTreeSet`. + - **`add_suggest_with_description(&mut self, items: impl Into<Vec<String>>, desc: impl Into<String>)`** — Wraps each item in `SuggestItem::WithDescription` using the provided description and inserts it into the set. + + These methods enable ergonomic batch population of suggestion sets from collections of strings, complementing the existing `insert()` method. + +4. **[`macros:gen_program`]** Added a `CRATE_ROOT` module that is only visible when the `docs_rs` feature is enabled. This module exists purely for docs.rs documentation purposes — it provides a placeholder view of the structures, enums, and other items that `gen_program!()` generates into `crate::*`, allowing users to inspect and understand the behavior behind `gen_program!()` through generated documentation. + + When the `docs_rs` feature is enabled, `gen_program!()` emits a `#[doc(hidden)]` `CRATE_ROOT` module (with the hidden attribute removed when `docs_rs` is active) containing doc comments that describe the generated items and their relationships. This gives users browsing docs.rs a clear picture of what `gen_program!` expands to — the `ThisProgram` type alias, the `Enum` enum, the `Entry` pack type, chain process types, and related plumbing — without needing to manually trace macro expansions. + + When `docs_rs` is disabled (the default), the `CRATE_ROOT` module is not emitted at all, so there is zero impact on normal builds, generated code size, or compilation times. + #### Features: 1. **[`picker:value:paths`]** Added new path wrapper types to `arg_picker::value` for filesystem-aware argument parsing: @@ -96,7 +128,7 @@ None These methods provide ergonomic alternatives to `to_result()` + `unwrap()` / `unwrap_or_default()` / `unwrap_or_else()` / `expect()` chaining, reducing boilerplate when working with `PickArgParsed` tuples directly. -3. **[`macros:command`]** Added the `#[command]` attribute macro (feature-gated behind `extra_macros`) that converts a plain function with a `Vec<String>` parameter into a fully wired Mingling command. The macro: +3. **[`macros:command`]** Added the `#[command]` attribute macro (feature-gated behind `extras`) that converts a plain function with a `Vec<String>` parameter into a fully wired Mingling command. The macro: - Calls `dispatcher!("command_name")` to register the dispatcher entry. - Generates a `#[chain]` wrapper that bridges the entry type (`Entry{Pascal}`) to the original function. @@ -142,9 +174,92 @@ None 7. **[`core`]** **[`comp`]** Added `Suggest::combine(self, other: impl Into<Suggest>) -> Self` method that merges two `Suggest` values. If both are `Suggest::Suggest`, their inner `BTreeSet`s are merged (all items from `other` are added into `self`). Otherwise, the first `Suggest::Suggest` (or `FileCompletion`) is returned unchanged, and the other value is discarded. This enables ergonomic aggregation of completion suggestions from multiple sources. +**[`features`]** Added preset feature groups to `mingling/Cargo.toml`, providing convenience combinations for common use cases: + +- **`mini`** — `extras`, `picker`. Minimal mode for small CLI tools. +- **`advanced`** — `extras`, `picker`, `repl`, `comp`, `dispatch_tree`, `structural_renderer`. Full-featured mode for medium-sized applications. +- **`full`** — `extras`, `picker`, `repl`, `clap`, `comp`, `dispatch_tree`, `structural_renderer_full`, `pathf`. Complete mode for large, feature-comprehensive applications. +- **`build_advanced`** — `build`, `comp`. Build-time configuration for generating completion scripts etc. +- **`build_full`** — `build`, `comp`, `pathf`, `dispatch_tree`. Full build-time configuration including the path analyzer. + + `build_advanced` and `build_full` are intended for use in `[build-dependencies]` alongside their corresponding runtime feature groups. + + Also reorganized the `[features]` section of `mingling/Cargo.toml` into logical subsections (Presets, Core, Special features, Features, LEGACY) for improved maintainability and documentation. + +8. **[`core`]** **[`macros`]** Added the `#[completion(EntryFallback)]` syntax to the `#[completion]` macro, mirroring the `#[help(EntryFallback)]` pattern. When the `EntryFallback` identifier is passed (either as a bare path in the attribute arguments), the macro generates a chain handler for the `EntryFallback` type (the program's fallback entry pack type generated by `gen_program!()`). This handler is invoked during the default-completion path when no explicit dispatcher match is found. + + When the program's dispatcher fails to find a match in the completion pipeline, the `CompletionHelper::complete` method now: + + - Checks for an explicit completion handler via the chain pipeline for the `EntryFallback` type (calling `P::do_comp(&P::build_entry_fallback(vec![]), ctx)`). + - If that produces suggestions, they are combined with the default completion suggestions via `Suggest::combine()` (which merges `BTreeSet`s for `Suggest::Suggest` values). + - Falls back to the standard `default_completion::<P>(ctx)` behavior when no explicit fallback handler yields results. + + This enables users to provide custom completion suggestions for the fallback/unmatched case: + + ```rust,ignore + #[completion(EntryFallback)] + fn complete_fallback(_ctx: &ShellContext) -> Suggest { + suggest! { "fallback" } + } + ``` + + The generated chain handler for `EntryFallback` is identical to how `#[chain]`-annotated functions targeting entry pack types work — the `EntryFallback` type name is resolved through the same `chain` code-generation path used for `Entry{Type}` types, allowing users to write a dedicated completion function for the fallback entry point without manually registering it in the program's dispatcher. + + Internal changes: + - `mingling_macros/src/attr/completion.rs` updated to detect the `EntryFallback` identifier in attribute arguments. + - `CompletionHelper::complete` in `mingling_core/src/comp.rs` now invokes the fallback completion handler via `P::do_comp(&P::build_entry_fallback(vec![]), ctx)` and merges results with `Suggest::combine()`. + #### **BREAKING CHANGES** (API CHANGES): -None +1. **[`macros`]** **[BREAKING]** Renamed the `extra_macros` feature to `extras`. All feature-gated macro re-exports in `mingling/src/lib.rs` (and throughout the codebase) have been updated from `#[cfg(feature = "extra_macros")]` to `#[cfg(feature = "extras")]`. + + **Affected macros** (all previously gated behind `extra_macros`, now `extras`): + - `#[command]` + - `empty_result!` + - `entry!` + - `group!` + - `group_structural!` (also requires `structural_renderer`) + - `pack_err!` + - `pack_err_structural!` (also requires `structural_renderer`) + - `#[program_setup]` + - `render_route!` + - `#[renderify]` + - `route!` + - `#[routeify]` + + **Migration guide:** + - Update `Cargo.toml` feature declarations from `extra_macros` to `extras`. + - If your code references `mingling::feature::MINGLING_EXTRA_MACROS`, update it to `mingling::feature::MINGLING_EXTRAS`. + + _No behavioral changes — this is a pure feature rename. The `extras` feature provides identical functionality to the old `extra_macros` feature; all prelude and macros module re-exports remain the same under the new feature name._ + +2. **[`core`]** **[BREAKING RENAME]** Renamed the internal fallback type `ErrorDispatcherNotFound` and its associated `ProgramCollect` plumbing to `EntryFallback` / `build_entry_fallback`. + + **Associated type renames (on `ProgramCollect`):** + + - `type ErrorDispatcherNotFound` → `type EntryFallback` + - `fn build_dispatcher_not_found(args)` → `fn build_entry_fallback(args)` + + **Type/enum renames generated by `gen_program!()`:** + + - Enum variant `ThisProgram::ErrorDispatcherNotFound` → `ThisProgram::EntryFallback` + - Pack type `ErrorDispatcherNotFound` → `EntryFallback` (created by `program_fallback_gen!()` via `pack!(EntryFallback = Vec<String>)`) + + **Migration guide (for downstream code):** + + - Renderer/help functions that previously took `ErrorDispatcherNotFound` as a parameter must now take `EntryFallback`. + - Any code referencing `C::build_dispatcher_not_found(...)` must now call `C::build_entry_fallback(...)`. + - Any manual `ProgramCollect` implementation (e.g., in tests or mocks) must rename both the associated type `ErrorDispatcherNotFound` → `EntryFallback` and the associated method `build_dispatcher_not_found` → `build_entry_fallback`. + + _No behavioral changes — this is a pure rename of the internal fallback type and its associated `ProgramCollect` methods. The type's semantics, shape (wrapping `Vec<String>`), and rendering behavior are unchanged. + +3. **[`picker:global`]** **[`setups:picker`]** Refactored the global picker utility functions into a trait-based API. The standalone functions `pick_global_flag(program, flag)` and `pick_global_argument(program, arg)` in `mingling::picker` have been replaced by the `PickerHelper<C>` trait, implemented for `Program<C>`. This trait provides `pick_flag(&mut self, flag: &PickerArg<Flag>) -> bool` and `pick_argument<A>(&mut self, arg: &PickerArg<A>) -> Option<A>`, and is backed by the `take_args` / `replace_args` methods on `Program`. + + **Migration guide:** + + - `pick_global_flag(program, flag)` → `program.pick_flag(flag)` + - `pick_global_argument(program, arg)` → `program.pick_argument(arg)` + - Import `mingling::picker::PickerHelper` instead of `mingling::picker::{pick_global_flag, pick_global_argument}` --- @@ -472,7 +587,7 @@ None } ``` - The `#[routeify]` macro is feature-gated behind `extra_macros` and re-exported as `mingling::macros::routeify`. + The `#[routeify]` macro is feature-gated behind `extras` and re-exported as `mingling::macros::routeify`. Internal changes: - Added `mingling_macros/src/extensions/routeify.rs` with `routeify_impl` implementation. @@ -540,7 +655,7 @@ None When used as a renderer/help extension, the `renderify` identifier is detected by the extension point mechanism, stripped from the attribute arguments, and `#[renderify]` is applied as an outer attribute on top of `#[renderer]`/`#[help]` — just like `routeify` works with `#[chain]`. - Both `render_route!` and `#[renderify]` are feature-gated behind `extra_macros` and re-exported as `mingling::macros::render_route` and `mingling::macros::renderify` respectively. + Both `render_route!` and `#[renderify]` are feature-gated behind `extras` and re-exported as `mingling::macros::render_route` and `mingling::macros::renderify` respectively. Internal changes: - Added `mingling_macros/src/extensions/renderify.rs` with `renderify_impl` implementation. @@ -557,7 +672,7 @@ None fn some_item() {} ``` - Since the attribute is a no-op at compile time, it has no effect on code generation, type checking, or runtime behavior. Its purpose is to serve as a structured annotation that `mlint` tooling can parse from the AST. The attribute is feature-gated behind `extra_macros`. + Since the attribute is a no-op at compile time, it has no effect on code generation, type checking, or runtime behavior. Its purpose is to serve as a structured annotation that `mlint` tooling can parse from the AST. The attribute is feature-gated behind `extras`. 16. **[`core`]** Added `RendererInvoker<T, C>` and `ChainInvoker<T, C>` types to `mingling_core::asset::core_invokes`, providing a mechanism for selectively invoking renderer and chain pipelines for specific types from within chain/renderer functions via resource injection. @@ -870,7 +985,7 @@ None - `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-repl`: ResREPL and basic types with `repl + extras` 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.) @@ -1034,7 +1149,7 @@ impl ErrorNotDir { } ``` -This macro is only available with the `extra_macros` feature. +This macro is only available with the `extras` feature. 9. **[`mingling`]** Added `Groupped` trait to the `mingling::prelude` module, so it can now be imported via `use mingling::prelude::*` without needing to separately import the trait from the `mingling` crate root. @@ -1053,7 +1168,7 @@ An aliased syntax is also supported for descriptive variant naming: group!(IoError = std::io::Error); ``` -This macro is only available with the `extra_macros` feature. +This macro is only available with the `extras` feature. 11. **[`macros`]** `#[help]` and `#[completion]` now support resource injection parameters, consistent with `#[chain]` and `#[renderer]`. Specific changes: @@ -1444,7 +1559,7 @@ fn render(prev: Previous) { // Implicitly introduces `__renderer_inner_result` } ``` -5. **[`macros`]** Moved the `entry!`, `route!`, `#[program_setup]` macros into the `extra_macros` feature +5. **[`macros`]** Moved the `entry!`, `route!`, `#[program_setup]` macros into the `extras` feature 6. **[`macros`]** The `crate::Next` generated by `gen_program!()` now requires explicit import into the project |
