Skip to content

Commit ffe050a

Browse files
gh-142389: Add support for backtick colorisation in argparse help text (#149375)
Co-authored-by: Savannah Ostrowski <savannah@python.org>
1 parent ef6f063 commit ffe050a

5 files changed

Lines changed: 64 additions & 20 deletions

File tree

Doc/library/argparse.rst

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -637,25 +637,22 @@ are set.
637637

638638
.. versionadded:: 3.14
639639

640-
To highlight inline code in your description or epilog text, you can use
641-
backticks::
640+
To highlight inline code in your description, epilog, or argument ``help``
641+
text, you can use single or double backticks::
642642

643643
>>> parser = argparse.ArgumentParser(
644644
... formatter_class=argparse.RawDescriptionHelpFormatter,
645+
... description='Run ``python -m myapp`` to start.',
645646
... epilog='''Examples:
646647
... `python -m myapp --verbose`
647-
... `python -m myapp --config settings.json`
648+
... ``python -m myapp --config settings.json``
648649
... ''')
650+
>>> parser.add_argument('--foo', help='set the `foo` value')
649651

650652
When colors are enabled, the text inside backticks will be displayed in a
651653
distinct color to help examples stand out. When colors are disabled, backticks
652654
are preserved as-is, which is readable in plain text.
653655

654-
.. note::
655-
656-
Backtick markup only applies to description and epilog text. It does not
657-
apply to individual argument ``help`` strings.
658-
659656
.. versionadded:: 3.15
660657

661658

Doc/whatsnew/3.15.rst

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -756,10 +756,14 @@ argparse
756756
default to ``True``. This enables suggestions for mistyped arguments by default.
757757
(Contributed by Jakob Schluse in :gh:`140450`.)
758758

759-
* Added backtick markup support in description and epilog text to highlight
760-
inline code when color output is enabled.
759+
* Added backtick markup support in :class:`~argparse.ArgumentParser` description
760+
and epilog text to highlight inline code when color output is enabled.
761761
(Contributed by Savannah Ostrowski in :gh:`142390`.)
762762

763+
* Extended backtick markup to argument ``help`` text and added support for
764+
double backticks (RST inline-literal style).
765+
(Contributed by Hugo van Kemenade in :gh:`149375`.)
766+
763767

764768
array
765769
-----

Lib/argparse.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -529,16 +529,16 @@ def _apply_text_markup(self, text):
529529
"""Apply color markup to text.
530530
531531
Supported markup:
532-
`...` - inline code (rendered with prog_extra color)
532+
`...` or ``...`` - inline code (rendered with prog_extra color)
533533
534534
When colors are disabled, backticks are preserved as-is.
535535
"""
536536
t = self._theme
537537
if not t.reset:
538538
return text
539539
text = _re.sub(
540-
r'`([^`]+)`',
541-
rf'{t.prog_extra}\1{t.reset}',
540+
r'(`{1,2})([^`]+)\1',
541+
rf'{t.prog_extra}\2{t.reset}',
542542
text,
543543
)
544544
return text
@@ -682,7 +682,7 @@ def _format_args(self, action, default_metavar):
682682
def _expand_help(self, action):
683683
help_string = self._get_help_string(action)
684684
if '%' not in help_string:
685-
return help_string
685+
return self._apply_text_markup(help_string)
686686
params = dict(vars(action), prog=self._prog)
687687
for name in list(params):
688688
value = params[name]
@@ -726,7 +726,9 @@ def colorize(match):
726726
# bare %s etc. - format with full params dict, no colorization
727727
return spec % params
728728

729-
return _re.sub(fmt_spec, colorize, help_string, flags=_re.VERBOSE)
729+
return self._apply_text_markup(
730+
_re.sub(fmt_spec, colorize, help_string, flags=_re.VERBOSE)
731+
)
730732

731733
def _iter_indented_subactions(self, action):
732734
try:

Lib/test/test_argparse.py

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7620,21 +7620,25 @@ def test_backtick_markup_in_description(self):
76207620
parser = argparse.ArgumentParser(
76217621
prog='PROG',
76227622
color=True,
7623-
description='Run `python -m myapp` to start.',
7623+
description='Run `python myapp` or ``python -m myapp`` to start.',
76247624
)
76257625

76267626
prog_extra = self.theme.prog_extra
76277627
reset = self.theme.reset
76287628

76297629
help_text = parser.format_help()
7630-
self.assertIn(f'Run {prog_extra}python -m myapp{reset} to start.',
7631-
help_text)
7630+
self.assertIn(
7631+
f'Run {prog_extra}python myapp{reset} or '
7632+
f'{prog_extra}python -m myapp{reset} to start.',
7633+
help_text,
7634+
)
7635+
self.assertNotIn("`", help_text)
76327636

76337637
def test_backtick_markup_multiple(self):
76347638
parser = argparse.ArgumentParser(
76357639
prog='PROG',
76367640
color=True,
7637-
epilog='Try `app run` or `app test`.',
7641+
epilog='Try `app run` or ``app test``.',
76387642
)
76397643

76407644
prog_extra = self.theme.prog_extra
@@ -7643,17 +7647,19 @@ def test_backtick_markup_multiple(self):
76437647
help_text = parser.format_help()
76447648
self.assertIn(f'{prog_extra}app run{reset}', help_text)
76457649
self.assertIn(f'{prog_extra}app test{reset}', help_text)
7650+
self.assertNotIn('`', help_text)
76467651

76477652
def test_backtick_markup_not_applied_when_color_disabled(self):
76487653
# When color is disabled, backticks are preserved as-is
76497654
parser = argparse.ArgumentParser(
76507655
prog='PROG',
76517656
color=False,
7652-
epilog='Example: `python -m myapp`',
7657+
epilog='Examples: `python -m myapp` or ``python -m myapp --x``',
76537658
)
76547659

76557660
help_text = parser.format_help()
76567661
self.assertIn('`python -m myapp`', help_text)
7662+
self.assertIn('``python -m myapp --x``', help_text)
76577663
self.assertNotIn('\x1b[', help_text)
76587664

76597665
def test_backtick_markup_with_format_string(self):
@@ -7696,6 +7702,39 @@ def test_backtick_markup_special_regex_chars(self):
76967702
help_text = parser.format_help()
76977703
self.assertIn(f'{prog_extra}grep "foo.*bar" | sort{reset}', help_text)
76987704

7705+
def test_backtick_markup_in_argument_help(self):
7706+
parser = argparse.ArgumentParser(prog="PROG", color=True)
7707+
parser.add_argument("--foo", help="set the `foo` value")
7708+
parser.add_argument("--bar", help="set the ``bar`` value")
7709+
7710+
prog_extra = self.theme.prog_extra
7711+
reset = self.theme.reset
7712+
7713+
help_text = parser.format_help()
7714+
self.assertIn(f"set the {prog_extra}foo{reset} value", help_text)
7715+
self.assertIn(f"set the {prog_extra}bar{reset} value", help_text)
7716+
self.assertNotIn("`", help_text)
7717+
7718+
def test_backtick_markup_in_argument_help_with_format(self):
7719+
parser = argparse.ArgumentParser(prog="PROG", color=True)
7720+
parser.add_argument(
7721+
"--foo", default="bar", help="set `foo` (default: %(default)s)"
7722+
)
7723+
7724+
prog_extra = self.theme.prog_extra
7725+
reset = self.theme.reset
7726+
7727+
help_text = parser.format_help()
7728+
self.assertIn(f"set {prog_extra}foo{reset}", help_text)
7729+
7730+
def test_backtick_markup_in_argument_help_color_disabled(self):
7731+
parser = argparse.ArgumentParser(prog="PROG", color=False)
7732+
parser.add_argument("--foo", help="set the `foo` value")
7733+
7734+
help_text = parser.format_help()
7735+
self.assertIn("set the `foo` value", help_text)
7736+
self.assertNotIn("\x1b[", help_text)
7737+
76997738
def test_help_with_format_specifiers(self):
77007739
# GH-142950: format specifiers like %x should work with color=True
77017740
parser = argparse.ArgumentParser(prog='PROG', color=True)
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Add backtick markup support in :mod:`argparse` option help text to highlight
2+
inline code when color output is enabled. Patch by Hugo van Kemenade.

0 commit comments

Comments
 (0)