You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
[core] Add auto dispatch + Extend the mgit example (#49)
This PR adds Cobra-style auto-dispatch to ArgMojo commands (register
per-command handlers and run via `execute()`), expands the `mgit`
example to use the new dispatch model (including nested subcommands),
and wires in tests + tooling updates to exercise the feature.
**Changes:**
- Introduce `Command.set_run_function(handler)` and `Command.execute()`
with recursive subcommand dispatch (plus `_execute_with_arguments()`
test helper).
- Add a dedicated test suite validating dispatch behavior across
root/subcommands/nested commands, aliases, persistent flags, and error
cases.
- Extend documentation and examples (`mgit`) to demonstrate and describe
auto-dispatch; adjust Pixi tasks to include the new tests and use a new
example build script.
- [x] **Confirmation option** — `confirmation_option()` or `confirmation_option["prompt"]()` auto-registers `--yes`/`-y` flag; prompts user for confirmation after parsing; aborts on decline or non-interactive stdin (Click `confirmation_option`) (PR #26)
572
-
- [] **Pre/Post run hooks** — callbacks before/after main logic (cobra `PreRun`/`PostRun`)
573
+
- [x] **Auto-dispatch** — `set_run_function(handler)` registers a `def (ParseResult) raises`functionpointer on a `Command`; `execute()` parses and walks the subcommand chain to invoke the matching handler;`_execute_with_arguments(args)` provides the same dispatch fortesting. **Lifecycle hooks** (PersistentPreRun/PreRun/PostRun/PersistentPostRun) are not yet implemented — they depend on auto-dispatch and will be addedin a future release.
573
574
- [x] **Remainder positional** — `.remainder()` consumes ALL remaining tokens (including `-` prefixed); at most one per command, must be last positional (argparse `nargs=REMAINDER`, clap `trailing_var_arg`) (PR #13)
574
575
- [x] **Allow hyphen values** — `.allow_hyphen_values()` on positional accepts dash-prefixed tokens as values without `--`; remainder enables this automatically (clap `allow_hyphen_values`) (PR #13)
575
576
- [ ] **Regex validation** — `.pattern(r"^\d{4}-\d{2}-\d{2}$")` validates value format (no major library has this)
@@ -580,6 +581,7 @@ Before adding Phase 5 features, further decompose `parse_arguments()` for readab
580
581
- [x] **`NO_COLOR` env variable** — honour the [no-color.org](https://no-color.org/) standard: if env `NO_COLOR` is set (any value, including empty), suppress all ANSI colour output; lower priority than explicit `.color(False)` API call (PR #9)
581
582
- [x] **Value-name wrapping control** — `.value_name[wrapped: Bool = True]("NAME")` displays custom value names in`<NAME>` by default (matching clap/cargo/pixi/git convention); pass `False`for bare display (PR #17)
582
583
- [ ] **Extend `implies()`** - support value-taking options with a default value, e.g., `cmd.implies("debug", "output", "debug.log")` — when `--debug` is set, auto-set `--output` to `"debug.log"`. Currently `implies()` only supports flag/count targets (same as cobra in Go). Revisit when there is a concrete use case.
584
+
- [ ] **80-character help formatting** — wrap help descriptions at 80 columns with proper indentation (no major library does this by default; users typically pipe through `less` or rely on terminal wrapping)
583
585
584
586
#### Explicitly Out of Scope in This Phase
585
587
@@ -606,7 +608,7 @@ ArgMojo's differentiating features — no other CLI library addresses CJK-specif
606
608
--ling 使用宇浩靈明編碼 ← CJK chars each take 2 columns, misaligned
607
609
```
608
610
609
-
**Implementation:**
611
+
##### Implementation (CJK alignment)
610
612
611
613
- [x] Implement `_display_width(s: String) -> Int` in `utils.mojo`, traversing each code point:
@@ -623,7 +625,7 @@ ArgMojo's differentiating features — no other CLI library addresses CJK-specif
623
625
- `--verbose` instead of `--verbose`
624
626
- `=` instead of `=`
625
627
626
-
**Implementation:**
628
+
##### Implementation (fullwidth correction)
627
629
628
630
- [x] Implement `_fullwidth_to_halfwidth(token: String) -> String` in `utils.mojo`:
629
631
- Full-width ASCII range: `U+FF01`–`U+FF5E` → subtract `0xFEE0` to get half-width
@@ -652,7 +654,7 @@ Note that the following punctuation characters are already handled by the full-w
652
654
- `——verbose` (em-dash `U+2014` × 2) instead of `--verbose`
653
655
- `--key:value` (full-width colon `U+FF1A`) instead of `--key=value`
654
656
655
-
**Implementation:**
657
+
##### Implementation (CJK punctuation)
656
658
657
659
- [x] Integrate with typo suggestion system — when a token fails to match any known option, check for common CJK punctuation patterns before running Levenshtein:
658
660
- `——` (`U+2014 U+2014`, 破折號) → `--` (note that `U+FF0D` full-width hyphen-minus is already handled by the full-width correction step)
@@ -679,10 +681,11 @@ The features below are **not part of the core builder API**. They are split into
679
681
680
682
These features use capabilities already available in Mojo 0.26.2 and can be experimented with immediately.
- **Optional** — Users who prefer the builder API are completely unaffected. Zero change to existing code.
693
696
694
-
**Pre/Post run hooks** — Straightforward callback mechanism (`def(ParseResult) raises`). No special language features needed; just needs API design and a decision on execution order with subcommands.
697
+
**Auto-dispatch** — Implemented via `set_run_function()` + `execute()`. Registers a non-capturing functionpointer (`def (ParseResult) raises`) on each `Command`. `execute()` parses `sys.argv()`, walks the subcommand chain, and invokes the leaf handler. `_execute_with_arguments(args)` provides the same dispatch fortesting with explicit argument lists. Works with aliases, nested subcommands, and persistent flags. Closures cannot be stored as struct fieldsin Mojo 0.26.2 (only non-capturing functionpointers via the `def (...) raises` type), so handlers must be free functions.
698
+
699
+
**Pre/Post lifecycle hooks** — Now unblocked by auto-dispatch. Straightforward extension: add `_pre_run_function` / `_post_run_function` fields with the same functionpointer type. Execution order: PersistentPreRun → PreRun → Run → PostRun → PersistentPostRun. Will be implemented in a future release.
Copy file name to clipboardExpand all lines: docs/changelog.md
+1Lines changed: 1 addition & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -6,6 +6,7 @@ This document tracks all notable changes to ArgMojo, including new features, API
6
6
Unreleased changes should be commented out from here. This file will be edited just before each release to reflect the final changelog for that version. Otherwise, the users would be confused.
7
7
8
8
- Add `allow_negative_expressions()` on `Command` — treats single-hyphen tokens as positional arguments when they don't conflict with registered short options. Handles mathematical expressions like `-1/3*pi`, `-sin(2)`, `-e^2`. Superset of `allow_negative_numbers()`.
9
+
- Add **auto-dispatch** — `set_run_function(handler)` registers a `def (ParseResult) raises` handler on a `Command`; `execute()` parses and auto-dispatches to the matching handler, eliminating manual `if/elif` subcommand chains. `_execute_with_arguments(args)` provides the same dispatch for testing with explicit argument lists. Works with nested subcommands, aliases, and persistent flags.
0 commit comments