diff --git a/Doc/library/argparse.rst b/Doc/library/argparse.rst index e37afd6d0b6d5a..db5fae2006678a 100644 --- a/Doc/library/argparse.rst +++ b/Doc/library/argparse.rst @@ -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 diff --git a/Doc/whatsnew/3.15.rst b/Doc/whatsnew/3.15.rst index 3baae534041446..937b31a344b4f5 100644 --- a/Doc/whatsnew/3.15.rst +++ b/Doc/whatsnew/3.15.rst @@ -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 ----- diff --git a/Lib/argparse.py b/Lib/argparse.py index d91707d9eec546..db7f909c320e8d 100644 --- a/Lib/argparse.py +++ b/Lib/argparse.py @@ -529,7 +529,7 @@ 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. """ @@ -537,8 +537,8 @@ def _apply_text_markup(self, text): 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 @@ 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] @@ -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: diff --git a/Lib/test/test_argparse.py b/Lib/test/test_argparse.py index e0c32976fd6f0d..e03f36fbb50ec2 100644 --- a/Lib/test/test_argparse.py +++ b/Lib/test/test_argparse.py @@ -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 @@ -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): @@ -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): + 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) diff --git a/Misc/NEWS.d/next/Library/2026-05-04-18-01-35.gh-issue-142389.4Faqpq.rst b/Misc/NEWS.d/next/Library/2026-05-04-18-01-35.gh-issue-142389.4Faqpq.rst new file mode 100644 index 00000000000000..725f2debe2c615 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-05-04-18-01-35.gh-issue-142389.4Faqpq.rst @@ -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.