@@ -258,14 +258,11 @@ def get_items(self) -> list[CompletionItems]:
258258import argparse
259259import re
260260import sys
261- from argparse import (
262- ONE_OR_MORE ,
263- ZERO_OR_MORE ,
264- ArgumentError ,
265- )
261+ from argparse import ArgumentError
266262from collections .abc import (
267263 Callable ,
268264 Iterable ,
265+ Iterator ,
269266 Sequence ,
270267)
271268from gettext import gettext
@@ -1296,29 +1293,68 @@ def format_tuple(tuple_size: int) -> tuple[str, ...]:
12961293
12971294 return format_tuple
12981295
1296+ def _build_nargs_range_str (self , nargs_range : tuple [int , int | float ]) -> str :
1297+ """Generate nargs range string for help text."""
1298+ if nargs_range [1 ] == constants .INFINITY :
1299+ # {min+}
1300+ range_str = f"{{{ nargs_range [0 ]} +}}"
1301+ else :
1302+ # {min..max}
1303+ range_str = f"{{{ nargs_range [0 ]} ..{ nargs_range [1 ]} }}"
1304+
1305+ return range_str
1306+
12991307 def _format_args (self , action : argparse .Action , default_metavar : str ) -> str :
1300- """Handle ranged nargs and make other output less verbose."""
1308+ """Override to handle cmd2's custom nargs formatting.
1309+
1310+ All formats in this function need to be handled by _rich_metavar_parts().
1311+ """
13011312 metavar = self ._determine_metavar (action , default_metavar )
13021313 metavar_formatter = self ._metavar_formatter (action , default_metavar )
13031314
13041315 # Handle nargs specified as a range
13051316 nargs_range = action .get_nargs_range () # type: ignore[attr-defined]
13061317 if nargs_range is not None :
1307- range_str = f'{ nargs_range [0 ]} +' if nargs_range [1 ] == constants .INFINITY else f'{ nargs_range [0 ]} ..{ nargs_range [1 ]} '
1308-
1309- return '{}{{{}}}' .format ('%s' % metavar_formatter (1 ), range_str ) # noqa: UP031
1310-
1311- # Make this output less verbose. Do not customize the output when metavar is a
1312- # tuple of strings. Allow argparse's formatter to handle that instead.
1313- if isinstance (metavar , str ):
1314- if action .nargs == ZERO_OR_MORE :
1315- return '[%s [...]]' % metavar_formatter (1 ) # noqa: UP031
1316- if action .nargs == ONE_OR_MORE :
1317- return '%s [...]' % metavar_formatter (1 ) # noqa: UP031
1318- if isinstance (action .nargs , int ) and action .nargs > 1 :
1319- return '{}{{{}}}' .format ('%s' % metavar_formatter (1 ), action .nargs ) # noqa: UP031
1318+ arg_str = '%s' % metavar_formatter (1 ) # noqa: UP031
1319+ range_str = self ._build_nargs_range_str (nargs_range )
1320+ return f"{ arg_str } { range_str } "
1321+
1322+ # When nargs is just a number, argparse repeats the arg in the help text.
1323+ # For instance, when nargs=5 the help text looks like: 'command arg arg arg arg arg'.
1324+ # To make this less verbose, format it like: 'command arg{5}'.
1325+ # Do not customize the output when metavar is a tuple of strings. Allow argparse's
1326+ # formatter to handle that instead.
1327+ if isinstance (metavar , str ) and isinstance (action .nargs , int ) and action .nargs > 1 :
1328+ arg_str = '%s' % metavar_formatter (1 ) # noqa: UP031
1329+ return f"{ arg_str } {{{ action .nargs } }}"
1330+
1331+ # Fallback to parent for all other cases
1332+ return super ()._format_args (action , default_metavar )
1333+
1334+ def _rich_metavar_parts (
1335+ self ,
1336+ action : argparse .Action ,
1337+ default_metavar : str ,
1338+ ) -> Iterator [tuple [str , bool ]]:
1339+ """Override to handle all cmd2-specific formatting in _format_args()."""
1340+ metavar = self ._determine_metavar (action , default_metavar )
1341+ metavar_formatter = self ._metavar_formatter (action , default_metavar )
13201342
1321- return super ()._format_args (action , default_metavar ) # type: ignore[arg-type]
1343+ # Handle nargs specified as a range
1344+ nargs_range = action .get_nargs_range () # type: ignore[attr-defined]
1345+ if nargs_range is not None :
1346+ yield "%s" % metavar_formatter (1 ), True # noqa: UP031
1347+ yield self ._build_nargs_range_str (nargs_range ), False
1348+ return
1349+
1350+ # Handle specific integer nargs (e.g., nargs=5 -> arg{5})
1351+ if isinstance (metavar , str ) and isinstance (action .nargs , int ) and action .nargs > 1 :
1352+ yield "%s" % metavar_formatter (1 ), True # noqa: UP031
1353+ yield f"{{{ action .nargs } }}" , False
1354+ return
1355+
1356+ # Fallback to parent for all other cases
1357+ yield from super ()._rich_metavar_parts (action , default_metavar )
13221358
13231359
13241360class RawDescriptionCmd2HelpFormatter (
0 commit comments