Skip to content

Commit f6d1fef

Browse files
authored
Add ArgMojo v0.1.0 - A command-line argument parser library for Mojo (#218)
* Add argmojo * Update image name
1 parent 1e28dae commit f6d1fef

File tree

3 files changed

+319
-0
lines changed

3 files changed

+319
-0
lines changed

recipes/argmojo/README.md

Lines changed: 282 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,282 @@
1+
# ArgMojo
2+
3+
![icon](image.jpeg)
4+
5+
A command-line argument parser library for [Mojo](https://www.modular.com/mojo).
6+
7+
> **A**rguments
8+
> **R**esolved and
9+
> **G**rouped into
10+
> **M**eaningful
11+
> **O**ptions and
12+
> **J**oined
13+
> **O**bjects
14+
15+
## Overview
16+
17+
ArgMojo provides a builder-pattern API for defining and parsing command-line arguments in Mojo. It currently supports:
18+
19+
- **Long options**: `--verbose`, `--output file.txt`, `--output=file.txt`
20+
- **Short options**: `-v`, `-o file.txt`
21+
- **Boolean flags**: options that take no value
22+
- **Positional arguments**: matched by position
23+
- **Default values**: fallback when an argument is not provided
24+
- **Required arguments**: validation that mandatory args are present
25+
- **Auto-generated help**: `--help` / `-h` (no need to implement manually)
26+
- **Version display**: `--version` / `-V` (also auto-generated)
27+
- **`--` stop marker**: everything after `--` is treated as positional
28+
- **Short flag merging**: `-abc` expands to `-a -b -c`
29+
- **Attached short values**: `-ofile.txt` means `-o file.txt`
30+
- **Choices validation**: restrict values to a set (e.g., `json`, `csv`, `table`)
31+
- **Metavar**: custom display name for values in help text
32+
- **Hidden arguments**: exclude internal args from `--help` output
33+
- **Count flags**: `-vvv``get_count("verbose") == 3`
34+
- **Positional arg count validation**: reject extra positional args
35+
- **Negatable flags**: `--color` / `--no-color` paired flags with `.negatable()`
36+
- **Mutually exclusive groups**: prevent conflicting flags (e.g., `--json` vs `--yaml`)
37+
- **Required-together groups**: enforce that related flags are provided together (e.g., `--username` + `--password`)
38+
- **Long option prefix matching**: allow abbreviated options (e.g., `--verb``--verbose`). If the prefix is ambiguous (e.g., `--ver` could match both `--verbose` and `--version`), an error is raised.
39+
40+
---
41+
42+
I created this project to support my experiments with a CLI-based Chinese character search engine in Mojo, as well as a CLI-based calculator for [DeciMojo](https://github.com/forfudan/decimojo). It is inspired by Python's `argparse`, Rust's `clap`, Go's `cobra`, and other popular argument parsing libraries, but designed to fit Mojo's unique features and constraints.
43+
44+
My goal is to provide a Mojo-idiomatic argument parsing library that can be easily adopted by the growing Mojo community for their CLI applications. **Before Mojo v1.0** (which means it gets stable), my focus is on building core features and ensuring correctness. "Core features" refer to those who appear in `argparse`/`clap`/`cobra` and are commonly used in CLI apps. "Correctness" means that the library should handle edge cases properly, provide clear error messages, and have good test coverage. Some fancy features will depend on my time and interest.
45+
46+
## Installation
47+
48+
ArgMojo requires Mojo == 0.26.1 and uses [pixi](https://pixi.sh) for environment management.
49+
50+
```bash
51+
git clone https://github.com/forfudan/argmojo.git
52+
cd argmojo
53+
pixi install
54+
```
55+
56+
I make the Mojo version strictly 0.26.1 because that's the version I developed and tested on, and Mojo is rapidly evolving. Based on my experience, the library will not work every time there's a new Mojo release.
57+
58+
## Quick Start
59+
60+
Here is a simple example of how to use ArgMojo in a Mojo program. The full example can be found in `examples/demo.mojo`.
61+
62+
```mojo
63+
from argmojo import Arg, Command
64+
65+
66+
fn main() raises:
67+
var cmd = Command("demo", "A CJK-aware text search tool that supports Pinyin and Yuhao Input Methods (宇浩系列輸入法).", version="0.1.0")
68+
69+
# Positional arguments
70+
cmd.add_arg(Arg("pattern", help="Search pattern").positional().required())
71+
cmd.add_arg(Arg("path", help="Search path").positional().default("."))
72+
73+
# Boolean flags
74+
cmd.add_arg(
75+
Arg("ling", help="Use Lingming IME for encoding")
76+
.long("ling").short("l").flag()
77+
)
78+
79+
# Count flag (verbosity)
80+
cmd.add_arg(
81+
Arg("verbose", help="Increase verbosity (-v, -vv, -vvv)")
82+
.long("verbose").short("v").count()
83+
)
84+
85+
# Key-value option with choices and metavar
86+
var formats: List[String] = ["json", "csv", "table"]
87+
cmd.add_arg(
88+
Arg("format", help="Output format")
89+
.long("format").short("f").choices(formats^).default("table")
90+
)
91+
92+
# Negatable flag — --color enables, --no-color disables
93+
cmd.add_arg(
94+
Arg("color", help="Enable colored output")
95+
.long("color").flag().negatable()
96+
)
97+
98+
# Parse and use
99+
var result = cmd.parse()
100+
print("pattern:", result.get_string("pattern"))
101+
print("verbose:", result.get_count("verbose"))
102+
print("format: ", result.get_string("format"))
103+
print("color: ", result.get_flag("color"))
104+
```
105+
106+
## Usage Examples
107+
108+
For detailed explanations and more examples of every feature, see the **[User Manual](docs/user_manual.md)**.
109+
110+
Build the demo binary first, then try the examples below:
111+
112+
```bash
113+
pixi run build_demo
114+
```
115+
116+
### Basic usage — positional args and flags
117+
118+
```bash
119+
./demo "nihao" ./src --ling
120+
```
121+
122+
### Short options and default values
123+
124+
The second positional arg (`path`) defaults to `"."` when omitted:
125+
126+
```bash
127+
./demo "zhongguo" -l
128+
```
129+
130+
### Help and version
131+
132+
```bash
133+
./demo --help
134+
./demo --version
135+
```
136+
137+
### Merged short flags
138+
139+
Multiple short flags can be combined in a single `-` token. For example, `-liv` is equivalent to `-l -i -v`:
140+
141+
```bash
142+
./demo "pattern" ./src -liv
143+
```
144+
145+
### Attached short values
146+
147+
A short option can receive its value without a space:
148+
149+
```bash
150+
./demo "pattern" -d3 # same as -d 3
151+
./demo "pattern" -ftable # same as -f table
152+
```
153+
154+
### Count flags — verbosity
155+
156+
Use `-v` multiple times (merged or repeated) to increase verbosity:
157+
158+
```bash
159+
./demo "pattern" -v # verbose = 1
160+
./demo "pattern" -vvv # verbose = 3
161+
./demo "pattern" -v --verbose # verbose = 2 (short + long)
162+
```
163+
164+
### Choices validation
165+
166+
The `--format` option only accepts `json`, `csv`, or `table`:
167+
168+
```bash
169+
./demo "pattern" --format json # OK
170+
./demo "pattern" --format xml # Error: Invalid value 'xml' for 'format'. Valid choices: json, csv, table
171+
```
172+
173+
### Negatable flags
174+
175+
A negatable flag pairs `--X` (sets `True`) with `--no-X` (sets `False`) automatically:
176+
177+
```bash
178+
./demo "pattern" --color # color = True
179+
./demo "pattern" --no-color # color = False
180+
./demo "pattern" # color = False (default)
181+
```
182+
183+
### Mutually exclusive groups
184+
185+
`--json` and `--yaml` are mutually exclusive — using both is an error:
186+
187+
```bash
188+
./demo "pattern" --json # OK
189+
./demo "pattern" --yaml # OK
190+
./demo "pattern" --json --yaml # Error: Arguments are mutually exclusive: '--json', '--yaml'
191+
```
192+
193+
### `--` stop marker
194+
195+
Everything after `--` is treated as a positional argument, even if it starts with `-`:
196+
197+
```bash
198+
./demo --ling -- "--pattern-with-dashes" ./src
199+
```
200+
201+
### Hidden arguments
202+
203+
Some arguments are excluded from `--help` but still work at the command line (useful for debug flags):
204+
205+
```bash
206+
./demo "pattern" --debug-index # Works, but not shown in --help
207+
```
208+
209+
### Required-together groups
210+
211+
`--username` and `--password` must be provided together — using one without the other is an error:
212+
213+
```bash
214+
./demo "pattern" --username admin --password secret # OK
215+
./demo "pattern" # OK (neither is provided)
216+
./demo "pattern" --username admin # Error: '--password' required when '--username' is provided
217+
```
218+
219+
### A mock example showing how features work together
220+
221+
```bash
222+
./demo yes ./src --verbo --color -li -d 3 --no-color --usern zhu --pas 12345
223+
```
224+
225+
This will be parsed as:
226+
227+
```bash
228+
=== Parsed Arguments ===
229+
pattern: yes
230+
path: ./src
231+
-l, --ling True
232+
-i, --ignore-case True
233+
-v, --verbose 1
234+
-d, --max-depth 3
235+
-f, --format table
236+
--color False
237+
--json False
238+
--yaml False
239+
-u, --username zhu
240+
-p, --password 12345
241+
```
242+
243+
## Development
244+
245+
```bash
246+
# Format code
247+
pixi run format
248+
249+
# Build package
250+
pixi run package
251+
252+
# Run tests
253+
pixi run test
254+
255+
# Clean build artifacts
256+
pixi run clean
257+
```
258+
259+
## Project Structure
260+
261+
```txt
262+
argmojo/
263+
├── docs/ # Documentation
264+
│ ├── user_manual.md # User manual with detailed examples
265+
│ └── argmojo_overall_planning.md
266+
├── src/
267+
│ └── argmojo/ # Main package
268+
│ ├── __init__.mojo # Package exports
269+
│ ├── arg.mojo # Arg struct (argument definition)
270+
│ ├── command.mojo # Command struct (parsing logic)
271+
│ └── result.mojo # ParseResult struct (parsed values)
272+
├── tests/
273+
│ └── test_argmojo.mojo # Tests
274+
├── pixi.toml # pixi configuration
275+
├── .gitignore
276+
├── LICENSE
277+
└── README.md
278+
```
279+
280+
## License
281+
282+
This project is licensed under the Apache License 2.0. See [LICENSE](LICENSE) for details.

recipes/argmojo/image.jpeg

36.9 KB
Loading

recipes/argmojo/recipe.yaml

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
context:
2+
version: "0.1.0"
3+
mojo_version: "=0.26.1"
4+
5+
package:
6+
name: "argmojo"
7+
version: ${{ version }}
8+
9+
source:
10+
- git: https://github.com/forfudan/argmojo.git
11+
rev: 6db272c433171f1bf5e158d24628581f248aefcc
12+
13+
build:
14+
number: 0
15+
script:
16+
- mkdir -p ${PREFIX}/lib/mojo
17+
- mojo package src/argmojo -o ${{ PREFIX }}/lib/mojo/argmojo.mojopkg
18+
19+
requirements:
20+
host:
21+
- mojo-compiler ${{ mojo_version }}
22+
build:
23+
- mojo-compiler ${{ mojo_version }}
24+
run:
25+
- mojo-compiler ${{ mojo_version }}
26+
27+
about:
28+
homepage: https://github.com/forfudan/argmojo
29+
license: Apache-2.0
30+
license_file: LICENSE
31+
summary: A command-line argument parser library for Mojo.
32+
repository: https://github.com/forfudan/argmojo.git
33+
34+
extra:
35+
project_name: argmojo
36+
maintainers:
37+
- forfudan

0 commit comments

Comments
 (0)