hamdanal / rich-argparse

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

Questions re: bracket and brace rendering #59

Closed kotfu closed 1 year ago

kotfu commented 1 year ago

Consider the following argument parser:

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",
)
mutex = parser.add_mutually_exclusive_group()
mutex.add_argument(
    "--rich",
    action="store_true",
    help="Rich and poor are mutually exclusive. Choose either one but not both.",
)
mutex.add_argument(
    "--poor", action="store_false", dest="rich", help="Does poor mean --not-rich 😉?"
)
parser.add_argument(
    "-s",
    "--state",
    choices=["running", "stopped"],
    help="only show apps in a given state",
)
console.print(parser.format_help())

Note the inconsistent highlighting of brackets and braces.

Observation: The brackets around optional arguments and the pipe separating the mutually exclusive options are the only text output which can not be styled using RichHelpFormatter.styles.

Suggestion: choices for an option (i.e. -s) of which you can only choose one, and mutually exclusive options (i.e. --rich and --poor), of which you can only choose one, should be rendered consistently.

Questions:

hamdanal commented 1 year ago

Questions:

Are these behaviors with [brackets|braces|commas|pipes] intentional?

Yes. I don't do any highlighting for these characters because I don't think highlighting them helps make the CLI help text clearer and easier to read by a human -- this is kinda the whole reason I created this project.

If not, would you consider rendering all of these symbols (braces, brackets, commas, pipes) with a new style, perhaps something like "argparse.symbols"?

If by "all of these symbols" you mean all of your four bullet point examples above then the simple answer is no, I would not consider it. The ones that are colored now (examples 2 & 4) are part of the metavar produced by argparse. I have no intention in parsing metavars as it is a very complicated business. It becomes even more complicated if you factor in the fact that metavars can be set by the user to technically anything. But even without taking user metavars into account, it is very difficult to get a generic solution right. As a for instance, apply this diff to your example and notice the difference in output:

 parser.add_argument(
     "config_name",
-    nargs="?",
+    nargs="+",
     help="a configuration name",
)

If you mean only the symbols that are currently not colored (examples 1 & 3), then I might consider them. I don't have the time (or interest to be frank) to implement this feature though. If you send a PR that is simple enough, well tested, and works with all the quirks of argparse's parenthesis and brackets manipulations I will accept it.

hamdanal commented 1 year ago

After thinking about this a bit more, I think the brackets handling within argparse usage is too fragile. Some of the upstream bugs are enumerated here https://github.com/python/cpython/pull/105039. Implementing this proposal would only lead to more errors with no real benefit compared to the effort. I am closing this now but I may reconsider it when argparse handling of usage is fixed and its semantics are clear.