Skip to content

Commit b3f4d86

Browse files
authored
Merge pull request #216 from dwreeves/enhance-docs
[Draft] Enhance documentation with accessibility and comparison pages
2 parents 964019e + 3abaaa2 commit b3f4d86

File tree

15 files changed

+461
-63
lines changed

15 files changed

+461
-63
lines changed

.pre-commit-config.yaml

+8
Original file line numberDiff line numberDiff line change
@@ -47,3 +47,11 @@ repos:
4747
types: [python]
4848
exclude: ^examples|^docs/
4949
require_serial: true
50+
51+
- repo: https://github.com/codespell-project/codespell
52+
rev: v2.2.4
53+
hooks:
54+
- id: codespell
55+
files: ^docs/.*\.md$
56+
additional_dependencies:
57+
- tomli

README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
- Rich is a _"Python library for rich text and beautiful formatting in the terminal"_.
2828

2929
The intention of `rich-click` is to provide attractive help output from
30-
Click, formatted with Rich, with minimal customisation required.
30+
Click, formatted with Rich, with minimal customization required.
3131

3232
## Features
3333

@@ -39,7 +39,7 @@ Click, formatted with Rich, with minimal customisation required.
3939
- 🎁 Group commands and options into named panels
4040
- ❌ Well formatted error messages
4141
- 🔢 Easily give custom sort order for options and commands
42-
- 🎨 Extensive customisation of styling and behaviour possible
42+
- 🎨 Extensive customization of styling and behaviour possible
4343

4444
## Installation
4545

docs/blog/posts/pycon-sweden-2024.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ You can find my slides below:
2121
## Slides
2222

2323

24-
[Open in new tab   :octicons-link-external-16:](/rich-click/images/blog/pycon-sweden-2024/Ewels-PyCon-Sweden-2024.pdf){ .md-button }
24+
[Open in new tab   :octicons-link-external-16:](../../images/blog/pycon-sweden-2024/Ewels-PyCon-Sweden-2024.pdf){ .md-button }
2525

2626

2727
<iframe style="width: 100%; border: 1px solid #333; aspect-ratio: 16 / 10;" src="/rich-click/images/blog/pycon-sweden-2024/Ewels-PyCon-Sweden-2024.pdf" title="PyCon Sweden 2024 Slides - Phil Ewels"></iframe>
+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# /// script
2+
# dependencies = [
3+
# "rich",
4+
# ]
5+
from rich.console import Console
6+
from rich.box import SIMPLE
7+
from rich.table import Table
8+
9+
console = Console(color_system="truecolor")
10+
table = Table(title="ANSI Colors", box=SIMPLE)
11+
colors = ["black", "red", "green", "yellow", "blue", "magenta", "cyan", "white"]
12+
table.add_column("Color", style="bold")
13+
14+
for variant in ["Normal", "Dim", "Bright", "Dim +\nBright"]:
15+
table.add_column(variant, style="bold")
16+
17+
for color in colors:
18+
table.add_row(
19+
color,
20+
*[
21+
f"[{style}{color}]██████[/{style}{color}]"
22+
for style in ["", "dim ", "bright_", "dim bright_"]
23+
]
24+
)
25+
26+
console.print(table)

docs/documentation/accessibility.md

