Skip to content

gh-148766: Add colour to Python help#148767

Merged
hugovk merged 7 commits intopython:mainfrom
hugovk:3.15-help-colour
May 6, 2026
Merged

gh-148766: Add colour to Python help#148767
hugovk merged 7 commits intopython:mainfrom
hugovk:3.15-help-colour

Conversation

@hugovk
Copy link
Copy Markdown
Member

@hugovk hugovk commented Apr 19, 2026

python --help (and especially --help-all) is a monochrome wall of text. Similar to argparse help, let's add some colour to add structure and improve readability.

Here's real screenshots of --help and termshot capture of --help-all:

Before After
--help
--help
--help-all
--help-all

📚 Documentation preview 📚: https://cpython-previews--148767.org.readthedocs.build/

@hugovk hugovk added the interpreter-core (Objects, Python, Grammar, and Parser dirs) label Apr 19, 2026
Comment thread Python/initconfig.c Outdated
Comment thread Python/initconfig.c Outdated
#if defined(MS_WINDOWS) && defined(HAVE_WINDOWS_CONSOLE_IO)
{
DWORD mode = 0;
HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this also consider stderr (or maybe it does? I don't know Windows quirks).

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Something like 294d008?

Comment thread Python/initconfig.c Outdated
PyMem_RawFree(buf);
}
else {
fprintf(f, usage_line, program);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If PyMem_RawMalloc fails we will get the raw tags, no?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This now falls back to no tags.

Comment thread Python/initconfig.c Outdated
return;
}
}
fprint_tagged(stdout, usage_envvars, 0);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We still need formatting here?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, updated to use colour if available.

Copy link
Copy Markdown
Member

@serhiy-storchaka serhiy-storchaka left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if the program path by accident contains {E}?

@hugovk
Copy link
Copy Markdown
Member Author

hugovk commented Apr 21, 2026

Updated to flip it: colour codes are now included in the help text (via macros to keep it tidier), and stripped out when not needed.

So {E} in the path is not an issue.

@hugovk hugovk marked this pull request as draft April 21, 2026 15:25
@hugovk hugovk marked this pull request as ready for review April 22, 2026 18:17
@hugovk
Copy link
Copy Markdown
Member Author

hugovk commented Apr 22, 2026

  • There are references to options and environment variables in descriptions. I would highlight them too.

Here we go:

image

@hugovk
Copy link
Copy Markdown
Member Author

hugovk commented May 3, 2026

Thanks for the reviews, any further comments?

@encukou
Copy link
Copy Markdown
Member

encukou commented May 5, 2026

Would something like this be more maintainable?

#define RESET "\x1b[0m"
#define ENVVAR(STR)  "\x1b[1;36m" STR RESET

@hugovk
Copy link
Copy Markdown
Member Author

hugovk commented May 5, 2026

Nice idea, updated :)

@read-the-docs-community
Copy link
Copy Markdown

read-the-docs-community Bot commented May 5, 2026

Documentation build overview

📚 cpython-previews | 🛠️ Build #32560311 | 📁 Comparing 0a8ab45 against main (a8c9aa9)

  🔍 Preview build  

5 files changed · ± 5 modified

± Modified

@serhiy-storchaka
Copy link
Copy Markdown
Member

This version is barely readable. What if return to the previous version with substitutions and use some of substitution codes to substitute the program name, the default PYTHONHOME, the path separator instead of just color sequences?

Comment thread Python/initconfig.c Outdated
SHORTOPT("-d") " : turn on parser debugging output (for experts only, only works on\n"
" debug builds); also " ENVVAR_REF("PYTHONDEBUG") SUMMARY_LABEL("=x") "\n"
SHORTOPT("-E") " : ignore " ENVVAR_REF("PYTHON*") " environment variables (such as " ENVVAR_REF("PYTHONPATH") ")\n"
SHORTOPT("-h") " : print this help message and exit (also " SHORTOPT_SUMMARY("-?") " or " ENVVAR_REF("--help") ")\n"
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
SHORTOPT("-h") " : print this help message and exit (also " SHORTOPT_SUMMARY("-?") " or " ENVVAR_REF("--help") ")\n"
SHORTOPT("-h") " : print this help message and exit (also " SHORTOPT_SUMMARY("-?") " or " LONGOPT("--help") ")\n"

Comment thread Python/initconfig.c Outdated
" this option has no effect on stdin; also " ENVVAR_REF("PYTHONUNBUFFERED") SUMMARY_LABEL("=x") "\n"
SHORTOPT("-v") " : verbose (trace import statements); also " ENVVAR_REF("PYTHONVERBOSE") SUMMARY_LABEL("=x") "\n"
" can be supplied multiple times to increase verbosity\n"
SHORTOPT("-V") " : print the Python version number and exit (also " ENVVAR_REF("--version") ")\n"
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
SHORTOPT("-V") " : print the Python version number and exit (also " ENVVAR_REF("--version") ")\n"
SHORTOPT("-V") " : print the Python version number and exit (also " LONGOPT("--version") ")\n"

