Skip to content

Releases: forfudan/argmojo

ArgMojo v0.5.0

04 Apr 16:26
29b6f54

Choose a tag to compare

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

  1. Declarative API coreParsable trait with compile-time reflection over wrapper-typed fields. Conforming structs need only declare fields and provide description(); all parsing, Command-building, and write-back methods are provided as trait defaults (PR #34, #35, #37, #40).
  2. Wrapper typesOption[T, ...], Flag[...], Positional[T, ...], Count[...] parametric structs encode CLI metadata as compile-time parameters. Conform to the internal ArgumentLike trait with add_to_command() / read_from_result() hooks (PR #34).
  3. Auto-initialisationParsable.__init__ uses mark_initialized + comptime for + UnsafePointer.init_pointee_move to default-construct all fields via reflection. Users never need to write __init__ (PR #37).
  4. Hybrid bridgeto_command() reflects a Parsable struct into an owned Command for builder-level customisation; parse_from_command(cmd^) parses back into a typed struct (PR #35, #40).
  5. Dual-return parsingparse_full() returns Tuple[Self, ParseResult] for workflows that need both typed struct fields and raw ParseResult access (e.g. subcommand dispatch). parse_full_from_command(cmd^) does the same from a pre-configured Command (PR #40, #42).
  6. Subcommand supportsubcommands() hook on Parsable returns List[Command]; called automatically by to_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).
  7. Asterisk-masked password input.password[True]() on Argument echoes * 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

  1. Remove Arg alias for Argument and drop ArgumentLike from the public export list. The public API now exports: Argument, Command, ParseResult, Parsable, Option, Flag, Positional, Count (PR #42).
  2. subcommands() hook signature changed from subcommands(mut cmd: Command) raises to subcommands() raises -> List[Command] — returns a list of Commands instead of mutating one (PR #43).
  3. Reorganise Argument and Command source 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.mojo for 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/Argument internals for clearer grouping by @forfudan in #33
  • [core][declarative] Implement argument wrappers and Parsable trait by @forfudan in #34
  • [core][declarative] Implement Parsable reflection, trait methods, and example by @forfudan in #35
  • [core][declarative] Use rebind instead of UnsafePointer in argument wrapper write-back logic by @forfudan in #36
  • [core][declarative] Default-initialize all fields via reflection in __init__ of Parsable trait 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_command so that it returns a list of Command by @forfudan in #43
  • [declarative][doc] Standardize Parsable parsing method names + Update documents for release by @forfudan in #44

Full Changelog: v0.4.0...v0.5.0

ArgMojo v0.4.0

21 Mar 18:45
2dbb897

Choose a tag to compare

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

  1. Add .default_if_no_value["value"]() — option appears without a value to use the fallback; with =value to override. For long options, implies .require_equals() (PR #12).
  2. Add .require_equals() — long options reject space-separated values and require --key=value syntax. Help output adapts: --key=<value> for require-equals, --key[=<value>] for default-if-no-value (PR #12).
  3. Add response_file_prefix() on Command for @args.txt expansion with comments, escaping, and recursive nesting. (Temporarily disabled due to a Mojo compiler deadlock under -D ASSERT=all.) (PR #12).
  4. Add .remainder() on Argument — consume all remaining tokens (including dash-prefixed) as a single positional, similar to argparse nargs=REMAINDER (PR #13).
  5. Add parse_known_arguments() on Command — unrecognised options are collected via result.get_unknown_args() instead of raising an error (PR #13).
  6. Add .allow_hyphen_values() on Argument — accept tokens starting with - as values without requiring -- first; covers the stdin - convention (PR #13).
  7. CJK-aware help alignment using terminal display width; CJK characters treated as 2-column-wide. No API changes — automatic (PR #14).
  8. Full-width → half-width auto-correction with a coloured warning when CJK users type fullwidth ASCII (e.g., --verbose--verbose). Disabled via disable_fullwidth_correction() (PR #15).
  9. CJK punctuation auto-correction — em-dash ——verbose corrected to --verbose. Disabled via disable_punctuation_correction() (PR #16).
  10. Add .group["name"]() on Argument — group arguments under dedicated headings in --help output (PR #17).
  11. Value-name wrapping control: .value_name["NAME"]() renders as <NAME> by default; .value_name["NAME", False]() renders bare (PR #17).
  12. Add runtime generate_completion("shell") overload alongside the existing compile-time generate_completion["shell"]() (PR #19).
  13. Registration-time validation for mutually_exclusive(), required_together(), one_required(), and required_if() — catches typos, empty lists, and self-referential rules immediately at add_argument() time (PR #22).
  14. Add .prompt() / .prompt["text"]() on Argument — interactively prompt for missing values before validation. Shows choices and defaults; handles non-interactive stdin gracefully (PR #23).
  15. Add add_parent(parent) on Command — share argument definitions and group constraints across commands, equivalent to argparse parents (PR #25).
  16. Add confirmation_option() on Command — register --yes/-y and prompt for confirmation after parsing; --yes skips the prompt (PR #26).
  17. Add usage(text) on Command — replace the auto-generated usage line with a custom string (PR #27).
  18. Add .password() on Argument — hide typed input via POSIX tcsetattr(3) during prompts, equivalent to Click hide_input=True (PR #28).

🔄 Mojo v0.26.2 migration (PR #29)

  • Bump Mojo dependency to ==0.26.2 in pixi.toml.
  • Migrate stdlib imports to std.* namespace (from sysfrom std.sys, etc.).
  • Replace constrained[] with comptime assert and @parameter if with comptime if.
  • Unify __copyinit__/__moveinit__ to new __init__(out self, *, copy/take: Self) forms.
  • Remove Stringable from trait lists (removed from stdlib).
  • Add byte= keyword to all string slicing operations.
  • Replace fn with def across all 30 files (754 declarations).
  • Remove __str__ methods; consolidate string output into write_to (Mojo v0.26.2 convention).

🦋 Changed in v0.4.0

  1. Rename .metavar() to .value_name() across the entire API (PR #13).
  2. Parameterise .long[]() and .short[]() as compile-time StringLiteral parameters (PR #20).
  3. 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).
  4. Replace .choices(list) with chained .choice["a"]().choice["b"]() compile-time parameters (PR #18).
  5. Value-name display uses angle brackets by default; .value_name["FOO", False]() for bare display (PR #17).
  6. Move print_summary() from Command to ParseResult (PR #24).

🔧 Fixes in v0.4.0

  • Clarify that default_if_no_value does 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]() at add_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 debug task for -D ASSERT=all regression testing (PR #22).

What's Changed

  • [core] Add default_if_no_value and require_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 metavar to value_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 StringLiteral type by @forfudan in #18
  • [core] Provide generate_completion overload 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 Argument type to compile-time parameters by @forfudan in #21
  • [core] Implement aggressive runtime validation for Command by @forfudan in #22
  • [core] Enable interactive prompting for arguments by @forfudan in #23
  • [core] Move print_summary from Command to ParseResult by @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

05 Mar 11:45

Choose a tag to compare

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

  1. 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).
  2. 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).
  3. Add Levenshtein-distance based "did you mean ...?" suggestions for misspelled long options and subcommand names (PR #3).
  4. Implement command_aliases() on Command to register alternative names for subcommands. Aliases are shown in help, accepted during dispatch, and included in shell completions and typo suggestions (PR #5).
  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).
  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).
  7. Parameterise .max[ceiling](), .range[min, max](), and .number_of_values[N]() as compile-time parameters, enabling build-time validation of invalid values (PR #8).
  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).
  9. Honour the NO_COLOR environment 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).
  10. 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

  1. parse_args() renamed to parse_arguments() (PR #5).
  2. help_on_no_args() renamed to help_on_no_arguments() (PR #5).
  3. .nargs() renamed to .number_of_values() and nargs_count field renamed to _number_of_values (PR #5).
  4. Several Argument and ParseResult attributes are now underscore-prefixed (private). Public builder methods are unchanged (PR #7).
  5. Decompose parse_args() into four sub-methods: _parse_long_option(), _parse_short_single(), _parse_short_merged(), _dispatch_subcommand() (PR #2).
  6. Decompose _generate_help() into five sub-methods: _help_usage_line(), _help_positionals_section(), _help_options_section(), _help_commands_section(), _help_tips_section() (PR #2).
  7. Extract ANSI colour constants and utility functions into a new internal module utils.mojo (PR #2).
  8. Rename example files to avoid confusion: git.mojo -> mgit.mojo, grep.mojo -> mgrep.mojo.
  9. 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.mojo covering Levenshtein-based suggestions (PR #3).
  • Add tests/test_completion.mojo with comprehensive tests for Bash, Zsh, and Fish script generation (PR #4).
  • Add tests/test_implies.mojo covering 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

28 Feb 09:11

Choose a tag to compare

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: ArgArgument (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:

  1. Implement full subcommand support with add_subcommand() API, hierarchical dispatch, and nested subcommands (e.g., git remote add).
  2. Auto-register a help subcommand so that app help <command> works out of the box; opt out with disable_help_subcommand().
  3. Add allow_positional_with_subcommands() guard — prevents accidental mixing of positional args and subcommands on the same Command, following the cobra/clap convention. Requires explicit opt-in.
  4. Add subcommand and subcommand_result fields on ParseResult with has_subcommand_result() / get_subcommand_result() accessors.

Persistent flags:

  1. Add .persistent() builder method on Argument to mark a flag as global.
  2. 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.
  3. Detect conflicting long/short names between parent persistent args and child local args at registration time (add_subcommand() raises an error).

Negative number passthrough:

  1. Recognize negative numeric tokens like -3.14 or -42 as positional values instead of unknown short options.
  2. Add allow_negative_numbers() opt-in on Command for explicit control.

Custom tips:

  1. Add add_tip() API on Command to attach user-defined tips that render as a dedicated section at the bottom of help output.

Error handling:

  1. Colored error and warning messages — ANSI-styled stderr output for all parse errors.
  2. Unknown subcommand error now lists all available commands.
  3. Errors inside child parse are prefixed with the full command path (e.g., git remote add: ...).

🦋 Changed in v0.2.0

API rename:

  1. Rename Arg struct to Argument. The old name is kept as alias for convenience.
  2. Rename source files: arg.mojoargument.mojo, result.mojoparse_result.mojo.

Help & UX improvements:

  1. Add a "Commands" section to help output listing available subcommands with aligned descriptions.
  2. Show <COMMAND> placeholder in the usage line for commands that have subcommands.
  3. Display persistent flags under a "Global Options" heading in child help.
  4. Show the full command path in child help and error messages (e.g., Usage: git remote add [OPTIONS] NAME URL).

Internal refactoring:

  1. Extract _apply_defaults() and _validate() into private helper methods on Command, 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) and examples/git.mojo (subcommand-based, with nested subcommands and persistent flags).
  • Add tests/test_subcommands.mojo covering 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

24 Feb 19:57

Choose a tag to compare

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 / -h with formatted usage and descriptions
  • Version display: --version / -V
  • -- stop marker: everything after -- is treated as positional
  • Short flag merging: -abc expands to -a -b -c
  • Attached short values: -ofile.txt is 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 --help output
  • Count flags: -vvvget_count("verbose") == 3
  • Negatable flags: --color / --no-color paired flags with .negatable()
  • Mutually exclusive groups: prevent conflicting flags (e.g., --json vs --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

Contributors

@forfudan