diff options
| author | Jonathan Corbet <corbet@lwn.net> | 2025-08-29 15:58:48 -0600 |
|---|---|---|
| committer | Jonathan Corbet <corbet@lwn.net> | 2025-08-29 15:58:48 -0600 |
| commit | c67a9f492c3c15ef1695c629bf5cc57f674a8e83 (patch) | |
| tree | 0b09fbef0138730702a0ef2c3b19d5748ca7145c /tools/docs/lib/enrich_formatter.py | |
| parent | 61578493ca7f9d4acd804544f3f5651f5124b12f (diff) | |
| parent | aebcc3009ed55564b74378945206642a372c3e27 (diff) | |
Merge branch 'mauro' into docs-mw
Another build series from Mauro:
The goal of this series is to drop one of the most ancient and ugliest
hack from the documentation build system. Before migrating to Sphinx,
the media subsystem already had a very comprehensive uAPI book, together
with a build time system to detect and point for any documentation gaps.
When migrating to Sphinx, we ported the logic to a Perl script
(parse-headers.pl) and Markus came up with a Sphinx extension
(kernel_include.py). We also added some files to control how parse-headers
produce results, and a Makefile.
At the initial Sphinx versions (1.4.1 if I recall correctly), when
a new symbol is added to videodev2.h, a new warning were
produced at documentatiion time, it the patchset didn't have
the corresponding documentation path.
While kernel-include is generic, the only user at the moment is the media
subsystem.
This series gets rid of the Python script, replacing it by a command
line script and a class. The parse header class can optionally be used by
kernel-include to produce an enriched code that will contain cross-references.
As the other conversions, it starts with a bug-compatible version of
parse-headers, but the subsequent patches add more functionalities and
fix bugs.
It should be noticed that modern of Sphinx disabled the cross-reference
warnings. So, at the next series, I'll be re-adding it in a controlled way
(e.g. just for the references from kernel-include that has an special
argument).
The script also supports now generating a "toc" output, which will be used
at the next series.
Diffstat (limited to 'tools/docs/lib/enrich_formatter.py')
| -rw-r--r-- | tools/docs/lib/enrich_formatter.py | 70 |
1 files changed, 70 insertions, 0 deletions
diff --git a/tools/docs/lib/enrich_formatter.py b/tools/docs/lib/enrich_formatter.py new file mode 100644 index 000000000000..bb171567a4ca --- /dev/null +++ b/tools/docs/lib/enrich_formatter.py @@ -0,0 +1,70 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: GPL-2.0 +# Copyright (c) 2025 by Mauro Carvalho Chehab <mchehab@kernel.org>. + +""" +Ancillary argparse HelpFormatter class that works on a similar way as +argparse.RawDescriptionHelpFormatter, e.g. description maintains line +breaks, but it also implement transformations to the help text. The +actual transformations ar given by enrich_text(), if the output is tty. + +Currently, the follow transformations are done: + + - Positional arguments are shown in upper cases; + - if output is TTY, ``var`` and positional arguments are shown prepended + by an ANSI SGR code. This is usually translated to bold. On some + terminals, like, konsole, this is translated into a colored bold text. +""" + +import argparse +import re +import sys + +class EnrichFormatter(argparse.HelpFormatter): + """ + Better format the output, making easier to identify the positional args + and how they're used at the __doc__ description. + """ + def __init__(self, *args, **kwargs): + """Initialize class and check if is TTY""" + super().__init__(*args, **kwargs) + self._tty = sys.stdout.isatty() + + def enrich_text(self, text): + """Handle ReST markups (currently, only ``foo``)""" + if self._tty and text: + # Replace ``text`` with ANSI SGR (bold) + return re.sub(r'\`\`(.+?)\`\`', + lambda m: f'\033[1m{m.group(1)}\033[0m', text) + return text + + def _fill_text(self, text, width, indent): + """Enrich descriptions with markups on it""" + enriched = self.enrich_text(text) + return "\n".join(indent + line for line in enriched.splitlines()) + + def _format_usage(self, usage, actions, groups, prefix): + """Enrich positional arguments at usage: line""" + + prog = self._prog + parts = [] + + for action in actions: + if action.option_strings: + opt = action.option_strings[0] + if action.nargs != 0: + opt += f" {action.dest.upper()}" + parts.append(f"[{opt}]") + else: + # Positional argument + parts.append(self.enrich_text(f"``{action.dest.upper()}``")) + + usage_text = f"{prefix or 'usage: '} {prog} {' '.join(parts)}\n" + return usage_text + + def _format_action_invocation(self, action): + """Enrich argument names""" + if not action.option_strings: + return self.enrich_text(f"``{action.dest.upper()}``") + + return ", ".join(action.option_strings) |
