Metadata-Version: 2.1
Name: rich_argparse
Version: 0.6.0
Summary: A rich help formatter for argparse
Project-URL: Homepage, https://github.com/hamdanal/rich-argparse
Project-URL: Documentation, https://github.com/hamdanal/rich-argparse#rich-argparse
Project-URL: Issue-Tracker, https://github.com/hamdanal/rich-argparse/issues
Project-URL: Changelog, https://github.com/hamdanal/rich-argparse/blob/main/CHANGELOG.md
Author-email: Ali Hamdan <ali.hamdan.dev@gmail.com>
License: MIT License
        
        Copyright (c) 2022 Ali Hamdan
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
License-File: LICENSE
Keywords: argparse,help-formatter,rich
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3.7
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Requires-Python: >=3.7
Requires-Dist: rich>=11.0.0
Description-Content-Type: text/markdown

# rich-argparse
[![tests](https://github.com/hamdanal/rich-argparse/actions/workflows/tests.yml/badge.svg)
](https://github.com/hamdanal/rich-argparse/actions/workflows/tests.yml)
[![pre-commit.ci status](https://results.pre-commit.ci/badge/github/hamdanal/rich-argparse/main.svg)
](https://results.pre-commit.ci/latest/github/hamdanal/rich-argparse/main)

[![Python Version](https://img.shields.io/pypi/pyversions/rich-argparse)
![Release](https://img.shields.io/github/v/release/hamdanal/rich-argparse?sort=semver)
![Status](https://img.shields.io/pypi/status/rich-argparse)
![Downloads](https://pepy.tech/badge/rich-argparse/month)
](https://pypi.org/project/rich-argparse/)

Format [argparse](https://docs.python.org/3/library/argparse.html) help output with
[rich](https://pypi.org/project/rich).

![python -m rich_argparse --help](
https://user-images.githubusercontent.com/93259987/194706255-caf3e987-9853-41f5-85d9-1150c7c8ac31.png)

## Installation

Install from PyPI with pip or your favorite tool.

```sh
pip install rich-argparse
```

Or copy the file `rich_argparse.py` to your project provided you have `rich` already installed.

## Usage

Simply pass `formatter_class` to the argument parser
```python
import argparse
from rich_argparse import RichHelpFormatter

parser = argparse.ArgumentParser(..., formatter_class=RichHelpFormatter)
...
```

`RichHelpFormatter` is the equivalent to `argparse.HelpFormatter` in the way it treats whitespace.
rich-argparse also defines four subclasses of `RichHelpFormatter` that are equivalent to the other
argparse formatters:

* `argparse.RawDescriptionHelpFormatter` -> `RawDescriptionRichHelpFormatter`
* `argparse.RawTextHelpFormatter` -> `RawTextRichHelpFormatter`
* `argparse.ArgumentDefaultsHelpFormatter` -> `ArgumentDefaultsRichHelpFormatter`
* `argparse.MetavarTypeHelpFormatter` -> `MetavarTypeRichHelpFormatter`

For more information on what these formatters do, check the [argparse documentation](
https://docs.python.org/3/library/argparse.html#formatter-class).

## Output styles

The default styles used by rich-argparse formatters are carefully chosen to work in different
light and dark themes. If the these styles don't suit your taste, read below to know how to change
them.

> **Note**
> This section only mentions `RichHelpFormatter` but the same can be applied its subclasses.

### Customize the colors
You can customize the colors in the output by modifying the `styles` dictionary on the formatter
class. By default, `RichHelpFormatter` defines the following styles:

```python
{
    'argparse.args': 'cyan',  # for positional-arguments and --options (e.g "--help")
    'argparse.groups': 'dark_orange',  # for group names (e.g. "positional arguments")
    'argparse.help': 'default',  # for argument's help text (e.g. "show this help message and exit")
    'argparse.metavar': 'dark_cyan',  # for metavariables (e.g. "FILE" in "--file FILE")
    'argparse.syntax': 'bold',  # for highlights of back-tick quoted text (e.g. "`some text`"),
    'argparse.text': 'default',  # for the description, epilog and group descriptions (e.g. "A program to foo")
}
```

For example, to make the description and epilog *italic*, change the `argparse.text` style:

```python
RichHelpFormatter.styles["argparse.text"] = "italic"
```

### Customize group name formatting
You can change how the names of the groups (like `'positional arguments'` and `'options'`) are
formatted by setting the `RichHelpFormatter.group_name_formatter` function. By default,
`RichHelpFormatter` sets the function to `str.upper` but any function that takes the group name
as an input and returns a str works. For example, to apply the *Title Case* format do this:

```python
RichHelpFormatter.group_name_formatter = str.title
```

### Special text highlighting

You can highlight patterns in the help text and the description text of your parser's help output
using regular expressions. By default, `RichHelpFormatter` highlights patterns of
`--options-with-hyphens` using the `argparse.args` style and patterns of
`` `back tick quoted text` `` using the `argparse.syntax` style. You can control what patterns get
highlighted by modifying the `RichHelpFormatter.highlights` list.
For example, to disable all highlights, you can clear this list using
`RichHelpFormatter.highlights.clear()`.

You can also add custom highlight patterns and styles. The following example highlights all
occurrences of `pyproject.toml` in green.

```python
# Add a style called `pyproject` which applies a green style (any rich style works)
RichHelpFormatter.styles["argparse.pyproject"] = "green"
# Add the highlight regex (the regex group name must match an existing style name)
RichHelpFormatter.highlights.append(r"\b(?P<pyproject>pyproject\.toml)\b")
# Pass the formatter class to argparse
parser = argparse.ArgumentParser(..., formatter_class=RichHelpFormatter)
...
```

### Colors in the `usage`

`RichHelpFormatter` colors the usage generated by the formatter using the same styles used to color
the arguments and their metavars. If you use a custom `usage` message in the parser, this text will
treated as "plain text" and will not be colored by default. You can enable colors in user defined
usage message with [console markup](https://rich.readthedocs.io/en/stable/markup.html) by setting
`RichHelpFormatter.usage_markup = True`.

## Working with subparsers

If your code uses argparse's subparsers and you want to format the subparsers' help output with
rich-argparse, you have to explicitly pass `formatter_class` to the subparsers since subparsers
do not inherit the formatter class from the parent parser by default. You have two options:

1. Create a helper function to set `formatter_class` automatically:
   ```python
    subparsers = parser.add_subparsers(...)

    def add_parser(*args, **kwds):
        kwds.setdefault("formatter_class", parser.formatter_class)
        return subparsers.add_parser(*args, **kwds)

    p1 = add_parser(...)
    p2 = add_parser(...)
   ```
1. Set `formatter_class` on each subparser individually:
   ```python
    subparsers = parser.add_subparsers(...)
    p1 = subparsers.add_parser(..., formatter_class=parser.formatter_class)
    p2 = subparsers.add_parser(..., formatter_class=parser.formatter_class)
   ```


## Working with third party formatters

`RichHelpFormatter` can be used with third party formatters that do not rely on the **private**
internals of `argparse.HelpFormatter`. For example, [django](https://pypi.org/project/django)
defines a custom help formatter that is used with the built in commands as well as with extension
libraries and user defined commands. To use rich-argparse in your django project, change your
`manage.py` file as follows:

```diff
diff --git a/my_project/manage.py b/my_project/manage.py
index 7fb6855..5e5d48a 100755
--- a/my_project/manage.py
+++ b/my_project/manage.py
@@ -1,22 +1,38 @@
 #!/usr/bin/env python
 """Django's command-line utility for administrative tasks."""
 import os
 import sys


 def main():
     """Run administrative tasks."""
     os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'my_project.settings')
     try:
         from django.core.management import execute_from_command_line
     except ImportError as exc:
         raise ImportError(
             "Couldn't import Django. Are you sure it's installed and "
             "available on your PYTHONPATH environment variable? Did you "
             "forget to activate a virtual environment?"
         ) from exc
+
+    from django.core.management.base import BaseCommand, DjangoHelpFormatter
+    from rich_argparse import RichHelpFormatter
+
+    class DjangoRichHelpFormatter(DjangoHelpFormatter, RichHelpFormatter):  # django first
+        """A rich-based help formatter for django commands."""
+
+    original_create_parser = BaseCommand.create_parser
+
+    def create_parser(*args, **kwargs):
+        parser = original_create_parser(*args, **kwargs)
+        parser.formatter_class = DjangoRichHelpFormatter  # set the formatter_class
+        return parser
+
+    BaseCommand.create_parser = create_parser
+
     execute_from_command_line(sys.argv)


 if __name__ == '__main__':
     main()
```

Now try out some command like: `python manage.py runserver --help`. Notice how the special
ordering of the arguments applied by django is respected by the new help formatter.
