Skip to content

Commit 6e100e8

Browse files
authored
[cli] Update codebase to argmojo v0.5.0 and use declarative API (#192)
1 parent f0fd648 commit 6e100e8

File tree

12 files changed

+180
-128
lines changed

12 files changed

+180
-128
lines changed

.github/workflows/run_tests.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
name: CI
22
on:
3+
push:
4+
branches: [main, dev]
35
pull_request:
46
workflow_dispatch:
57

@@ -195,8 +197,6 @@ jobs:
195197
echo "$HOME/.pixi/bin" >> $GITHUB_PATH
196198
- name: pixi install
197199
run: pixi install
198-
- name: Fetch argmojo
199-
run: pixi run fetch
200200
- name: Build CLI binary
201201
run: pixi run buildcli
202202
- name: Run tests

pixi.lock

Lines changed: 18 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pixi.toml

Lines changed: 24 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ version = "0.9.0"
1010

1111
[dependencies]
1212
# argmojo = ">=0.4.0" # CLI argument parsing for the Decimo calculator (TODO: waiting for argmojo 0.4.0 compatible with mojo 0.26.2)
13+
argmojo = ">=0.5.0,<0.6.0" # CLI argument parsing for the Decimo calculator
1314
mojo = ">=0.26.2.0,<0.26.3" # Mojo language compiler and runtime
1415
python = ">=3.13" # For Python bindings and tests
1516
python-build = ">=0.2.0" # Build PyPI wheel (`pixi run wheel`)
@@ -26,17 +27,17 @@ format = """pixi run mojo format ./src \
2627
&&pixi run ruff format ./python"""
2728

2829
# doc
29-
doc = "pixi run mojo doc --diagnose-missing-doc-strings src/decimo"
30+
doc = "pixi run mojo doc --diagnose-missing-doc-strings src/decimo > /dev/null"
3031

3132
# compile the package
3233
p = "clear && pixi run package"
3334
package = """pixi run format \
34-
&& pixi run doc \
35-
&& pixi run package_decimo"""
35+
&&pixi run doc \
36+
&&pixi run package_decimo"""
3637
package_decimo = """pixi run mojo package src/decimo \
37-
&& cp decimo.mojopkg tests/ \
38-
&& cp decimo.mojopkg benches/ \
39-
&& rm decimo.mojopkg"""
38+
&&cp decimo.mojopkg tests/ \
39+
&&cp decimo.mojopkg benches/ \
40+
&&rm decimo.mojopkg"""
4041

4142
# clean the package files in tests folder
4243
c = "clear && pixi run clean"
@@ -64,26 +65,31 @@ bench = "pixi run package && bash benches/run_bench.sh"
6465

6566
# bench with debug assertions enabled
6667
bdec_debug = """clear && pixi run package && cd benches/bigdecimal \
67-
&& pixi run mojo run -I ../ -D ASSERT=all bench.mojo && cd ../.. \
68-
&& pixi run clean"""
68+
&&pixi run mojo run -I ../ -D ASSERT=all bench.mojo && cd ../.. \
69+
&&pixi run clean"""
6970
bint_debug = """clear && pixi run package && cd benches/bigint \
70-
&& pixi run mojo run -I ../ -D ASSERT=all bench.mojo && cd ../.. \
71-
&& pixi run clean"""
71+
&&pixi run mojo run -I ../ -D ASSERT=all bench.mojo && cd ../.. \
72+
&&pixi run clean"""
7273
buint_debug = """clear && pixi run package && cd benches/biguint \
73-
&& pixi run mojo run -I ../ -D ASSERT=all bench.mojo && cd ../.. \
74-
&& pixi run clean"""
74+
&&pixi run mojo run -I ../ -D ASSERT=all bench.mojo && cd ../.. \
75+
&&pixi run clean"""
7576
dec_debug = """clear && pixi run package && cd benches/decimal128 \
76-
&& pixi run mojo run -I ../ -D ASSERT=all bench.mojo && cd ../.. \
77-
&& pixi run clean"""
77+
&&pixi run mojo run -I ../ -D ASSERT=all bench.mojo && cd ../.. \
78+
&&pixi run clean"""
7879

7980
# Fetch argmojo source code for CLI calculator
80-
fetch = """git clone https://github.com/forfudan/argmojo.git temp/argmojo 2>/dev/null || true \
81-
&& cd temp/argmojo && git checkout 24ca712fa291ec6a82dc9317f6ba5d0484d1fb47 2>/dev/null"""
81+
# Only do this when necessary
82+
# (argmojo is not compatible with the latest mojo version)
83+
# fetch = """git clone https://github.com/forfudan/argmojo.git temp/argmojo 2>/dev/null || true \
84+
# && cd temp/argmojo && git checkout 29b6f54545f850e19d9a9ccfd1185d87f54e92b2 2>/dev/null"""
8285

8386
# cli calculator
8487
bcli = "clear && pixi run buildcli"
85-
buildcli = """pixi run mojo package temp/argmojo/src/argmojo -o temp/argmojo.mojopkg \
86-
&& pixi run mojo build -I src -I src/cli -I temp -o decimo src/cli/main.mojo"""
88+
# Uncomment the following lines if we build the CLI package with
89+
# local clone of argmojo
90+
# buildcli = """pixi run mojo package temp/argmojo/src/argmojo -o temp/argmojo.mojopkg \
91+
# && pixi run mojo build -I src -I src/cli -I temp -o decimo src/cli/main.mojo"""
92+
buildcli = """pixi run mojo build -I src -I src/cli -o decimo src/cli/main.mojo"""
8793
tcli = "clear && pixi run testcli"
8894
testcli = "bash tests/test_cli.sh"
8995

@@ -101,7 +107,6 @@ all = """pixi run format \
101107
&&pixi run package \
102108
&&pixi run doc \
103109
&&pixi run test \
104-
&&pixi run fetch \
105110
&&pixi run buildcli \
106111
&&pixi run testcli \
107112
&&pixi run buildpy \

src/cli/main.mojo

Lines changed: 71 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,71 @@
1111

1212
from std.sys import exit
1313

14-
from argmojo import Arg, Command
14+
from argmojo import Parsable, Option, Flag, Positional, Command
1515
from decimo.rounding_mode import RoundingMode
1616
from calculator.tokenizer import tokenize
1717
from calculator.parser import parse_to_rpn
1818
from calculator.evaluator import evaluate_rpn, final_round
1919
from calculator.display import print_error
2020

2121

22+
struct DecimoArgs(Parsable):
23+
var expr: Positional[
24+
String,
25+
help="Math expression to evaluate (e.g. 'sqrt(abs(1.1*-12-23/17))')",
26+
required=True,
27+
]
28+
var precision: Option[
29+
Int,
30+
long="precision",
31+
short="p",
32+
help="Number of significant digits",
33+
default="50",
34+
]
35+
var scientific: Flag[
36+
long="scientific",
37+
short="s",
38+
help="Output in scientific notation (e.g. 1.23E+10)",
39+
]
40+
var engineering: Flag[
41+
long="engineering",
42+
short="e",
43+
help="Output in engineering notation (exponent multiple of 3)",
44+
]
45+
var pad: Flag[
46+
long="pad",
47+
short="P",
48+
help="Pad trailing zeros to the specified precision",
49+
]
50+
var delimiter: Option[
51+
String,
52+
long="delimiter",
53+
short="d",
54+
help="Digit-group separator inserted every 3 digits (e.g. '_' gives 1_234.567_89)",
55+
default="",
56+
]
57+
var rounding_mode: Option[
58+
String,
59+
long="rounding-mode",
60+
short="r",
61+
help="Rounding mode for the final result",
62+
default="half-even",
63+
choices="half-even,half-up,half-down,up,down,ceiling,floor",
64+
]
65+
66+
@staticmethod
67+
def description() -> String:
68+
return "Arbitrary-precision CLI calculator powered by Decimo."
69+
70+
@staticmethod
71+
def version() -> String:
72+
return "0.1.0"
73+
74+
@staticmethod
75+
def name() -> String:
76+
return "decimo"
77+
78+
2279
def main():
2380
try:
2481
_run()
@@ -31,106 +88,21 @@ def main():
3188

3289

3390
def _run() raises:
34-
var cmd = Command(
35-
"decimo",
36-
(
37-
"Arbitrary-precision CLI calculator powered by Decimo.\n"
38-
"\n"
39-
"Note: if your expression contains *, ( or ), your shell may\n"
40-
"intercept them before decimo runs. Use quotes or noglob:\n"
41-
' decimo "2 * (3 + 4)" # with quotes\n'
42-
" noglob decimo 2*(3+4) # with noglob\n"
43-
" alias decimo='noglob decimo' # add to ~/.zshrc"
44-
),
45-
version="0.1.0",
46-
)
47-
48-
# Positional: the math expression
49-
cmd.add_argument(
50-
Arg(
51-
"expr",
52-
help=(
53-
"Math expression to evaluate (e.g. 'sqrt(abs(1.1*-12-23/17))')"
54-
),
55-
)
56-
.positional()
57-
.required()
58-
)
59-
60-
# Named option: number of significant digits
61-
cmd.add_argument(
62-
Arg("precision", help="Number of significant digits (default: 50)")
63-
.long["precision"]()
64-
.short["p"]()
65-
.default["50"]()
66-
)
67-
68-
# Output formatting flags
69-
# Mutually exclusive: scientific, engineering
70-
cmd.add_argument(
71-
Arg("scientific", help="Output in scientific notation (e.g. 1.23E+10)")
72-
.long["scientific"]()
73-
.short["s"]()
74-
.flag()
75-
)
76-
cmd.add_argument(
77-
Arg(
78-
"engineering",
79-
help="Output in engineering notation (exponent multiple of 3)",
80-
)
81-
.long["engineering"]()
82-
.short["e"]()
83-
.flag()
84-
)
91+
var cmd = DecimoArgs.to_command()
8592
cmd.mutually_exclusive(["scientific", "engineering"])
86-
cmd.add_argument(
87-
Arg(
88-
"pad",
89-
help="Pad trailing zeros to the specified precision",
90-
)
91-
.long["pad"]()
92-
.short["P"]()
93-
.flag()
94-
)
95-
cmd.add_argument(
96-
Arg(
97-
"delimiter",
98-
help=(
99-
"Digit-group separator inserted every 3 digits"
100-
" (e.g. '_' gives 1_234.567_89)"
101-
),
102-
)
103-
.long["delimiter"]()
104-
.short["d"]()
105-
.default[""]()
93+
cmd.add_tip(
94+
'If your expression contains *, ( or ), quote it: decimo "2 * (3 + 4)"'
10695
)
107-
108-
# Rounding mode for the final result
109-
cmd.add_argument(
110-
Arg(
111-
"rounding-mode",
112-
help="Rounding mode for the final result (default: half-even)",
113-
)
114-
.long["rounding-mode"]()
115-
.short["r"]()
116-
.choice["half-even"]()
117-
.choice["half-up"]()
118-
.choice["half-down"]()
119-
.choice["up"]()
120-
.choice["down"]()
121-
.choice["ceiling"]()
122-
.choice["floor"]()
123-
.default["half-even"]()
124-
)
125-
126-
var result = cmd.parse()
127-
var expr = result.get_string("expr")
128-
var precision = result.get_int("precision")
129-
var scientific = result.get_flag("scientific")
130-
var engineering = result.get_flag("engineering")
131-
var pad = result.get_flag("pad")
132-
var delimiter = result.get_string("delimiter")
133-
var rounding_mode = _parse_rounding_mode(result.get_string("rounding-mode"))
96+
cmd.add_tip("Or use noglob: alias decimo='noglob decimo' (add to ~/.zshrc)")
97+
var args = DecimoArgs.parse_from_command(cmd^)
98+
99+
var expr = args.expr.value
100+
var precision = args.precision.value
101+
var scientific = args.scientific.value
102+
var engineering = args.engineering.value
103+
var pad = args.pad.value
104+
var delimiter = args.delimiter.value
105+
var rounding_mode = _parse_rounding_mode(args.rounding_mode.value)
134106

135107
# ── Phase 1: Tokenize & parse ──────────────────────────────────────────
136108
try:

tests/test_bigdecimal.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@
22
set -e
33

44
for f in tests/bigdecimal/*.mojo; do
5-
pixi run mojo run -I src -D ASSERT=all -debug-level=line-tables "$f"
5+
pixi run mojo run -I src -D ASSERT=all --debug-level=line-tables "$f"
66
done

tests/test_bigfloat.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ trap cleanup EXIT
3737
for f in tests/bigfloat/*.mojo; do
3838
echo "=== $f ==="
3939
TMPBIN=$(mktemp /tmp/decimo_test_bigfloat_XXXXXX)
40-
pixi run mojo build -I src -debug-level=line-tables \
40+
pixi run mojo build -I src --debug-level=line-tables \
4141
-Xlinker -L./"$WRAPPER_DIR" -Xlinker -ldecimo_gmp_wrapper \
4242
-o "$TMPBIN" "$f"
4343
DYLD_LIBRARY_PATH="./$WRAPPER_DIR" LD_LIBRARY_PATH="./$WRAPPER_DIR" "$TMPBIN"

tests/test_bigint.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@
22
set -e
33

44
for f in tests/bigint/*.mojo; do
5-
pixi run mojo run -I src -D ASSERT=all -debug-level=line-tables "$f"
5+
pixi run mojo run -I src -D ASSERT=all --debug-level=line-tables "$f"
66
done

tests/test_bigint10.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@
22
set -e
33

44
for f in tests/bigint10/*.mojo; do
5-
pixi run mojo run -I src -D ASSERT=all -debug-level=line-tables "$f"
5+
pixi run mojo run -I src -D ASSERT=all --debug-level=line-tables "$f"
66
done

tests/test_biguint.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@
22
set -e
33

44
for f in tests/biguint/*.mojo; do
5-
pixi run mojo run -I src -D ASSERT=all -debug-level=line-tables "$f"
5+
pixi run mojo run -I src -D ASSERT=all --debug-level=line-tables "$f"
66
done

0 commit comments

Comments
 (0)