anntzer / defopt

Effortless argument parser
https://pypi.org/project/defopt/
MIT License
213 stars 11 forks source link

Support for blank lines and indentation in argument help #127

Closed msto closed 5 months ago

msto commented 6 months ago

Hi,

Would it be possible to support blank lines and nested indentation in an argument's help?

e.g. in this example, it'd be helpful to align the special note with its parent bullet, and add a line of space between the summary and the list of fields.

Current formatting and output:

from pathlib import Path

import defopt

def main(*, in_foo: Path, in_bar: Path) -> None:
    """
    Example help text.

    Args:
        in_foo: Ipsum dolor
        in_bar: This argument has more detailed help text.
            It has multiple lines describing the format of the input file.
            And, there is a list enumerating its fields:
            - Field 1: ipsum dolor
            - Field 2: ipsum dolor
            **Special note about field 2**
            - Field 3: ipsum dolor
    """

if __name__ == "__main__":
    defopt.run(main)
$ python test.py -h
usage: test.py [-h] --in-foo IN_FOO --in-bar IN_BAR

Example help text.

options:
  -h, --help       show this help message and exit
  --in-foo IN_FOO  Ipsum dolor
  --in-bar IN_BAR  This argument has more detailed help text.
                   It has multiple lines describing the format of the input file.
                   And, there is a list enumerating its fields:
                   - Field 1: ipsum dolor
                   - Field 2: ipsum dolor
                   Special note about field 2
                   - Field 3: ipsum dolor

Desired formatting and output:

from pathlib import Path

import defopt

def main(*, in_foo: Path, in_bar: Path) -> None:
    """
    Example help text.

    Args:
        in_foo: Ipsum dolor
        in_bar: This argument has more detailed help text.
            It has multiple lines describing the format of the input file.

            And, there is a list enumerating its fields:
            - Field 1: ipsum dolor
            - Field 2: ipsum dolor
              **Special note about field 2**
            - Field 3: ipsum dolor
    """

if __name__ == "__main__":
    defopt.run(main)
$ python test.py -h
usage: test.py [-h] --in-foo IN_FOO --in-bar IN_BAR

Example help text.

options:
  -h, --help       show this help message and exit
  --in-foo IN_FOO  Ipsum dolor
  --in-bar IN_BAR  This argument has more detailed help text.
                   It has multiple lines describing the format of the input file.

                   And, there is a list enumerating its fields:
                   - Field 1: ipsum dolor
                   - Field 2: ipsum dolor
                     Special note about field 2
                   - Field 3: ipsum dolor
anntzer commented 6 months ago

Thanks for the report. That looks like a simple bug in the doc mangling routine. Can you check that the following patch fixes the issue for you?

diff --git i/src/defopt.py w/src/defopt.py
index 5a5e9f9..f3f0cd5 100644
--- i/src/defopt.py
+++ w/src/defopt.py
@@ -976,7 +976,7 @@ def _parse_docstring(doc):
             visitor = Visitor(self.document)
             field_body_node.walkabout(visitor)
             if doctype in ['param', 'type']:
-                self.params[name][doctype] = ''.join(visitor.paragraphs)
+                self.params[name][doctype] = '\n\n'.join(visitor.paragraphs)
             elif doctype in ['raises']:
                 self.raises.append(name)
             raise SkipNode
anntzer commented 5 months ago

Committed the fix. Thanks for the report!