Hi colleagues I have the code (max_help_position is 2000):
formatter_class=lambda prog: argparse.HelpFormatter(prog, max_help_position=2000)
parser = argparse.ArgumentParser(formatter_class=formatter_class)
subparsers = parser.add_subparsers(title="Commands", metavar="<command>")
cmd_parser = subparsers.add_parser('long_long_long_long_long_long_long',
help='- jksljdalkjda',
formatter_class=formatter_class)
args = parser.parse_args(['-h'])
print args
we have
optional arguments:
-h, --help show this help message and exit
Commands:
<command>
long_long_long_long_long_long_long
- jksljdalkjda
small - descr
instead
optional arguments:
-h, --help show this help message and exit
Commands:
<command>
long_long_long_long_long_long_long - jksljdalkjda
small - descr
Do you know simply way how to fix this?
The code:
class MyFormatter(argparse.HelpFormatter):
def __init__(self, prog):
super(MyFormatter, self).__init__(prog, max_help_position=2000)
self._max_help_position = 2000
self._action_max_length += 4
formatter_class = MyFormatter
parser = argparse.ArgumentParser(formatter_class=formatter_class)
got same result.
The code (with width=2000)
formatter_class = lambda prog: argparse.HelpFormatter(prog,
max_help_position=2000, width=2000)
got same result.
Thank you.
P.S. Also some additional small issue: this is odd spaces in "optional arguments". Do you know how to separate "Commands" and "optional arguments" for do not have spaces in "optional arguments" and have spaces in "Commands" since these are different essences?
You need to increase the width as well
try:
formatter_class=lambda prog: argparse.HelpFormatter(prog,
max_help_position=100, width=200)
As my earlier thoughts (below) show, the formatting considers overall width as well as the max_position value.
(earlier)
In my limited testing, your formatter subclass seems to work. But I haven't pushed the limits.
You many need to dig more into the Formatter code.
For example there is a format_action
method that actually uses the max_width
def _format_action(self, action):
# determine the required width and the entry label
help_position = min(self._action_max_length + 2,
self._max_help_position)
help_width = self._width - help_position
action_width = help_position - self._current_indent - 2
...
Notice that it interacts with the width. Then it goes on to actually format the help lines and perform wrapping. So the actual implementation is not simple.
I'm not following your question about spaces. format_help
commands the formatter to format a number of sections (including argument groups). The sections (usually) end with a couple of line feeds. Upon assembling them the formatter removes 'unnecessary' line feeds, leaving one space between groups. The subparser doesn't fit other categories, so I'd have to study the code to see exactly how it is handled.
Your lambda
definition works as well. I haven't seen it before, and I don't think it's what the developers intended, but Python that doesn't matter - if it works.
Playing around with values and strings, I see that max_position up to about 56 works. Then it sort of sticks. But if I also change width
(default is from CONSOLE), I can increase max_position further.
I was testing this with a long parser
argument. Adding
parser.add_argument('-l','--long','--longlonglonglong', help='help after long option strings')
produces:
usage: issue25297.py [-h] [-l LONG] <command> ...
optional arguments:
-h, --help show this help message and
exit
-l LONG, --long LONG, --longlonglonglong LONG help after long option
strings
Commands:
<command>
long_long_long_long_long_long_long - jksljdalkjda
So max_help_position
does work in regular parser formatting. But for some reason, when only the subparser names are long, it does not. That section requires some special formatting. It is indented, and the subparser names are not real actions (arguments) but rather choices the subparsers
argument. I'll have study it in more detail.
The subparser name string is indented 2 extra characters (compared to other arguments). The code that collects self._action_max_length
does not take this into account. Hence if the subparser name is the longest string, this max_length will end up 2 spaces short. Compare actual v desired:
long_long_long_long_long_long_long
- jksljdalkjda
long_long_long_long_long_long_long - jksljdalkjda
(Formatting is done in 2 steps; once to calculate values like this _action_max_length
, and a 2nd time to produce the actual output).
Subparsers are formatted with a recursive call to _format_action
, so I'm not optimistic about an easy fix.
Corrected formatter
Here's a patched Formatter that correctly accounts for the indenting of subactions (sub parsers). When an argument (action) is added to the Formatter, this function figures how wide its invocation strings are, and adjusts self._max_action_length. This is used latter to indent the help strings.
class MyFormatter(argparse.HelpFormatter):
"""
Corrected _max_action_length for the indenting of subactions
"""
def add_argument(self, action):
if action.help is not argparse.SUPPRESS:
# find all invocations
get_invocation = self._format_action_invocation
invocations = [get_invocation(action)]
current_indent = self._current_indent
for subaction in self._iter_indented_subactions(action):
# compensate for the indent that will be added
indent_chg = self._current_indent - current_indent
added_indent = 'x'*indent_chg
invocations.append(added_indent+get_invocation(subaction))
# print('inv', invocations)
# update the maximum item length
invocation_length = max([len(s) for s in invocations])
action_length = invocation_length + self._current_indent
self._action_max_length = max(self._action_max_length,
action_length)
# add the item to the list
self._add_item(self._format_action, [action])
An example of its use (without going real wide):
# call class with alternate parameters
formatter_class=lambda prog: MyFormatter(prog, max_help_position=40,width=100)
parser = argparse.ArgumentParser(formatter_class=formatter_class)
parser.add_argument('-l','--long', help='help after long option strings')
subparsers = parser.add_subparsers(title="Commands", metavar="<command>")
cmd_parser = subparsers.add_parser('long_long_cmd',
help='longish command',
formatter_class=formatter_class,
aliases=['long', 'long_cmd'])
# newer arpgarse take aliases
sht_parser = subparsers.add_parser('short', help = 'short cmd')
args = parser.parse_args(['-h'])
which displays:
usage: issue25297.py [-h] [-l LONG] <command> ...
optional arguments:
-h, --help show this help message and exit
-l LONG, --long LONG help after long option strings
Commands:
<command>
long_long_cmd (long, long_cmd) longish command
short short cmd
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With