Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Formatting error when printing via rich.console #54

Closed
kotfu opened this issue Feb 18, 2023 · 1 comment
Closed

Formatting error when printing via rich.console #54

kotfu opened this issue Feb 18, 2023 · 1 comment
Labels
invalid This doesn't seem right rich Concerns rich

Comments

@kotfu
Copy link

kotfu commented Feb 18, 2023

When printing the results of format_help() from an argparser that uses RichHelpFormatter() as a formatter, the output is not formatted correctly if those results are printed using rich.console.Console. I've created a program which reproduces this problem:

# reproduce a formatting bug in RichHelpFormatter()

import argparse
import rich_argparse
import rich.console

console = rich.console.Console(markup=False, emoji=False, highlight=False)
prsr = argparse.ArgumentParser(
    prog="config",
    description="Edit or show the location of the user configuration file.",
    formatter_class=rich_argparse.RichHelpFormatter,
)
prsr.add_argument(
    "action",
    choices=["edit", "file", "convert"],
    help="""'edit' edits the configuration file in your preferred editor.
            'file' shows the name of the configuration file.
            'convert' writes a new .toml configuration file with the same settings as the old .ini configuration file.""",
)

console.rule("printing help with print()")
print(prsr.format_help())

console.rule("printing help with rich.console.print")
console.print(prsr.format_help())

Here's a screenshot of the output:
screenshot

Note that when the output is printed using console.print(prsr.format_help()) the help text for the single positional argument does not wrap correctly.

My current (untested) hypothesis is that this has something to do with having nested rich.console objects. The current implementation of format_help() uses the .capture() context manager to collect the output before returning.

@hamdanal
Copy link
Owner

Thanks for the extra context.

Note that when the output is printed using console.print(prsr.format_help()) the help text for the single positional argument does not wrap correctly.

This has to do with your console trying to wrap the output to fit the console width (the console width is by default set to the width of your terminal). Note that the formatter's output is wrapped by the formatter itself, not by the internal console and shouldn't be wrapped by the external console. This is how argparse formatters work (HelpFormatter wraps everything, RawDescriptionHelpFormatter wraps everything except the description, RawTextHelpFormatter doesn't do any wrapping).
To solve your issue, you have two solutions:

  1. use the built-in print (as you saw with the first part of your example): print(prsr.format_help())
  2. tell your console to not wrap the formatter output as this is handled by the formatter itself: console.print(prsr.format_help(), soft_wrap=True)

My current (untested) hypothesis is that this has something to do with having nested rich.console objects. The current implementation of format_help() uses the .capture() context manager to collect the output before returning.

This has nothing to do with the internal console, it just return the text as a string. The same wrapping issue would happen if you console print any long text that contains new lines and leading spaces. If you follow solution 2 above, your problem will be solved.

I'll close this issue as no action has to be taken in rich_argparse. Feel free to continue the discussion if you have more questions.

@hamdanal hamdanal closed this as not planned Won't fix, can't repro, duplicate, stale Feb 18, 2023
@hamdanal hamdanal added the invalid This doesn't seem right label Feb 18, 2023
@hamdanal hamdanal added the rich Concerns rich label Aug 19, 2023
hamdanal added a commit that referenced this issue Sep 24, 2023
This is a new approach that allows the formatter itself to be rendered
with rich. The handling of whitespace manipulation and wrapping is now
baked into the renderable itself. This also removes the need to use
`soft_wrap=True` when printing the formatted help. The downside is that
the code is now very low-level in terms of rich rendering, it needs to
do line-by-line handling of `Segment` objects.

This could help unblock more niche use-cases like #81 and #54.
hamdanal added a commit that referenced this issue Sep 24, 2023
This is a new approach that allows the formatter itself to be rendered
with rich. The handling of whitespace manipulation and wrapping is now
baked into the renderable itself. This also removes the need to use
`soft_wrap=True` when printing the formatted help. The downside is that
the code is now very low-level in terms of rich rendering, it needs to
do line-by-line handling of `Segment` objects.

This could help unblock more niche use-cases like #81 and #54.
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
invalid This doesn't seem right rich Concerns rich
Projects
None yet
Development

No branches or pull requests

2 participants