optparse help output

Dan thermostat at gmail.com
Wed Oct 24 13:26:03 EDT 2007


On Oct 24, 12:06 pm, Tim Chase <python.l... at tim.thechases.com> wrote:
> > I've been using optparse for a while, and I have an option with a
> > number of sub-actions I want to describe in the help section:
>
> >     parser.add_option("-a", "--action",
> >                       help=\
>
> [snipped formatted help]> """)
>
> > Unfortunately, when I run the script with --help, this is what I get
> > for the -a option:
>
> [snipped munged formatting of help]
>
> > Is there any way to get the formatting I want?
>
> I had the same issue:
>
> http://groups.google.com/group/comp.lang.python/browse_thread/thread/...
>
> and was directed by Ben Finney to check out a custom formatter.
> I got it working to my satisfaction and posted it in that thread:
>
> http://groups.google.com/group/comp.lang.python/msg/09f28e26af0699b1
>
> It may be a little more kind in what it does with your help-text.
>   If you need variant behavior you can take my code and mung it
> even further.
>
> The changes are basically a copy&paste (including the comments,
> which Steven D'Aprano suggested might be better made into
> docstrings) of the format_description() and format_option() calls
> from the standard-library's source, and changing a few small
> lines to alter the behavior of calls to textwrap.*
>
> Hope this helps,
>
> -tkc

Thanks, Tim!

That was incredibly helpful. I did alter it to format paragraphs, but
maintain the double newlines. Also, I made a few changes to work with
the 2.3 version of optparse. Posted below for anyone who might want
it. (Also to work as a standalone .py file)

-Dan


# From Tim Chase via comp.lang.python.

from optparse import IndentedHelpFormatter
import textwrap

class IndentedHelpFormatterWithNL(IndentedHelpFormatter):
  def format_description(self, description):
    if not description: return ""
    desc_width = self.width - self.current_indent
    indent = " "*self.current_indent
# the above is still the same
    bits = description.split('\n')
    formatted_bits = [
      textwrap.fill(bit,
        desc_width,
        initial_indent=indent,
        subsequent_indent=indent)
      for bit in bits]
    result = "\n".join(formatted_bits) + "\n"
    return result

  def format_option(self, option):
    # The help for each option consists of two parts:
    #   * the opt strings and metavars
    #   eg. ("-x", or "-fFILENAME, --file=FILENAME")
    #   * the user-supplied help string
    #   eg. ("turn on expert mode", "read data from FILENAME")
    #
    # If possible, we write both of these on the same line:
    #   -x    turn on expert mode
    #
    # But if the opt string list is too long, we put the help
    # string on a second line, indented to the same column it would
    # start in if it fit on the first line.
    #   -fFILENAME, --file=FILENAME
    #       read data from FILENAME
    result = []
    opts = option.option_strings
    opt_width = self.help_position - self.current_indent - 2
    if len(opts) > opt_width:
      opts = "%*s%s\n" % (self.current_indent, "", opts)
      indent_first = self.help_position
    else: # start help on same line as opts
      opts = "%*s%-*s  " % (self.current_indent, "", opt_width, opts)
      indent_first = 0
    result.append(opts)
    if option.help:
      help_text = option.help
# Everything is the same up through here
      help_lines = []
      help_text = "\n".join([x.strip() for x in
help_text.split("\n")])
      for para in help_text.split("\n\n"):
        help_lines.extend(textwrap.wrap(para, self.help_width))
        if len(help_lines):
          # for each paragraph, keep the double newlines..
          help_lines[-1] += "\n"
# Everything is the same after here
      result.append("%*s%s\n" % (
        indent_first, "", help_lines[0]))
      result.extend(["%*s%s\n" % (self.help_position, "", line)
        for line in help_lines[1:]])
    elif opts[-1] != "\n":
      result.append("\n")
    return "".join(result)




More information about the Python-list mailing list