mirror of
https://github.com/python/cpython.git
synced 2026-05-06 04:37:33 -04:00
gh-142389: Add support for backtick colorisation in argparse help text (#149375)
Co-authored-by: Savannah Ostrowski <savannah@python.org>
This commit is contained in:
committed by
GitHub
parent
ef6f0635ce
commit
ffe050ad9b
@@ -637,25 +637,22 @@ are set.
|
||||
|
||||
.. versionadded:: 3.14
|
||||
|
||||
To highlight inline code in your description or epilog text, you can use
|
||||
backticks::
|
||||
To highlight inline code in your description, epilog, or argument ``help``
|
||||
text, you can use single or double backticks::
|
||||
|
||||
>>> parser = argparse.ArgumentParser(
|
||||
... formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
... description='Run ``python -m myapp`` to start.',
|
||||
... epilog='''Examples:
|
||||
... `python -m myapp --verbose`
|
||||
... `python -m myapp --config settings.json`
|
||||
... ``python -m myapp --config settings.json``
|
||||
... ''')
|
||||
>>> parser.add_argument('--foo', help='set the `foo` value')
|
||||
|
||||
When colors are enabled, the text inside backticks will be displayed in a
|
||||
distinct color to help examples stand out. When colors are disabled, backticks
|
||||
are preserved as-is, which is readable in plain text.
|
||||
|
||||
.. note::
|
||||
|
||||
Backtick markup only applies to description and epilog text. It does not
|
||||
apply to individual argument ``help`` strings.
|
||||
|
||||
.. versionadded:: 3.15
|
||||
|
||||
|
||||
|
||||
@@ -756,10 +756,14 @@ argparse
|
||||
default to ``True``. This enables suggestions for mistyped arguments by default.
|
||||
(Contributed by Jakob Schluse in :gh:`140450`.)
|
||||
|
||||
* Added backtick markup support in description and epilog text to highlight
|
||||
inline code when color output is enabled.
|
||||
* Added backtick markup support in :class:`~argparse.ArgumentParser` description
|
||||
and epilog text to highlight inline code when color output is enabled.
|
||||
(Contributed by Savannah Ostrowski in :gh:`142390`.)
|
||||
|
||||
* Extended backtick markup to argument ``help`` text and added support for
|
||||
double backticks (RST inline-literal style).
|
||||
(Contributed by Hugo van Kemenade in :gh:`149375`.)
|
||||
|
||||
|
||||
array
|
||||
-----
|
||||
|
||||
+7
-5
@@ -529,7 +529,7 @@ class HelpFormatter(object):
|
||||
"""Apply color markup to text.
|
||||
|
||||
Supported markup:
|
||||
`...` - inline code (rendered with prog_extra color)
|
||||
`...` or ``...`` - inline code (rendered with prog_extra color)
|
||||
|
||||
When colors are disabled, backticks are preserved as-is.
|
||||
"""
|
||||
@@ -537,8 +537,8 @@ class HelpFormatter(object):
|
||||
if not t.reset:
|
||||
return text
|
||||
text = _re.sub(
|
||||
r'`([^`]+)`',
|
||||
rf'{t.prog_extra}\1{t.reset}',
|
||||
r'(`{1,2})([^`]+)\1',
|
||||
rf'{t.prog_extra}\2{t.reset}',
|
||||
text,
|
||||
)
|
||||
return text
|
||||
@@ -682,7 +682,7 @@ class HelpFormatter(object):
|
||||
def _expand_help(self, action):
|
||||
help_string = self._get_help_string(action)
|
||||
if '%' not in help_string:
|
||||
return help_string
|
||||
return self._apply_text_markup(help_string)
|
||||
params = dict(vars(action), prog=self._prog)
|
||||
for name in list(params):
|
||||
value = params[name]
|
||||
@@ -726,7 +726,9 @@ class HelpFormatter(object):
|
||||
# bare %s etc. - format with full params dict, no colorization
|
||||
return spec % params
|
||||
|
||||
return _re.sub(fmt_spec, colorize, help_string, flags=_re.VERBOSE)
|
||||
return self._apply_text_markup(
|
||||
_re.sub(fmt_spec, colorize, help_string, flags=_re.VERBOSE)
|
||||
)
|
||||
|
||||
def _iter_indented_subactions(self, action):
|
||||
try:
|
||||
|
||||
@@ -7620,21 +7620,25 @@ class TestColorized(TestCase):
|
||||
parser = argparse.ArgumentParser(
|
||||
prog='PROG',
|
||||
color=True,
|
||||
description='Run `python -m myapp` to start.',
|
||||
description='Run `python myapp` or ``python -m myapp`` to start.',
|
||||
)
|
||||
|
||||
prog_extra = self.theme.prog_extra
|
||||
reset = self.theme.reset
|
||||
|
||||
help_text = parser.format_help()
|
||||
self.assertIn(f'Run {prog_extra}python -m myapp{reset} to start.',
|
||||
help_text)
|
||||
self.assertIn(
|
||||
f'Run {prog_extra}python myapp{reset} or '
|
||||
f'{prog_extra}python -m myapp{reset} to start.',
|
||||
help_text,
|
||||
)
|
||||
self.assertNotIn("`", help_text)
|
||||
|
||||
def test_backtick_markup_multiple(self):
|
||||
parser = argparse.ArgumentParser(
|
||||
prog='PROG',
|
||||
color=True,
|
||||
epilog='Try `app run` or `app test`.',
|
||||
epilog='Try `app run` or ``app test``.',
|
||||
)
|
||||
|
||||
prog_extra = self.theme.prog_extra
|
||||
@@ -7643,17 +7647,19 @@ class TestColorized(TestCase):
|
||||
help_text = parser.format_help()
|
||||
self.assertIn(f'{prog_extra}app run{reset}', help_text)
|
||||
self.assertIn(f'{prog_extra}app test{reset}', help_text)
|
||||
self.assertNotIn('`', help_text)
|
||||
|
||||
def test_backtick_markup_not_applied_when_color_disabled(self):
|
||||
# When color is disabled, backticks are preserved as-is
|
||||
parser = argparse.ArgumentParser(
|
||||
prog='PROG',
|
||||
color=False,
|
||||
epilog='Example: `python -m myapp`',
|
||||
epilog='Examples: `python -m myapp` or ``python -m myapp --x``',
|
||||
)
|
||||
|
||||
help_text = parser.format_help()
|
||||
self.assertIn('`python -m myapp`', help_text)
|
||||
self.assertIn('``python -m myapp --x``', help_text)
|
||||
self.assertNotIn('\x1b[', help_text)
|
||||
|
||||
def test_backtick_markup_with_format_string(self):
|
||||
@@ -7696,6 +7702,39 @@ class TestColorized(TestCase):
|
||||
help_text = parser.format_help()
|
||||
self.assertIn(f'{prog_extra}grep "foo.*bar" | sort{reset}', help_text)
|
||||
|
||||
def test_backtick_markup_in_argument_help(self):
|
||||
parser = argparse.ArgumentParser(prog="PROG", color=True)
|
||||
parser.add_argument("--foo", help="set the `foo` value")
|
||||
parser.add_argument("--bar", help="set the ``bar`` value")
|
||||
|
||||
prog_extra = self.theme.prog_extra
|
||||
reset = self.theme.reset
|
||||
|
||||
help_text = parser.format_help()
|
||||
self.assertIn(f"set the {prog_extra}foo{reset} value", help_text)
|
||||
self.assertIn(f"set the {prog_extra}bar{reset} value", help_text)
|
||||
self.assertNotIn("`", help_text)
|
||||
|
||||
def test_backtick_markup_in_argument_help_with_format(self):
|
||||
parser = argparse.ArgumentParser(prog="PROG", color=True)
|
||||
parser.add_argument(
|
||||
"--foo", default="bar", help="set `foo` (default: %(default)s)"
|
||||
)
|
||||
|
||||
prog_extra = self.theme.prog_extra
|
||||
reset = self.theme.reset
|
||||
|
||||
help_text = parser.format_help()
|
||||
self.assertIn(f"set {prog_extra}foo{reset}", help_text)
|
||||
|
||||
def test_backtick_markup_in_argument_help_color_disabled(self):
|
||||
parser = argparse.ArgumentParser(prog="PROG", color=False)
|
||||
parser.add_argument("--foo", help="set the `foo` value")
|
||||
|
||||
help_text = parser.format_help()
|
||||
self.assertIn("set the `foo` value", help_text)
|
||||
self.assertNotIn("\x1b[", help_text)
|
||||
|
||||
def test_help_with_format_specifiers(self):
|
||||
# GH-142950: format specifiers like %x should work with color=True
|
||||
parser = argparse.ArgumentParser(prog='PROG', color=True)
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
Add backtick markup support in :mod:`argparse` option help text to highlight
|
||||
inline code when color output is enabled. Patch by Hugo van Kemenade.
|
||||
Reference in New Issue
Block a user