+114
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
# Accessibility
2+
3+
This page goes over information relevant to both developers and users relating to accessibility considerations.
4+
5+
Accessibility is very important to consider when developing applications.
6+
Colorblindness impacts roughly 4% of the general population, meaning that if your application gets even a small user base, there is a high probability that it is being used by someone with colorblindness.
7+
8+
Fortunately, there are ways as both developers and users to address these accessibility concerns, as detailed on this page.
9+
10+
## For users
11+
12+
If you are a user of a **rich-click** CLI, there are a few options you have to improve accessibility for yourself.
13+
14+
### 1. Use the `NO_COLOR` environment variable
15+
16+
Rich uses the `NO_COLOR` standard ([more information here](https://no-color.org/)), giving rich-click built-in capability to allow the user to suppress color.
17+
18+
So, to run any rich-click CLI program without colour, you can do:
19+
20+
```shell
21+
export NO_COLOR=1 # Set environment variable in shell
22+
python cli.py # Run CLI tool
23+
24+
# ... Or run as a single line:
25+
NO_COLOR=1 python cli.py
26+
```
27+
28+
In order to set this environment variable automatically every time you use the terminal, you can add it to your `~/.bashrc` (if using bash) or `~/.zshrc` (if using zsh):
29+
30+
=== "bash"
31+
```shell
32+
echo "export NO_COLOR=1" >> ~/.bashrc
33+
```
34+
35+
=== "zsh"
36+
```shell
37+
echo "export NO_COLOR=1" >> ~/.zshrc
38+
```
39+
40+
!!!tip
41+
Note that other programs may also respect `NO_COLOR`, so it could have other effects!
42+
43+
### 2. Configure your terminal's 4-bit ANSI colors
44+
45+
The 4-bit ANSI color system is a set of 16 different colors implemented in every terminal. This is the most common way to set colors.
46+
These colors are **not** deterministic; different terminals use slightly different hex values for the ANSI colors. [Wikipedia has a full breakdown of all the variations in these colors](https://en.wikipedia.org/wiki/ANSI_escape_code#3-bit_and_4-bit)
47+
48+
Most modern terminals have the ability to customize all of these colors in the terminals' settings.
49+
If you are having difficulty distinguishing colors, it is recommended that you adjust these settings.
50+
51+
!!! note
52+
This will only work for CLIs that utilize the 4-bit ANSI color system.
53+
CLIs that utilize hex values or other color systems will not be impacted by your terminal's ANSI color settings.
54+
55+
## For developers
56+
57+
If you would like to make your CLI more accessible for others, there are a few rules of thumb you can follow:
58+
59+
### 1. Use Rich features over Click features
60+
61+
There are some Click features that rich-click doesn't override such as print statements and interactive prompts (see [Comparison of Click and rich-click](comparison_of_click_and_rich_click.md#click-features-that-rich-click-does-not-override)).
62+
63+
In these cases, we recommend using native Rich functionality so that your end users can benefit from `NO_COLOR`, which Click does not support.
64+
65+
So, for example:
66+
67+
- `#!python Confirm.ask("[red]Are you sure?[/]")` is more accessible because it works with `NO_COLOR`.
68+
- `#!python click.confirm(click.echo("Are you sure?", fg="red"))` is less accessible because it cannot be overridden by `NO_COLOR`.
69+
70+
### 2. Use 4-bit ANSI colors
71+
72+
The 4-bit ANSI color system is a set of 16 different colors implemented in effectively every terminal, and they are the most common way to set colors.
73+
These colors are **not** deterministic; different terminals use slightly different hex values for the ANSI colors. [Wikipedia has a full breakdown of all the variations in these colors](https://en.wikipedia.org/wiki/ANSI_escape_code#3-bit_and_4-bit)
74+
75+
!!! note
76+
**rich-click**'s logo references the ANSI colors! 😁
77+
78+
There are 16 total ANSI colors: 8 base ANSI colors, with each one having a "bright" variant:
79+
80+
- `black`, `bright_black`
81+
- `red`, `bright_red`
82+
- `green`, `bright_green`
83+
- `yellow`, `bright_yellow`
84+
- `blue`, `bright_blue`
85+
- `magenta`, `bright_magenta`
86+
- `cyan`, `bright_cyan`
87+
- `white`, `bright_white`
88+
89+
Additionally, each one of these can be modified with `dim`, which in modern terminals just applies a change to the opacity of the color, giving developers a total of 32 different colors that can be shown.
90+
91+
Below is a quick script that renders all of these colors:
92+
93+
```python
94+
{!code_snippets/accessibility/colors.py!}
95+
```
96+
97+
<!-- RICH-CODEX
98+
working_dir: docs/code_snippets/accessibility
99+
hide_command: true
100+
terminal_width: 48
101+
-->
102+
![`python colors.py`](../images/code_snippets/accessibility/colors.svg){.screenshot}
103+
104+
(The colors you see when running this locally will differ from the colors in the image.)
105+
106+
The fact that the colors are not deterministic is a _benefit_ for accessibility; it means, for example, a user can customize their terminal so that the ANSI "red" is more suitable for them.
107+
Nearly every modern terminal allows for this sort of customization.
108+
109+
This means that developers looking to create a more accessible experience should prefer ANSI colors.
110+
111+
So, for example:
112+
113+
- `#!python RichHelpConfiguration(style_option="red")` is more accessible because users can configure the hex value of this red.
114+
- `#!python RichHelpConfiguration(style_option="#FF0000")` is less accessible because it is not configurable by the end user.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
# Comparison of Click and rich-click
2+
3+
**rich-click** is a [shim](https://en.wikipedia.org/wiki/Shim_(computing)) around Click,
4+
meaning its API is designed to mirror the Click API and intercept some of the calls to slightly different functions.
5+
6+
Everything available via `#!python import click` is also available via `#!python import rich_click as click`.
7+
8+
**rich-click** is designed to keep the additional API surface introduced on top of Click as lightweight as possible.
9+
10+
## Click features that rich-click overrides
11+
12+
The only things that **rich-click** explicitly overrides in the high-level API are the decorators:
13+
14+
- `click.command()`
15+
- `click.group()`
16+
17+
The only change to these decorators is that by default, their `cls=` parameters point to the **rich-click** implementations of `Command` (i.e. `RichCommand`) and `Group` (i.e. `RichGroup`).
18+
19+
!!! note
20+
There is also a thin wrapper around `pass_context()` to cast the `click.Context` type in the function signature to `click.RichContext` to assist with static type-checking with MyPy. Aside from different typing, there are no substantive changes to the `pass_context()` decorator.
21+
22+
## Click features that rich-click does _not_ override
23+
24+
### Base Click command classes
25+
26+
You can still access the base Click classes by their original names:
27+
28+
```python
29+
from rich_click import Command, Group, Context
30+
```
31+
32+
The above are the same as importing from `click`.
33+
34+
**rich-click**'s subclasses all have the word Rich in front of them!
35+
36+
```python
37+
from rich_click import RichCommand, RichGroup, RichContext
38+
```
39+
40+
### Echo and interactive elements
41+
42+
**rich-click** deliberately does _not_ enrich certain Click features:
43+
44+
```python
45+
click.echo()
46+
click.echo_via_pager()
47+
click.confirm()
48+
click.prompt()
49+
```
50+
51+
You are free to use these functions and they are available via `#!python import rich_click as click`,
52+
but Rich's markup will not work with these functions because these functions are just the base Click implementations,
53+
without any changes.
54+
55+
This is a deliberate decision that we are unlikely to change in the future.
56+
We do not want to maintain a more spread-out API surface, and we encourage users to become comfortable using Rich directly; it's a great library and it's worth learning a little bit about it!
57+
If you'd like Rich markup for your echos and interactive elements, then you can:
58+
59+
| Click Function | Rich Replacement | Rich Documentation |
60+
|---------------|------------------|---------------|
61+
| `click.echo()` | `rich.print()` | [Quick start](https://rich.readthedocs.io/en/stable/introduction.html#quick-start) |
62+
| `click.echo_via_pager()` | `rich.Console().pager()` | [Console](https://rich.readthedocs.io/en/stable/console.html#paging) |
63+
| `click.confirm()` | `rich.prompt.Confirm.ask()` | [Prompt](https://rich.readthedocs.io/en/stable/prompt.html) |
64+
| `click.prompt()` | `rich.prompt.Prompt.ask()` | [Prompt](https://rich.readthedocs.io/en/stable/prompt.html) |
65+
66+
Below is a side-by-side comparison of Click and Rich implementations of echos and interactive elements in **rich-click**:
67+
68+
=== "Click"
69+
70+
```python
71+
import rich_click as click
72+
73+
@click.command("greet")
74+
def greet():
75+
name = click.prompt(click.style("What is your name?", fg="blue"))
76+
77+
if not click.confirm(click.style("Are you sure?", fg="blue")):
78+
click.echo(click.style("Aborting", fg="red"))
79+
return
80+
81+
click.echo(click.style(f"Hello, {name}!", fg="green"))
82+
83+
if __name__ == "__main__":
84+
greet()
85+
```
86+
87+
=== "Rich"
88+
89+
```python
90+
import rich_click as click
91+
import rich
92+
from rich.prompt import Confirm, Prompt
93+
94+
@click.command("greet")
95+
def greet():
96+
name = Prompt.ask("[blue]What is your name?[/]")
97+
98+
if not Confirm.ask("[blue]Are you sure?[/]"):
99+
rich.print("[red]Aborting[/]")
100+
return
101+
102+
rich.print(f"[green]Hello, {name}![/]")
103+
104+
if __name__ == "__main__":
105+
greet()
106+
```
107+
108+
## Additional rich-click features
109+
110+
- **rich-click** has a configuration object, `RichHelpConfiguration()`, that allows for control over how **rich-click** help text renders, so you are not just locked into the defaults. More information about this is described in [the **Configuration** docs](configuration.md).
111+
- **rich-click** comes with a CLI tool that allows you to convert regular Click CLIs into **rich-click** CLIs, and also lets you render your **rich-click** CLI help text as HTML and SVG. More information about this is described in [the **rich-click CLI** docs](rich_click_cli.md).

docs/documentation/configuration.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Configuration
22

3-
There are two methods to configure rich-click:
3+
There are two methods to configure **rich-click**:
44

55
- Decorator: Use the `@rich_config()` decorator (and `RichHelpConfiguration()`).
66
- Globals: Set the global variables in the `rich_config.rich_config` module.

docs/documentation/formatting_and_styles.md

+6-6
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
## Formatting
88

9-
There are a large number of customisation options in rich-click.
9+
There are a large number of customization options in rich-click.
1010
These can be modified by changing variables in the `click.rich_click` namespace.
1111

1212
Note that most normal click options should still work, such as `show_default=True`, `required=True` and `hidden=True`.
@@ -158,7 +158,7 @@ working_dir: .
158158
-->
159159
![`python examples/01_simple.py --hep || true`](../images/error.svg "Error message"){.screenshot}
160160

161-
You can customise the _Try 'command --help' for help._ message with `ERRORS_SUGGESTION`
161+
You can customize the _Try 'command --help' for help._ message with `ERRORS_SUGGESTION`
162162
using rich-click though, and add some text after the error with `ERRORS_EPILOGUE`.
163163

164164
For example, from [`examples/07_custom_errors.py`](https://github.com/ewels/rich-click/blob/main/examples/07_custom_errors.py):
@@ -211,9 +211,9 @@ Setting `MAX_WIDTH` overrides the effect of `WIDTH`
211211
!!! success
212212
Check out the [**Live Style Editor**](../editor.md) to easily get started building a custom **rich-click** style!
213213

214-
Most aspects of rich-click formatting can be customised, from colours to alignment.
214+
Most aspects of rich-click formatting can be customized, from color to alignment.
215215

216-
For example, to print the option flags in a different colour, you can use:
216+
For example, to print the option flags in a different color, you can use:
217217

218218
```python
219219
click.rich_click.STYLE_OPTION = "magenta"
@@ -226,7 +226,7 @@ click.rich_click.STYLE_OPTIONS_TABLE_LEADING = 1
226226
click.rich_click.STYLE_OPTIONS_TABLE_BOX = "SIMPLE"
227227
```
228228

229-
You can make some really ~horrible~ _colourful_ solutions using these styles if you wish:
229+
You can make some really ~horrible~ _colorful_ solutions using these styles if you wish:
230230

231231
<!-- RICH-CODEX
232232
working_dir: .
@@ -238,5 +238,5 @@ extra_env:
238238

239239
> See [`examples/10_table_styles.py`](https://github.com/ewels/rich-click/blob/main/examples/10_table_styles.py) for an example.
240240
241-
See the [_Configuration options_](#configuration-options) section below for the full list of available options.
241+
See the [_Configuration options_](configuration.md#configuration-options) section below for the full list of available options.
242242

0 commit comments

Comments
 (0)