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