Releases: forfudan/argmojo
ArgMojo v0.5.0
20260404 (v0.5.0)
ArgMojo v0.5.0 introduces the struct-based declarative API — define a Parsable struct with typed wrapper fields (Option, Flag, Positional, Count), call MyArgs.parse(), and get typed results. The declarative API coexists with the existing builder API and bridges between them via to_command() / parse_from_command(). This release also adds asterisk-masked password input and reorganises internal modules.
ArgMojo v0.5.0 targets Mojo v0.26.2.
⭐️ New in v0.5.0
- Declarative API core —
Parsabletrait with compile-time reflection over wrapper-typed fields. Conforming structs need only declare fields and providedescription(); all parsing, Command-building, and write-back methods are provided as trait defaults (PR #34, #35, #37, #40). - Wrapper types —
Option[T, ...],Flag[...],Positional[T, ...],Count[...]parametric structs encode CLI metadata as compile-time parameters. Conform to the internalArgumentLiketrait withadd_to_command()/read_from_result()hooks (PR #34). - Auto-initialisation —
Parsable.__init__usesmark_initialized+comptime for+UnsafePointer.init_pointee_moveto default-construct all fields via reflection. Users never need to write__init__(PR #37). - Hybrid bridge —
to_command()reflects aParsablestruct into an ownedCommandfor builder-level customisation;parse_from_command(cmd^)parses back into a typed struct (PR #35, #40). - Dual-return parsing —
parse_full()returnsTuple[Self, ParseResult]for workflows that need both typed struct fields and rawParseResultaccess (e.g. subcommand dispatch).parse_full_from_command(cmd^)does the same from a pre-configured Command (PR #40, #42). - Subcommand support —
subcommands()hook onParsablereturnsList[Command]; called automatically byto_command()for recursive tree assembly.run(self)method for leaf command execution.from_parse_result()for typed write-back from subcommand results (PR #39, #43). - Asterisk-masked password input —
.password[True]()onArgumentechoes*for each keystroke (sudo-rs style), complementing the existing.password()which hides input entirely. Uses raw terminal mode with ICANON/ISIG disabled (PR #32).
🦋 Changed in v0.5.0
- Remove
Argalias forArgumentand dropArgumentLikefrom the public export list. The public API now exports:Argument,Command,ParseResult,Parsable,Option,Flag,Positional,Count(PR #42). subcommands()hook signature changed fromsubcommands(mut cmd: Command) raisestosubcommands() raises -> List[Command]— returns a list of Commands instead of mutating one (PR #43).- Reorganise
ArgumentandCommandsource files into clearly grouped internal sections for readability (PR #33).
📚 Documentation and testing in v0.5.0
- Add
docs/declarative_api_planning.md— comprehensive design document for the declarative API (PR #33). - Add 4 declarative examples:
search.mojo(pure declarative),deploy.mojo(hybrid),convert.mojo(full parse + extra builder args),jomo.mojo(subcommands with hybrid tree) (PR #41). - Add 4 test modules:
test_wrappers.mojo(wrapper defaults, copy/move,Flag.__bool__),test_declarative.mojo(to_command, parse_args, from_parse_result),test_hybrid.mojo(builder customisation, mutually exclusive, implies, configure pattern),test_subcommands_declarative.mojo(flat/nested subcommands, run() dispatch, dual return) (PR #38, #39). - Add
test_interactive.mojofor interactive prompting edge cases (PR #33). - Add method matrix table to README, user manual, and planning doc.
- Update README with declarative API Quick Start, examples table, and project structure.
- Update user manual with declarative API usage guide, full-parse section, and API summary.
What's Changed
- [core] Enable asterisk-masked password input by @forfudan in #32
- [doc] Add a planning file for declarative API + Reorganize
Command/Argumentinternals for clearer grouping by @forfudan in #33 - [core][declarative] Implement argument wrappers and Parsable trait by @forfudan in #34
- [core][declarative] Implement
Parsablereflection, trait methods, and example by @forfudan in #35 - [core][declarative] Use
rebindinstead ofUnsafePointerin argument wrapper write-back logic by @forfudan in #36 - [core][declarative] Default-initialize all fields via reflection in
__init__ofParsabletrait by @forfudan in #37 - [core][declarative] Add tests for hybrid declarative + builder API by @forfudan in #38
- [core][declarative] Add tests for declarative subcommands by @forfudan in #39
- [core][declarative] Consolidate Parsable trait functions into methods by @forfudan in #40
- [core][declarative] Add more examples of declarative API by @forfudan in #41
- [core][declarative][doc] Enrich documentation and rename some methods by @forfudan in #42
- [core][declarative] Update
to_commandso that it returns a list ofCommandby @forfudan in #43 - [declarative][doc] Standardize
Parsableparsing method names + Update documents for release by @forfudan in #44
Full Changelog: v0.4.0...v0.5.0
ArgMojo v0.4.0
20260321 (v0.4.0)
ArgMojo v0.4.0 adds interactive prompting, password input, confirmation, argument parents, custom usage lines, response files, CJK-aware help formatting, and full-width auto-correction. The builder API is fully parameterised with compile-time StringLiteral parameters. The codebase is migrated to Mojo v0.26.2 and the test suite consolidated from 20 files into 8 modules.
ArgMojo v0.4.0 targets Mojo v0.26.2.
⭐️ New in v0.4.0
- Add
.default_if_no_value["value"]()— option appears without a value to use the fallback; with=valueto override. For long options, implies.require_equals()(PR #12). - Add
.require_equals()— long options reject space-separated values and require--key=valuesyntax. Help output adapts:--key=<value>for require-equals,--key[=<value>]for default-if-no-value (PR #12). - Add
response_file_prefix()onCommandfor@args.txtexpansion with comments, escaping, and recursive nesting. (Temporarily disabled due to a Mojo compiler deadlock under-D ASSERT=all.) (PR #12). - Add
.remainder()onArgument— consume all remaining tokens (including dash-prefixed) as a single positional, similar to argparsenargs=REMAINDER(PR #13). - Add
parse_known_arguments()onCommand— unrecognised options are collected viaresult.get_unknown_args()instead of raising an error (PR #13). - Add
.allow_hyphen_values()onArgument— accept tokens starting with-as values without requiring--first; covers the stdin-convention (PR #13). - CJK-aware help alignment using terminal display width; CJK characters treated as 2-column-wide. No API changes — automatic (PR #14).
- Full-width → half-width auto-correction with a coloured warning when CJK users type fullwidth ASCII (e.g.,
--verbose→--verbose). Disabled viadisable_fullwidth_correction()(PR #15). - CJK punctuation auto-correction — em-dash
——verbosecorrected to--verbose. Disabled viadisable_punctuation_correction()(PR #16). - Add
.group["name"]()onArgument— group arguments under dedicated headings in--helpoutput (PR #17). - Value-name wrapping control:
.value_name["NAME"]()renders as<NAME>by default;.value_name["NAME", False]()renders bare (PR #17). - Add runtime
generate_completion("shell")overload alongside the existing compile-timegenerate_completion["shell"]()(PR #19). - Registration-time validation for
mutually_exclusive(),required_together(),one_required(), andrequired_if()— catches typos, empty lists, and self-referential rules immediately atadd_argument()time (PR #22). - Add
.prompt()/.prompt["text"]()onArgument— interactively prompt for missing values before validation. Shows choices and defaults; handles non-interactive stdin gracefully (PR #23). - Add
add_parent(parent)onCommand— share argument definitions and group constraints across commands, equivalent to argparseparents(PR #25). - Add
confirmation_option()onCommand— register--yes/-yand prompt for confirmation after parsing;--yesskips the prompt (PR #26). - Add
usage(text)onCommand— replace the auto-generated usage line with a custom string (PR #27). - Add
.password()onArgument— hide typed input via POSIXtcsetattr(3)during prompts, equivalent to Clickhide_input=True(PR #28).
🔄 Mojo v0.26.2 migration (PR #29)
- Bump Mojo dependency to
==0.26.2inpixi.toml. - Migrate stdlib imports to
std.*namespace (from sys→from std.sys, etc.). - Replace
constrained[]withcomptime assertand@parameter ifwithcomptime if. - Unify
__copyinit__/__moveinit__to new__init__(out self, *, copy/take: Self)forms. - Remove
Stringablefrom trait lists (removed from stdlib). - Add
byte=keyword to all string slicing operations. - Replace
fnwithdefacross all 30 files (754 declarations). - Remove
__str__methods; consolidate string output intowrite_to(Mojo v0.26.2 convention).
🦋 Changed in v0.4.0
- Rename
.metavar()to.value_name()across the entire API (PR #13). - Parameterise
.long[]()and.short[]()as compile-timeStringLiteralparameters (PR #20). - Parameterise
.alias_name[](),.delimiter[](),.default[](),.deprecated[](),.default_if_no_value[](),.group[](),.prompt[](), and colour setters (header_color[],arg_color[],warn_color[],error_color[]) as compile-time parameters (PR #18, #21). - Replace
.choices(list)with chained.choice["a"]().choice["b"]()compile-time parameters (PR #18). - Value-name display uses angle brackets by default;
.value_name["FOO", False]()for bare display (PR #17). - Move
print_summary()fromCommandtoParseResult(PR #24).
🔧 Fixes in v0.4.0
- Clarify that
default_if_no_valuedoes not "reject"--key value— it simply does not consume the next token (PR #12). - Fix Click description: "Python CLI framework", not "built on top of argparse" (PR #12).
- Reject
.require_equals()/.default_if_no_value()combined with.number_of_values[N]()atadd_argument()time (PR #12).
📚 Documentation and testing in v0.4.0
- Consolidate test suite from 20 files into 8 focused modules (PR #30).
- Add Developer Validation section to user manual with two-layer validation model (compile-time + registration-time) (PR #22).
- Add
pixi run debugtask for-D ASSERT=allregression testing (PR #22).
What's Changed
- [core] Add
default_if_no_valueandrequire_equals+ add cross-library reference in user manual by @forfudan in #12 - [core] Implement response file (but temporarily not exposed to users due to issues when setting
ASSERT=all) by @forfudan in #13 - [core] Rename
metavartovalue_name+ consume remainder args + hyphen values + partial parsing by @forfudan in #14 - [core][cjk] Implement CJK-aware help formatting by @forfudan in #15
- [core][cjk] Implement fullwidth-to-halfwidth conversion by @forfudan in #16
- [core] Add argument goups in help message by @forfudan in #17
- [core] Convert color customization to a compile-time parameter of
StringLiteraltype by @forfudan in #18 - [core] Provide
generate_completionoverload that takes shell name as parameter by @forfudan in #19 - [core] Make long name and short name compile-time parameters by @forfudan in #20
- [core] Convert all other arguments of the methods of the
Argumenttype to compile-time parameters by @forfudan in #21 - [core] Implement aggressive runtime validation for
Commandby @forfudan in #22 - [core] Enable interactive prompting for arguments by @forfudan in #23
- [core] Move
print_summaryfromCommandtoParseResultby @forfudan in #24 - [core] Add argument parents by @forfudan in #25
- [core] Add confirmation option (--yes / -y) by @forfudan in #26
- [core] Enable custom usage line by @forfudan in #27
- [core] Add password / masked input capability by @forfudan in #28
- [test] Consolidate the test suite by @forfudan in #30
- [doc] Update documents for release by @forfudan in #31
Full Changelog: v0.3.0...v0.4.0
ArgMojo v0.3.0
20260305 (v0.3.0)
ArgMojo v0.3.0 adds shell completion, typo suggestions, mutual implication, hidden subcommands, NO_COLOR support, and several builder-method improvements. Internally the code is decomposed into smaller helpers and a new utils.mojo module; several API names are refined for consistency. Two breaking changes affect call sites that use nargs, max, or range (now compile-time parameters) and the renamed methods listed below.
ArgMojo v0.3.0 is compatible with Mojo v0.26.1.
⭐️ New in v0.3.0
- Implement shell completion script generation for Bash, Zsh, and Fish, with a built-in
--completions <shell>flag that emits a ready-to-source script (PR #4). - Allow disabling the built-in flag (
disable_default_completions()), customising the trigger name (completions_name()), or exposing completions as a subcommand (completions_as_subcommand()) (PR #4). - Add Levenshtein-distance based "did you mean ...?" suggestions for misspelled long options and subcommand names (PR #3).
- Implement
command_aliases()onCommandto register alternative names for subcommands. Aliases are shown in help, accepted during dispatch, and included in shell completions and typo suggestions (PR #5). - Add
.clamp()modifier for.range[min, max]()-- out-of-range values are adjusted to the nearest boundary with a warning instead of a hard error (PR #6). - Move count-ceiling enforcement (
.max[N]()) and range validation into the_validate()phase so all post-parse checks run in a single pass (PR #6). - Parameterise
.max[ceiling](),.range[min, max](), and.number_of_values[N]()as compile-time parameters, enabling build-time validation of invalid values (PR #8). - Add
Command.hidden()builder method. Hidden subcommands are excluded from help output, shell completions, "Available commands" error messages, and typo suggestions, while remaining dispatchable by exact name or alias (PR #9). - Honour the
NO_COLORenvironment variable (any value, including empty). When set, all ANSI colour output from help, warning, and error messages is suppressed, following the no-color.org standard (PR #9). - Add
Command.implies(trigger, implied)to automatically set one argument when another is present. Supports chained implications (A -> B -> C) with cycle detection at registration time. Works with flags and count arguments, and integrates with existing constraints (required_if,mutually_exclusive) (PR #10).
🦋 Changed in v0.3.0
parse_args()renamed toparse_arguments()(PR #5).help_on_no_args()renamed tohelp_on_no_arguments()(PR #5)..nargs()renamed to.number_of_values()andnargs_countfield renamed to_number_of_values(PR #5).- Several
ArgumentandParseResultattributes are now underscore-prefixed (private). Public builder methods are unchanged (PR #7). - Decompose
parse_args()into four sub-methods:_parse_long_option(),_parse_short_single(),_parse_short_merged(),_dispatch_subcommand()(PR #2). - Decompose
_generate_help()into five sub-methods:_help_usage_line(),_help_positionals_section(),_help_options_section(),_help_commands_section(),_help_tips_section()(PR #2). - Extract ANSI colour constants and utility functions into a new internal module
utils.mojo(PR #2). - Rename example files to avoid confusion:
git.mojo->mgit.mojo,grep.mojo->mgrep.mojo. - Add
examples/demo.mojo-- a comprehensive showcase of all ArgMojo features in a single CLI (PR #7).
📚 Documentation and testing in v0.3.0
- Add
tests/test_typo_suggestions.mojocovering Levenshtein-based suggestions (PR #3). - Add
tests/test_completion.mojowith comprehensive tests for Bash, Zsh, and Fish script generation (PR #4). - Add
tests/test_implies.mojocovering basic, chained, and multi-target implications, cycle detection, and constraint integration (PR #10). - Add builder method compatibility section to the user manual with an ASCII tree, Mermaid diagram, and compatibility table (PR #11).
- Set up GitHub Actions workflow for automatic wiki synchronisation from
docs/user_manual.md. - Update user manual to cover all new features.
What's Changed
- [core] Refactor: decompose large methods & extract utils.mojo by @forfudan in #2
- [core] Add typo-suggestion support via Levenshtein distance by @forfudan in #3
- [core] Add shell completion support + built-in completion by @forfudan in #4
- [core] Implement command aliases by @forfudan in #5
- [core] Add range clamping + conduct ceiling and clamping at validation phase + warning message by @forfudan in #6
- [core][demo] Provide a new demo + make some attributes private + rename some attributes and methods by @forfudan in #7
- [core] Parameterize some arguments to enable compile-time check by @forfudan in #8
- [core] Add hidden subcommands + NO-COLOR option by @forfudan in #9
- [core] Add mutual implication functionality by @forfudan in #10
- [doc] Add compatibility charts in user manual showing relationship between builder methods by @forfudan in #11
Full Changelog: v0.2.0...v0.3.0
ArgMojo v0.2.0
20260228 (v0.2.0)
ArgMojo v0.2.0 is a major release that transforms the library from a single-command parser into a full subcommand-capable CLI framework. It introduces hierarchical subcommands with automatic dispatch, persistent (global) flags with bidirectional sync, negative number passthrough, colored error messages, custom tips, and significant help/UX improvements. The public API is also refined: Arg → Argument (old name kept as alias). Two complete example CLIs (grep and git) replace the previous demo.
ArgMojo v0.2.0 is compatible with Mojo v0.26.1.
⭐️ New in v0.2.0
Subcommands:
- Implement full subcommand support with
add_subcommand()API, hierarchical dispatch, and nested subcommands (e.g.,git remote add). - Auto-register a
helpsubcommand so thatapp help <command>works out of the box; opt out withdisable_help_subcommand(). - Add
allow_positional_with_subcommands()guard — prevents accidental mixing of positional args and subcommands on the sameCommand, following the cobra/clap convention. Requires explicit opt-in. - Add
subcommandandsubcommand_resultfields onParseResultwithhas_subcommand_result()/get_subcommand_result()accessors.
Persistent flags:
- Add
.persistent()builder method onArgumentto mark a flag as global. - Persistent args are automatically injected into child commands and support bidirectional sync: flags set before the subcommand push down to the child, and flags set after the subcommand bubble up to the root.
- Detect conflicting long/short names between parent persistent args and child local args at registration time (
add_subcommand()raises an error).
Negative number passthrough:
- Recognize negative numeric tokens like
-3.14or-42as positional values instead of unknown short options. - Add
allow_negative_numbers()opt-in onCommandfor explicit control.
Custom tips:
- Add
add_tip()API onCommandto attach user-defined tips that render as a dedicated section at the bottom of help output.
Error handling:
- Colored error and warning messages — ANSI-styled stderr output for all parse errors.
- Unknown subcommand error now lists all available commands.
- Errors inside child parse are prefixed with the full command path (e.g.,
git remote add: ...).
🦋 Changed in v0.2.0
API rename:
- Rename
Argstruct toArgument. The old name is kept as alias for convenience. - Rename source files:
arg.mojo→argument.mojo,result.mojo→parse_result.mojo.
Help & UX improvements:
- Add a "Commands" section to help output listing available subcommands with aligned descriptions.
- Show
<COMMAND>placeholder in the usage line for commands that have subcommands. - Display persistent flags under a "Global Options" heading in child help.
- Show the full command path in child help and error messages (e.g.,
Usage: git remote add [OPTIONS] NAME URL).
Internal refactoring:
- Extract
_apply_defaults()and_validate()into private helper methods onCommand, enabling clean reuse for both root and child parsing.
📚 Documentation and testing in v0.2.0
- Add two complete example CLIs:
examples/grep.mojo(single-command, demonstrating all argument features) andexamples/git.mojo(subcommand-based, with nested subcommands and persistent flags). - Add
tests/test_subcommands.mojocovering data model, dispatch, help subcommand, persistent flags, allow-positional guard, and error handling. - Add
tests/test_negative_numbers.mojo. - Add
tests/test_persistent.mojo. - Update user manual (
docs/user_manual.md) to cover all new features.
ArgMojo v0.1.0
20260224 (v0.1.0)
ArgMojo v0.1.0 is the initial release of a command-line argument parser library for Mojo. It provides a builder-pattern API for defining and parsing CLI arguments, inspired by Python's argparse, Rust's clap, and Go's cobra.
ArgMojo v0.1.0 is compatible with Mojo v0.26.1.
⭐️ Features
- Long and short options:
--output file.txt,--output=file.txt,-o file.txt,-ofile.txt - Boolean flags: options that take no value (
--verbose,-v) - Positional arguments: matched by position, with count validation
- Default values: fallback when an argument is not provided
- Required arguments: validation that mandatory arguments are present
- Auto-generated help:
--help/-hwith formatted usage and descriptions - Version display:
--version/-V --stop marker: everything after--is treated as positional- Short flag merging:
-abcexpands to-a -b -c - Attached short values:
-ofile.txtis equivalent to-o file.txt - Choices validation: restrict values to an allowed set (e.g.,
json,csv,table) - Metavar: custom display name for values in help text (e.g.,
--format <FMT>) - Hidden arguments: exclude internal arguments from
--helpoutput - Count flags:
-vvv→get_count("verbose") == 3 - Negatable flags:
--color/--no-colorpaired flags with.negatable() - Mutually exclusive groups: prevent conflicting flags (e.g.,
--jsonvs--yaml) - Required-together groups: enforce related flags are provided together (e.g.,
--username+--password) - Long option prefix matching: allow abbreviated options (e.g.,
--verb→--verbose), with ambiguity detection print_summary()method: human-readable summary of all parsed arguments
📚 Documentation and testing
- Comprehensive user manual covering every feature
- Unit tests covering all features and edge cases
- Demo CLI application (demo.mojo) showcasing all features
- CI workflow for Ubuntu and macOS