Comment thread Python/initconfig.c Outdated
"PYTHON_FROZEN_MODULES: whether to use frozen modules; the default is \"on\"\n"
" for installed Python and \"off\" for a local build\n"
" (-X frozen_modules)\n"
HEADING("These variables have equivalent command-line options (see ") ENVVAR_REF("--help") " for details):" "\n"
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
HEADING("These variables have equivalent command-line options (see ") ENVVAR_REF("--help") " for details):" "\n"
HEADING("These variables have equivalent command-line options") "(see " ENVVAR_REF("--help") " for details):" "\n"

Comment thread Python/initconfig.c Outdated
"PYTHONPERFSUPPORT: support the Linux \"perf\" profiler (-X perf)\n"
ENVVAR("PYTHONINSPECT") " : inspect interactively after running script (" SHORTOPT_SUMMARY("-i") ")\n"
ENVVAR("PYTHONINTMAXSTRDIGITS") ": limit the size of int<->str conversions;\n"
" 0 disables the limit (" SHORTOPT_SUMMARY("-X") " " ENVVAR_REF("int_max_str_digits") SUMMARY_LABEL("=N") ")\n"
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
" 0 disables the limit (" SHORTOPT_SUMMARY("-X") " " ENVVAR_REF("int_max_str_digits") SUMMARY_LABEL("=N") ")\n"
" " SUMMARY_LABEL("0") " disables the limit (" SHORTOPT_SUMMARY("-X") " " ENVVAR_REF("int_max_str_digits") SUMMARY_LABEL("=N") ")\n"

Comment thread Python/initconfig.c Outdated
ENVVAR("PYTHONEXECUTABLE") ": set sys.argv[0] to this value (macOS only)\n"
#endif
"PYTHONHASHSEED : if this variable is set to 'random', a random value is used\n"
ENVVAR("PYTHONHASHSEED") " : if this variable is set to 'random', a random value is used\n"
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
ENVVAR("PYTHONHASHSEED") " : if this variable is set to 'random', a random value is used\n"
ENVVAR("PYTHONHASHSEED") " : if this variable is set to '" SUMMARY_LABEL("random") "', a random value is used\n"

Comment thread Python/initconfig.c Outdated
"PYTHONMALLOCSTATS: print memory allocator statistics\n"
"PYTHONPATH : '%lc'-separated list of directories prefixed to the\n"
ENVVAR("PYTHONMALLOCSTATS") ": print memory allocator statistics\n"
ENVVAR("PYTHONPATH") " : '%lc'-separated list of directories prefixed to the\n"
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
ENVVAR("PYTHONPATH") " : '%lc'-separated list of directories prefixed to the\n"
ENVVAR("PYTHONPATH") " : '" SUMMARY_LABEL(%lc) "'-separated list of directories prefixed to the\n"

@serhiy-storchaka
Copy link
Copy Markdown
Member

My previous comment was related to the version prior to the latest change, but I still thing that substitution-based approach would be clearer than macros-based.

@hugovk
Copy link
Copy Markdown
Member Author

hugovk commented May 5, 2026

@serhiy-storchaka Could you give a short example of what you're thinking of?

@serhiy-storchaka
Copy link
Copy Markdown
Member

Simple example:

"{E}PYTHONHOME{r}      : alternate <prefix> directory (or <prefix>{b}{D}{r}<exec_prefix>).\n"
"                  The default module search path uses {b}{H}{r}.\n"

{E}, {b} and {r} substitute color sequences, {D} substitutes the DELIM character, {H} substitutes PYTHONHOMEHELP.

To avoid repeated {r} we can also change the syntax, for example:

"#E{PYTHONHOME}      : alternate <prefix> directory (or <prefix>#b{#D}<exec_prefix>).\n"
"                  The default module search path uses #b{#H}.\n"

This is simpler than it looks. #E{ and #b{ change the color, } resets it to default. We do not need to support arbitrary nesting.

@hugovk
Copy link
Copy Markdown
Member Author

hugovk commented May 6, 2026

Thanks, updated! How does this look?

Copy link
Copy Markdown
Member

@serhiy-storchaka serhiy-storchaka left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. 👍

@hugovk hugovk merged commit e7613f2 into python:main May 6, 2026
59 checks passed
@hugovk hugovk deleted the 3.15-help-colour branch May 6, 2026 13:48
@hugovk
Copy link
Copy Markdown
Member Author

hugovk commented May 6, 2026

Thanks all for the reviews!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

interpreter-core (Objects, Python, Grammar, and Parser dirs)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants