Skip to content

Instantly share code, notes, and snippets.

@JujuDel
Last active June 23, 2022 06:19
Show Gist options
  • Save JujuDel/1a13eb24cf8472cb07161eec2a886be3 to your computer and use it in GitHub Desktop.
Save JujuDel/1a13eb24cf8472cb07161eec2a886be3 to your computer and use it in GitHub Desktop.
Colorfull argparse formatter
import argparse
import os
import re
# User-friendly console display colors
# In case of f-formating alignment, str.rjust, str.ljust or str.center,
# be aware of their len even if you won't see then while printing
os.system("")
class bcolors:
PINK = '\033[95m' # len -> 5
PURPLE = '\033[94m' # len -> 5
CYAN = '\033[96m' # len -> 5
GREY = '\033[92m' # len -> 5
GREEN = '\033[32m' # len -> 5
YELLOW = '\033[93m' # len -> 5
RED = '\033[91m' # len -> 5
ENDC = '\033[0m' # len -> 4
BOLD = '\033[1m' # len -> 4
UNDERLINE = '\033[4m' # len -> 4
# ######################################### #
# #
# ARGS #
# #
# ######################################### #
class CustomFormatter(argparse.ArgumentDefaultsHelpFormatter, argparse.RawTextHelpFormatter):
"""
This class allows the usage of multiple formatter at once as a formatter_class of the ArgumentParser.
It also reimplement the `format_help` method.
"""
def format_help(self) -> str:
"""
Format the message
:return: the formatted message
"""
help = self._root_section.format_help()
if help:
help = self._long_break_matcher.sub('\n\n', help)
help = help.strip('\n') + '\n'
help = re.sub(r"[Pp]ositional arguments:", f"{bcolors.RED}Positional Arguments{bcolors.ENDC}:", help)
help = re.sub(r"[Oo]ptional arguments:", f"{bcolors.RED}Optional Arguments{bcolors.ENDC}:", help)
# Add color around parameters
# Regex explained:
# \1 -> ' ' or '['
# \2 -> '-' or '--'
# \3 -> contains only english letters or '_'
# \4 -> ' ' or ']' or ',' or '.'
help = re.sub(r"([\s\[])(-{1,2})([a-zA-Z_]+)([\s\],\.])", rf"\1{bcolors.YELLOW}\2\3{bcolors.ENDC}\4", help)
# Add color around default
# Regex explained:
# \1 -> '(default: '
# \2 -> anything
# ends with ')'
help = re.sub(r"(\(default:\s)(.*)\)", rf"{bcolors.YELLOW}\1\2){bcolors.ENDC}", help)
return help
def get_args() -> argparse.ArgumentParser:
"""
Get the command line arguments.
:return: parser, the resulting argument parser.
"""
parser = argparse.ArgumentParser(description=f"Here is the {bcolors.CYAN}description{bcolors.ENDC} of this script.\n" + \
f"With this class formatter, you can do the following:\n" + \
f" - using newlines with '\\n' in your argparse description {bcolors.UNDERLINE}and{bcolors.ENDC} in your parameters' help messages\n" + \
f" - printing the default value of your {bcolors.YELLOW}parameters{bcolors.ENDC}\n" + \
f" - adding some colors as coded in the method `{bcolors.BOLD}format_help{bcolors.ENDC}`",
formatter_class=CustomFormatter)
parser.add_argument(
"-a", "--arg_one", type=str, required=True, help="This is a required parameter, not like --arg_two, which is optional"
)
parser.add_argument(
"-b", "--arg_two", type=str, default="valhalla", help="This is an optinal parameter.\nNot setting it will result in using the default value"
)
parser.add_argument(
"-c", "--arg_three", action="store_true", help="Another type of parameter"
)
return parser
def sum_up(args: argparse.Namespace) -> None:
"""
Print the sum-up of the arguments parsed by this script
:Args:
args: the parsed arguments.
"""
# Params will be colorized, so size + 5 (yellow) + 4 (endc)
size_param = max(len(param) for param in args.__dict__.keys()) + 9
print(f'Sum-up of the script\'s {bcolors.YELLOW}arguments{bcolors.ENDC}:')
for param, value in args.__dict__.items():
print(f' - %{size_param}s: %s'%(f"{bcolors.YELLOW}{param}{bcolors.ENDC}", value))
# ######################################### #
# #
# MAIN #
# #
# ######################################### #
def main() -> None:
"""
Main function
"""
# Parse the arguments
args = get_args().parse_args()
# Sum-up the arguments
sum_up(args)
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment