mirror of
https://github.com/torvalds/linux.git
synced 2025-11-30 23:16:01 +07:00
tools: docs: parse-headers.py: move it from sphinx dir
As suggested by Jon, we should start having a tools/docs directory, instead of placing everything under scripts. In the specific case of parse-headers.py, the previous location is where we're placing Sphinx extensions, which is not the right place for execs. Move it to tools/docs/parse-headers.py. Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org> Signed-off-by: Jonathan Corbet <corbet@lwn.net> Link: https://lore.kernel.org/r/0f5ac2d704cffe9834e589b39549d2393e1237ef.1755872208.git.mchehab+huawei@kernel.org
This commit is contained in:
committed by
Jonathan Corbet
parent
37497a4dc5
commit
cde494660f
@@ -1,2 +1,2 @@
|
||||
[MASTER]
|
||||
init-hook='import sys; sys.path += ["scripts/lib/kdoc", "scripts/lib/abi"]'
|
||||
init-hook='import sys; sys.path += ["scripts/lib/kdoc", "scripts/lib/abi", "tools/docs/lib"]'
|
||||
|
||||
0
tools/docs/lib/__init__.py
Normal file
0
tools/docs/lib/__init__.py
Normal file
70
tools/docs/lib/enrich_formatter.py
Normal file
70
tools/docs/lib/enrich_formatter.py
Normal file
@@ -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)
|
||||
@@ -1,36 +1,32 @@
|
||||
#!/usr/bin/env python3
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
# Copyright (c) 2016 by Mauro Carvalho Chehab <mchehab@kernel.org>.
|
||||
# pylint: disable=C0103,R0902,R0912,R0914,R0915
|
||||
# Copyright (c) 2016-2025 by Mauro Carvalho Chehab <mchehab@kernel.org>.
|
||||
# pylint: disable=R0912,R0915
|
||||
|
||||
"""
|
||||
Convert a C header or source file ``FILE_IN``, into a ReStructured Text
|
||||
included via ..parsed-literal block with cross-references for the
|
||||
documentation files that describe the API. It accepts an optional
|
||||
``FILE_RULES`` file to describes what elements will be either ignored or
|
||||
be pointed to a non-default reference type/name.
|
||||
Parse a source file or header, creating ReStructured Text cross references.
|
||||
|
||||
The output is written at ``FILE_OUT``.
|
||||
It accepts an optional file to change the default symbol reference or to
|
||||
suppress symbols from the output.
|
||||
|
||||
It is capable of identifying defines, functions, structs, typedefs,
|
||||
enums and enum symbols and create cross-references for all of them.
|
||||
It is also capable of distinguish #define used for specifying a Linux
|
||||
ioctl.
|
||||
|
||||
The optional ``FILE_RULES`` contains a set of rules like:
|
||||
The optional rules file contains a set of rules like:
|
||||
|
||||
ignore ioctl VIDIOC_ENUM_FMT
|
||||
replace ioctl VIDIOC_DQBUF vidioc_qbuf
|
||||
replace define V4L2_EVENT_MD_FL_HAVE_FRAME_SEQ :c:type:`v4l2_event_motion_det`
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
|
||||
|
||||
class ParseHeader:
|
||||
class ParseDataStructs:
|
||||
"""
|
||||
Creates an enriched version of a Kernel header file with cross-links
|
||||
to each C data structure type.
|
||||
@@ -400,80 +396,3 @@ class ParseHeader:
|
||||
f.write("=" * len(title))
|
||||
f.write("\n\n.. parsed-literal::\n\n")
|
||||
f.write(text)
|
||||
|
||||
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 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()}``")
|
||||
else:
|
||||
return ", ".join(action.option_strings)
|
||||
|
||||
|
||||
def main():
|
||||
"""Main function"""
|
||||
parser = argparse.ArgumentParser(description=__doc__,
|
||||
formatter_class=EnrichFormatter)
|
||||
|
||||
parser.add_argument("-d", "--debug", action="count", default=0,
|
||||
help="Increase debug level. Can be used multiple times")
|
||||
parser.add_argument("file_in", help="Input C file")
|
||||
parser.add_argument("file_out", help="Output RST file")
|
||||
parser.add_argument("file_rules", nargs="?",
|
||||
help="Exceptions file (optional)")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
parser = ParseHeader(debug=args.debug)
|
||||
parser.parse_file(args.file_in)
|
||||
|
||||
if args.file_rules:
|
||||
parser.process_exceptions(args.file_rules)
|
||||
|
||||
parser.debug_print()
|
||||
parser.write_output(args.file_in, args.file_out)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
57
tools/docs/parse-headers.py
Executable file
57
tools/docs/parse-headers.py
Executable file
@@ -0,0 +1,57 @@
|
||||
#!/usr/bin/env python3
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
# Copyright (c) 2016, 2025 by Mauro Carvalho Chehab <mchehab@kernel.org>.
|
||||
# pylint: disable=C0103
|
||||
|
||||
"""
|
||||
Convert a C header or source file ``FILE_IN``, into a ReStructured Text
|
||||
included via ..parsed-literal block with cross-references for the
|
||||
documentation files that describe the API. It accepts an optional
|
||||
``FILE_RULES`` file to describes what elements will be either ignored or
|
||||
be pointed to a non-default reference type/name.
|
||||
|
||||
The output is written at ``FILE_OUT``.
|
||||
|
||||
It is capable of identifying defines, functions, structs, typedefs,
|
||||
enums and enum symbols and create cross-references for all of them.
|
||||
It is also capable of distinguish #define used for specifying a Linux
|
||||
ioctl.
|
||||
|
||||
The optional ``FILE_RULES`` contains a set of rules like:
|
||||
|
||||
ignore ioctl VIDIOC_ENUM_FMT
|
||||
replace ioctl VIDIOC_DQBUF vidioc_qbuf
|
||||
replace define V4L2_EVENT_MD_FL_HAVE_FRAME_SEQ :c:type:`v4l2_event_motion_det`
|
||||
"""
|
||||
|
||||
import argparse
|
||||
|
||||
from lib.parse_data_structs import ParseDataStructs
|
||||
from lib.enrich_formatter import EnrichFormatter
|
||||
|
||||
def main():
|
||||
"""Main function"""
|
||||
parser = argparse.ArgumentParser(description=__doc__,
|
||||
formatter_class=EnrichFormatter)
|
||||
|
||||
parser.add_argument("-d", "--debug", action="count", default=0,
|
||||
help="Increase debug level. Can be used multiple times")
|
||||
parser.add_argument("file_in", help="Input C file")
|
||||
parser.add_argument("file_out", help="Output RST file")
|
||||
parser.add_argument("file_rules", nargs="?",
|
||||
help="Exceptions file (optional)")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
parser = ParseDataStructs(debug=args.debug)
|
||||
parser.parse_file(args.file_in)
|
||||
|
||||
if args.file_rules:
|
||||
parser.process_exceptions(args.file_rules)
|
||||
|
||||
parser.debug_print()
|
||||
parser.write_output(args.file_in, args.file_out)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user