1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170
|
# -*- coding: utf-8 -*-
"""HelpFormatter
We have a slightly adjusted HelpFormatter that we use for the manpages.
Author: G.J.J. van den Burg
License: See the LICENSE file.
Copyright: 2021, G.J.J. van den Burg
This file is part of Wilderness.
"""
import argparse
import re
import textwrap
from typing import Dict
from typing import List
from typing import Optional
class HelpFormatter(argparse.HelpFormatter):
def _fill_text(self, text, width, indent):
# Minor change to _fill_text to keep newlines provided by the user in
# the prolog and epilog.
lines = text.splitlines()
new_lines = []
for line in lines:
new_line = textwrap.fill(
line,
width,
initial_indent=indent,
subsequent_indent=indent,
)
new_lines.append(new_line)
new_text = "\n".join(new_lines)
return new_text
def _format_actions_usage(self, actions, groups, return_parts=False):
# find group indices and identify actions in groups
group_actions = set()
inserts = {} # type: Dict[int, str]
for group in groups:
try:
start = actions.index(group._group_actions[0])
except ValueError:
continue
else:
end = start + len(group._group_actions)
if actions[start:end] == group._group_actions:
for action in group._group_actions:
group_actions.add(action)
if not group.required:
if start in inserts:
inserts[start] += " ["
else:
inserts[start] = "["
if end in inserts:
inserts[end] += "]"
else:
inserts[end] = "]"
else:
if start in inserts:
inserts[start] += " ("
else:
inserts[start] = "("
if end in inserts:
inserts[end] += ")"
else:
inserts[end] = ")"
for i in range(start + 1, end):
inserts[i] = "|"
# collect all actions format strings
parts = [] # type: List[Optional[str]]
for i, action in enumerate(actions):
if isinstance(action, argparse._HelpAction):
inserts = {i - 1: inserts[i] for i in inserts}
elif action.help is argparse.SUPPRESS:
parts.append(None)
if inserts.pop(i) == "|":
inserts.pop(i)
elif inserts.get(i + 1) == "|":
inserts.pop(i + 1)
# produce all arg strings
elif not action.option_strings:
default = self._get_default_metavar_for_positional(action)
part = self._format_args(action, default)
# if it's in a group, strip the outer []
if action in group_actions:
if part[0] == "[" and part[-1] == "]":
part = part[1:-1]
else:
if action.nargs == "?":
pass
else:
part = "<%s>" % part
# add the action string to the list
parts.append(part)
# produce the first way to invoke the option in brackets
else:
part = self._format_part(action, group_actions)
# add the action string to the list
parts.append(part)
# insert things at the necessary indices
for i in sorted(inserts, reverse=True):
parts[i:i] = [inserts[i]]
# join all the action items with spaces
text = " ".join([item for item in parts if item is not None])
# clean up separators for mutually exclusive groups
open = r"[\[(]"
close = r"[\])]"
text = re.sub(r"(%s) " % open, r"\1", text)
text = re.sub(r" (%s)" % close, r"\1", text)
text = re.sub(r"%s *%s" % (open, close), r"", text)
text = re.sub(r"\(([^|]*)\)", r"\1", text)
text = text.strip()
if return_parts:
return text, parts
# return the text
return text
def _format_part(self, action, group_actions):
option_string = action.option_strings[0]
# if the Optional doesn't take a value, format is:
# -s or --long
if action.nargs == 0:
if len(action.option_strings) == 2:
part = " | ".join(action.option_strings)
else:
part = action.option_strings[0]
elif option_string.startswith("--"): # TODO: get prefix from parser
default = self._get_default_metavar_for_optional(action)
args_string = self._format_args(action, default)
if args_string.startswith("["):
part = "%s[=%s" % (option_string, args_string[1:])
else:
part = "%s=%s" % (option_string, args_string)
elif len(action.option_strings) == 2:
default = self._get_default_metavar_for_optional(action)
args_string = self._format_args(action, default)
part0 = "%s %s" % (action.option_strings[0], args_string)
part1 = "%s=%s" % (action.option_strings[1], args_string)
part = "%s | %s" % (part0, part1)
# if the Optional takes a value, format is:
# -s ARGS or --long ARGS
else:
default = self._get_default_metavar_for_optional(action)
args_string = self._format_args(action, default)
part = "%s %s" % (option_string, args_string)
# make it look optional if it's not required or in a group
if not action.required and action not in group_actions:
part = "[%s]" % part
return part
|