Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion examples/demo.mojo
Original file line number Diff line number Diff line change
Expand Up @@ -385,4 +385,4 @@ fn main() raises:

# ── Parse & display ──────────────────────────────────────────────────
var result = app.parse()
app.print_summary(result)
result.print_summary()
2 changes: 1 addition & 1 deletion examples/mgit.mojo
Original file line number Diff line number Diff line change
Expand Up @@ -485,4 +485,4 @@ fn main() raises:

# ── Parse & display ──────────────────────────────────────────────────
var result = app.parse()
app.print_summary(result)
result.print_summary()
2 changes: 1 addition & 1 deletion examples/mgrep.mojo
Original file line number Diff line number Diff line change
Expand Up @@ -250,4 +250,4 @@ fn main() raises:

# ── Parse & display ──────────────────────────────────────────────────
var result = app.parse()
app.print_summary(result)
result.print_summary()
103 changes: 0 additions & 103 deletions src/argmojo/command.mojo
Original file line number Diff line number Diff line change
Expand Up @@ -3892,109 +3892,6 @@ struct Command(Copyable, Movable, Stringable, Writable):
s += " " + tip_lines[_ti] + "\n"
return s

fn print_summary(self, result: ParseResult):
"""Prints a human-readable summary of all parsed arguments.

Iterates over registered argument definitions and prints each
argument's display name (``--long`` / ``-s``) alongside its
parsed value. Hidden arguments are included only when they
were actually provided.

Args:
result: The ParseResult returned by ``parse()`` or
``parse_arguments()``.
"""
print("=== Parsed Arguments ===")

# Positional arguments.
for i in range(len(self.args)):
if self.args[i]._is_positional:
var val = String("(not set)")
try:
val = result.get_string(self.args[i].name)
except:
pass
print(" " + self.args[i].name + ": " + val)

# Named arguments — two-pass for dynamic column alignment.
# First pass: collect display names and value strings.
var displays = List[String]()
var value_strs = List[String]()
for i in range(len(self.args)):
if self.args[i]._is_positional:
continue
# Skip hidden args that weren't provided.
if self.args[i]._is_hidden and not result.has(self.args[i].name):
continue

var display = String("")
if self.args[i]._short_name:
display += "-" + self.args[i]._short_name
if self.args[i]._long_name:
if display:
display += ", "
display += "--" + self.args[i]._long_name
displays.append(display)

var val_str: String
if self.args[i]._is_count:
val_str = String(result.get_count(self.args[i].name))
elif self.args[i]._is_flag:
val_str = String(result.get_flag(self.args[i].name))
elif self.args[i]._is_map:
if self.args[i].name in result._maps:
var m = result.get_map(self.args[i].name)
var s = String("{")
var first = True
for entry in m.items():
if not first:
s += ", "
s += entry.key + "=" + entry.value
first = False
s += "}"
val_str = s
else:
val_str = "{}"
elif self.args[i]._is_append:
var lst = result.get_list(self.args[i].name)
if len(lst) > 0:
var s = String("[")
for j in range(len(lst)):
if j > 0:
s += ", "
s += lst[j]
s += "]"
val_str = s
else:
val_str = "[]"
else:
if result.has(self.args[i].name):
var s = String("")
try:
s = result.get_string(self.args[i].name)
except:
pass
val_str = s
else:
val_str = "(not set)"
value_strs.append(val_str)

# Compute padding width from the longest display name.
var max_len: Int = 0
for k in range(len(displays)):
if len(displays[k]) > max_len:
max_len = len(displays[k])
var pad_width = max_len + 2

# Second pass: print with aligned columns.
for k in range(len(displays)):
var line = " " + displays[k]
var padding = pad_width - len(displays[k])
for _p in range(padding):
line += " "
line += value_strs[k]
print(line)

# ===------------------------------------------------------------------=== #
# Shell completion generation
# ===------------------------------------------------------------------=== #
Expand Down
123 changes: 123 additions & 0 deletions src/argmojo/parse_result.mojo
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,129 @@ struct ParseResult(Copyable, Movable, Stringable, Writable):
"""
return self._unknown_args.copy()

fn print_summary(self, indent: Int = 0):
"""Prints a human-readable summary of all parsed arguments.

Displays positionals, flags, values, counts, lists, and maps
stored in this result. If a subcommand result is present, it
is printed recursively with increased indentation.

Args:
indent: Number of leading spaces for nested output.
"""
self._print_summary_impl(indent, String(""))

fn _print_summary_impl(self, indent: Int, name: String):
"""Internal implementation that accepts a subcommand name.

Args:
indent: Number of leading spaces for nested output.
name: Subcommand name passed from parent (empty at top level).
"""
var prefix = String("")
for _ in range(indent):
prefix += " "

if indent == 0:
print(prefix + "=== Parsed Arguments ===")
else:
print(
prefix
+ "=== Subcommand: "
+ name
+ " ==="
)

# Positional arguments.
for i in range(len(self._positionals)):
var name: String
if i < len(self._positional_names):
name = self._positional_names[i]
else:
name = "positional[" + String(i) + "]"
print(prefix + " " + name + ": " + self._positionals[i])

# Collect named entries for aligned printing.
var names = List[String]()
var vals = List[String]()

# Flags.
for entry in self._flags.items():
names.append(entry.key)
vals.append(String(entry.value))

# Counts.
for entry in self._counts.items():
names.append(entry.key)
vals.append(String(entry.value))

# String values.
for entry in self._values.items():
names.append(entry.key)
vals.append(entry.value)

# Lists.
for entry in self._lists.items():
# Skip list entries that also appear in _maps (maps store
# raw key=value strings in _lists for has() detection).
if entry.key in self._maps:
continue
names.append(entry.key)
var s = String("[")
for j in range(len(entry.value)):
if j > 0:
s += ", "
s += entry.value[j]
s += "]"
vals.append(s)

# Maps.
for entry in self._maps.items():
names.append(entry.key)
var s = String("{")
var first = True
for kv in entry.value.items():
if not first:
s += ", "
s += kv.key + "=" + kv.value
first = False
s += "}"
vals.append(s)

# Compute padding width.
var max_len: Int = 0
for k in range(len(names)):
if len(names[k]) > max_len:
max_len = len(names[k])
var pad_width = max_len + 2

# Print with aligned columns.
for k in range(len(names)):
var line = prefix + " " + names[k]
var padding = pad_width - len(names[k])
for _p in range(padding):
line += " "
line += vals[k]
print(line)

# Unknown args.
if len(self._unknown_args) > 0:
var s = prefix + " (unknown): ["
for j in range(len(self._unknown_args)):
if j > 0:
s += ", "
s += self._unknown_args[j]
s += "]"
print(s)

# Recurse into subcommand result.
if self.has_subcommand_result():
try:
var sub = self.get_subcommand_result()
sub._print_summary_impl(indent + 2, self.subcommand)
except:
pass

fn __str__(self) -> String:
"""Return a string representation of the parse result."""
var s = String("ParseResult(")
Expand Down
Loading