1#!/usr/bin/env python3 2# SPDX-License-Identifier: GPL-2.0 3# Copyright (c) 2025 by Mauro Carvalho Chehab <mchehab@kernel.org>. 4 5""" 6Ancillary argparse HelpFormatter class that works on a similar way as 7argparse.RawDescriptionHelpFormatter, e.g. description maintains line 8breaks, but it also implement transformations to the help text. The 9actual transformations ar given by enrich_text(), if the output is tty. 10 11Currently, the follow transformations are done: 12 13 - Positional arguments are shown in upper cases; 14 - if output is TTY, ``var`` and positional arguments are shown prepended 15 by an ANSI SGR code. This is usually translated to bold. On some 16 terminals, like, konsole, this is translated into a colored bold text. 17""" 18 19import argparse 20import re 21import sys 22 23class EnrichFormatter(argparse.HelpFormatter): 24 """ 25 Better format the output, making easier to identify the positional args 26 and how they're used at the __doc__ description. 27 """ 28 def __init__(self, *args, **kwargs): 29 """ 30 Initialize class and check if is TTY. 31 """ 32 super().__init__(*args, **kwargs) 33 self._tty = sys.stdout.isatty() 34 35 def enrich_text(self, text): 36 r""" 37 Handle ReST markups (currently, only \`\`text\`\` markups). 38 """ 39 if self._tty and text: 40 # Replace ``text`` with ANSI SGR (bold) 41 return re.sub(r'\`\`(.+?)\`\`', 42 lambda m: f'\033[1m{m.group(1)}\033[0m', text) 43 return text 44 45 def _fill_text(self, text, width, indent): 46 """ 47 Enrich descriptions with markups on it. 48 """ 49 enriched = self.enrich_text(text) 50 return "\n".join(indent + line for line in enriched.splitlines()) 51 52 def _format_usage(self, usage, actions, groups, prefix): 53 """ 54 Enrich positional arguments at usage: line. 55 """ 56 57 prog = self._prog 58 parts = [] 59 60 for action in actions: 61 if action.option_strings: 62 opt = action.option_strings[0] 63 if action.nargs != 0: 64 opt += f" {action.dest.upper()}" 65 parts.append(f"[{opt}]") 66 else: 67 # Positional argument 68 parts.append(self.enrich_text(f"``{action.dest.upper()}``")) 69 70 usage_text = f"{prefix or 'usage: '} {prog} {' '.join(parts)}\n" 71 return usage_text 72 73 def _format_action_invocation(self, action): 74 """ 75 Enrich argument names. 76 """ 77 if not action.option_strings: 78 return self.enrich_text(f"``{action.dest.upper()}``") 79 80 return ", ".join(action.option_strings) 81