Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 5 additions & 8 deletions Doc/library/argparse.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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


Expand Down
8 changes: 6 additions & 2 deletions Doc/whatsnew/3.15.rst
Original file line number Diff line number Diff line change
Expand Up @@ -715,10 +715,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
-----
Expand Down
12 changes: 7 additions & 5 deletions Lib/argparse.py
Original file line number Diff line number Diff line change
Expand Up @@ -529,16 +529,16 @@ def _apply_text_markup(self, text):
"""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.
"""
t = self._theme
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
Expand Down Expand Up @@ -682,7 +682,7 @@ def _format_args(self, action, default_metavar):
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]
Expand Down Expand Up @@ -726,7 +726,9 @@ def colorize(match):
# 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:
Expand Down
49 changes: 44 additions & 5 deletions Lib/test/test_argparse.py
Original file line number Diff line number Diff line change
Expand Up @@ -7620,21 +7620,25 @@ def test_backtick_markup_in_description(self):
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
Expand All @@ -7643,17 +7647,19 @@ def test_backtick_markup_multiple(self):
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):
Expand Down Expand Up @@ -7696,6 +7702,39 @@ def test_backtick_markup_special_regex_chars(self):
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):
Comment thread
savannahostrowski marked this conversation as resolved.
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)
Expand Down
Original file line number Diff line number Diff line change
@@ -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.
Loading