hamdanal / rich-argparse

A rich help formatter for argparse
https://pypi.org/project/rich-argparse/
MIT License
129 stars 11 forks source link

PR #56 introduced a formatting bug #60

Closed kotfu closed 1 year ago

kotfu commented 1 year ago

After further experimenting, I think I found a bug which was introduced by #56. Consider the following:

import argparse
import rich.console
from rich_argparse import RichHelpFormatter

console = rich.console.Console(markup=False, emoji=False, highlight=False)
parser = argparse.ArgumentParser(
    prog="list",
    description="Show all installed applications",
    add_help=False,
    formatter_class=RichHelpFormatter,
)
parser.add_argument(
    "config_name",
    nargs="?",
    help="a configuration name",
)
parser.add_argument(
    "-r",
    "--raw",
    action="store_true",
    required=True,
    help="show apps without formatting",
)
parser.add_argument(
    "-s",
    "--state",
    choices=["running", "stopped"],
    help="only show apps in a given state",
)
console.print(parser.format_help())

In the released 1.0.0 version, the output is:

Usage: list -r [-s {running,stopped}] [config_name]

Show all installed applications

Positional Arguments:
  config_name           a configuration name

Options:
  -r, --raw             show apps without formatting
  -s, --state {running,stopped}
                        only show apps in a given state

In the unreleased main branch, the output is:

Usage: list -r [-s {running,stopped}]
[config_name]

Show all installed applications

Positional Arguments:
  config_name           a configuration name

Options:
  -r, --raw             show apps without formatting
  -s, --state {running,stopped}
                        only show apps in a given state
hamdanal commented 1 year ago

console.print(parser.format_help())

It seems like you are hitting #54 again. parser.format_help() produces a text with ansi escape sequences that you are printing with console.print which treats it as literal text, not as ansi text. It appears that the new %(prog)s style in your example makes the produced raw ansi text just long enough to exceed the width of your console which in turn wraps it to the second line. Here is the produced ansi text of the usage:

As you can see the second one differs from the first only by the new "%(prog)s style" \x1b[38;5;244mlist\x1b[0m which is the expected behavior. You are just using the wrong tool to display it on the terminal. Again, here are your options to print the output:

Code ```python import argparse import rich.console from rich.text import Text from rich_argparse import RichHelpFormatter console = rich.console.Console(markup=False, emoji=False, highlight=False) parser = argparse.ArgumentParser( prog="list", description="Show all installed applications", add_help=False, formatter_class=RichHelpFormatter, ) parser.add_argument( "config_name", nargs="?", help="a configuration name", ) parser.add_argument( "-r", "--raw", action="store_true", required=True, help="show apps without formatting", ) parser.add_argument( "-s", "--state", choices=["running", "stopped"], help="only show apps in a given state", ) usage = parser.format_usage() console.rule("BEST: built-in print") print(usage) console.rule("2ND BEST: Text.from_ansi with soft_wrap=True") console.print(Text.from_ansi(usage), soft_wrap=True) console.rule("WORKS: console.print with soft_wrap=True") console.print(usage, soft_wrap=True) console.rule("MOSTLY WORKS: Text.from_ansi") console.print(Text.from_ansi(usage)) console.rule("WRONG: console.print") console.print(usage) ```

rich_argparse_printing_options