@@ -261,11 +261,9 @@ def get_items(self) -> list[CompletionItems]:
261261from argparse import ArgumentError
262262from collections .abc import (
263263 Callable ,
264- Iterable ,
265264 Iterator ,
266265 Sequence ,
267266)
268- from gettext import gettext
269267from typing import (
270268 TYPE_CHECKING ,
271269 Any ,
@@ -1131,173 +1129,6 @@ def __init__(
11311129
11321130 super ().__init__ (prog , indent_increment , max_help_position , width , console = console , ** kwargs )
11331131
1134- def _format_usage (
1135- self ,
1136- usage : str | None ,
1137- actions : Iterable [argparse .Action ],
1138- groups : Iterable [argparse ._ArgumentGroup ],
1139- prefix : str | None = None ,
1140- ) -> str :
1141- if prefix is None :
1142- prefix = gettext ('Usage: ' )
1143-
1144- # if usage is specified, use that
1145- if usage is not None :
1146- usage %= {"prog" : self ._prog }
1147-
1148- # if no optionals or positionals are available, usage is just prog
1149- elif not actions :
1150- usage = f'{ self ._prog } '
1151-
1152- # if optionals and positionals are available, calculate usage
1153- else :
1154- prog = f'{ self ._prog } '
1155-
1156- # split optionals from positionals
1157- optionals = []
1158- positionals = []
1159- # Begin cmd2 customization (separates required and optional, applies to all changes in this function)
1160- required_options = []
1161- for action in actions :
1162- if action .option_strings :
1163- if action .required :
1164- required_options .append (action )
1165- else :
1166- optionals .append (action )
1167- else :
1168- positionals .append (action )
1169- # End cmd2 customization
1170-
1171- # build full usage string
1172- format_actions = self ._format_actions_usage
1173- action_usage = format_actions (required_options + optionals + positionals , groups ) # type: ignore[arg-type]
1174- usage = ' ' .join ([s for s in [prog , action_usage ] if s ])
1175-
1176- # wrap the usage parts if it's too long
1177- text_width = self ._width - self ._current_indent
1178- if len (prefix ) + len (usage ) > text_width :
1179- # Begin cmd2 customization
1180-
1181- # break usage into wrappable parts
1182- part_regexp = r'\(.*?\)+|\[.*?\]+|\S+'
1183- req_usage = format_actions (required_options , groups ) # type: ignore[arg-type]
1184- opt_usage = format_actions (optionals , groups ) # type: ignore[arg-type]
1185- pos_usage = format_actions (positionals , groups ) # type: ignore[arg-type]
1186- req_parts = re .findall (part_regexp , req_usage )
1187- opt_parts = re .findall (part_regexp , opt_usage )
1188- pos_parts = re .findall (part_regexp , pos_usage )
1189-
1190- # End cmd2 customization
1191-
1192- # helper for wrapping lines
1193- def get_lines (parts : list [str ], indent : str , prefix : str | None = None ) -> list [str ]:
1194- lines : list [str ] = []
1195- line : list [str ] = []
1196- line_len = len (prefix ) - 1 if prefix is not None else len (indent ) - 1
1197- for part in parts :
1198- if line_len + 1 + len (part ) > text_width and line :
1199- lines .append (indent + ' ' .join (line ))
1200- line = []
1201- line_len = len (indent ) - 1
1202- line .append (part )
1203- line_len += len (part ) + 1
1204- if line :
1205- lines .append (indent + ' ' .join (line ))
1206- if prefix is not None :
1207- lines [0 ] = lines [0 ][len (indent ) :]
1208- return lines
1209-
1210- # if prog is short, follow it with optionals or positionals
1211- if len (prefix ) + len (prog ) <= 0.75 * text_width :
1212- indent = ' ' * (len (prefix ) + len (prog ) + 1 )
1213- # Begin cmd2 customization
1214- if req_parts :
1215- lines = get_lines ([prog , * req_parts ], indent , prefix )
1216- lines .extend (get_lines (opt_parts , indent ))
1217- lines .extend (get_lines (pos_parts , indent ))
1218- elif opt_parts :
1219- lines = get_lines ([prog , * opt_parts ], indent , prefix )
1220- lines .extend (get_lines (pos_parts , indent ))
1221- elif pos_parts :
1222- lines = get_lines ([prog , * pos_parts ], indent , prefix )
1223- else :
1224- lines = [prog ]
1225- # End cmd2 customization
1226-
1227- # if prog is long, put it on its own line
1228- else :
1229- indent = ' ' * len (prefix )
1230- # Begin cmd2 customization
1231- parts = req_parts + opt_parts + pos_parts
1232- lines = get_lines (parts , indent )
1233- if len (lines ) > 1 :
1234- lines = []
1235- lines .extend (get_lines (req_parts , indent ))
1236- lines .extend (get_lines (opt_parts , indent ))
1237- lines .extend (get_lines (pos_parts , indent ))
1238- # End cmd2 customization
1239- lines = [prog , * lines ]
1240-
1241- # join lines into usage
1242- usage = '\n ' .join (lines )
1243-
1244- # prefix with 'Usage:'
1245- return f'{ prefix } { usage } \n \n '
1246-
1247- def _format_action_invocation (self , action : argparse .Action ) -> str :
1248- if not action .option_strings :
1249- default = self ._get_default_metavar_for_positional (action )
1250- (metavar ,) = self ._metavar_formatter (action , default )(1 )
1251- return metavar
1252-
1253- parts : list [str ] = []
1254-
1255- # if the Optional doesn't take a value, format is:
1256- # -s, --long
1257- if action .nargs == 0 :
1258- parts .extend (action .option_strings )
1259- return ', ' .join (parts )
1260-
1261- # Begin cmd2 customization (less verbose)
1262- # if the Optional takes a value, format is:
1263- # -s, --long ARGS
1264- default = self ._get_default_metavar_for_optional (action )
1265- args_string = self ._format_args (action , default )
1266-
1267- return ', ' .join (action .option_strings ) + ' ' + args_string
1268- # End cmd2 customization
1269-
1270- def _determine_metavar (
1271- self ,
1272- action : argparse .Action ,
1273- default_metavar : str ,
1274- ) -> str | tuple [str , ...]:
1275- """Determine what to use as the metavar value of an action."""
1276- if action .metavar is not None :
1277- result = action .metavar
1278- elif action .choices is not None :
1279- choice_strs = [str (choice ) for choice in action .choices ]
1280- # Begin cmd2 customization (added space after comma)
1281- result = f'{ ", " .join (choice_strs )} '
1282- # End cmd2 customization
1283- else :
1284- result = default_metavar
1285- return result
1286-
1287- def _metavar_formatter (
1288- self ,
1289- action : argparse .Action ,
1290- default_metavar : str ,
1291- ) -> Callable [[int ], tuple [str , ...]]:
1292- metavar = self ._determine_metavar (action , default_metavar )
1293-
1294- def format_tuple (tuple_size : int ) -> tuple [str , ...]:
1295- if isinstance (metavar , tuple ):
1296- return metavar
1297- return (metavar ,) * tuple_size
1298-
1299- return format_tuple
1300-
13011132 def _build_nargs_range_str (self , nargs_range : tuple [int , int | float ]) -> str :
13021133 """Generate nargs range string for help text."""
13031134 if nargs_range [1 ] == constants .INFINITY :
@@ -1314,13 +1145,12 @@ def _format_args(self, action: argparse.Action, default_metavar: str) -> str:
13141145
13151146 All formats in this function need to be handled by _rich_metavar_parts().
13161147 """
1317- metavar = self ._determine_metavar (action , default_metavar )
1318- metavar_formatter = self ._metavar_formatter (action , default_metavar )
1148+ get_metavar = self ._metavar_formatter (action , default_metavar )
13191149
13201150 # Handle nargs specified as a range
13211151 nargs_range = action .get_nargs_range () # type: ignore[attr-defined]
13221152 if nargs_range is not None :
1323- arg_str = '%s' % metavar_formatter (1 ) # noqa: UP031
1153+ arg_str = '%s' % get_metavar (1 ) # noqa: UP031
13241154 range_str = self ._build_nargs_range_str (nargs_range )
13251155 return f"{ arg_str } { range_str } "
13261156
@@ -1329,8 +1159,8 @@ def _format_args(self, action: argparse.Action, default_metavar: str) -> str:
13291159 # To make this less verbose, format it like: 'command arg{5}'.
13301160 # Do not customize the output when metavar is a tuple of strings. Allow argparse's
13311161 # formatter to handle that instead.
1332- if isinstance (metavar , str ) and isinstance (action .nargs , int ) and action .nargs > 1 :
1333- arg_str = '%s' % metavar_formatter (1 ) # noqa: UP031
1162+ if not isinstance (action . metavar , tuple ) and isinstance (action .nargs , int ) and action .nargs > 1 :
1163+ arg_str = '%s' % get_metavar (1 ) # noqa: UP031
13341164 return f"{ arg_str } {{{ action .nargs } }}"
13351165
13361166 # Fallback to parent for all other cases
@@ -1342,19 +1172,18 @@ def _rich_metavar_parts(
13421172 default_metavar : str ,
13431173 ) -> Iterator [tuple [str , bool ]]:
13441174 """Override to handle all cmd2-specific formatting in _format_args()."""
1345- metavar = self ._determine_metavar (action , default_metavar )
1346- metavar_formatter = self ._metavar_formatter (action , default_metavar )
1175+ get_metavar = self ._metavar_formatter (action , default_metavar )
13471176
13481177 # Handle nargs specified as a range
13491178 nargs_range = action .get_nargs_range () # type: ignore[attr-defined]
13501179 if nargs_range is not None :
1351- yield "%s" % metavar_formatter (1 ), True # noqa: UP031
1180+ yield "%s" % get_metavar (1 ), True # noqa: UP031
13521181 yield self ._build_nargs_range_str (nargs_range ), False
13531182 return
13541183
13551184 # Handle specific integer nargs (e.g., nargs=5 -> arg{5})
1356- if isinstance (metavar , str ) and isinstance (action .nargs , int ) and action .nargs > 1 :
1357- yield "%s" % metavar_formatter (1 ), True # noqa: UP031
1185+ if not isinstance (action . metavar , tuple ) and isinstance (action .nargs , int ) and action .nargs > 1 :
1186+ yield "%s" % get_metavar (1 ), True # noqa: UP031
13581187 yield f"{{{ action .nargs } }}" , False
13591188 return
13601189
0 commit comments