diff --git a/CHANGELOG.md b/CHANGELOG.md index f4f96de4..500079f1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +## 2.7.0 (TBD) + +- Enhancements + - Integrated rich-argparse with cmd2's default argparse help formatter. + ## 2.6.2 (June 26, 2025) - Enhancements diff --git a/cmd2/argparse_custom.py b/cmd2/argparse_custom.py index 01eea688..d67ccbe8 100644 --- a/cmd2/argparse_custom.py +++ b/cmd2/argparse_custom.py @@ -229,14 +229,17 @@ def my_completer(self, text, line, begidx, endidx, arg_tokens) ZERO_OR_MORE, ArgumentError, ) -from collections.abc import Callable, Iterable, Sequence -from gettext import ( - gettext, +from collections.abc import ( + Callable, + Iterable, + Sequence, ) +from gettext import gettext from typing import ( IO, TYPE_CHECKING, Any, + ClassVar, NoReturn, Optional, Protocol, @@ -245,6 +248,8 @@ def my_completer(self, text, line, begidx, endidx, arg_tokens) runtime_checkable, ) +from rich_argparse import RawTextRichHelpFormatter + from . import ( ansi, constants, @@ -991,9 +996,25 @@ def _SubParsersAction_remove_parser(self: argparse._SubParsersAction, name: str) ############################################################################################################ -class Cmd2HelpFormatter(argparse.RawTextHelpFormatter): +class Cmd2HelpFormatter(RawTextRichHelpFormatter): """Custom help formatter to configure ordering of help text.""" + # rich-argparse formats all group names with str.title(). + # Override their formatter to do nothing. + group_name_formatter: ClassVar[Callable[[str], str]] = str + + # Disable automatic highlighting in the help text. + highlights: ClassVar[list[str]] = [] + + # Disable markup rendering in usage, help, description, and epilog text. + # cmd2's built-in commands do not escape opening brackets in their help text + # and therefore rely on these settings being False. If you desire to use + # markup in your help text, inherit from Cmd2HelpFormatter and override + # these settings in that child class. + usage_markup: ClassVar[bool] = False + help_markup: ClassVar[bool] = False + text_markup: ClassVar[bool] = False + def _format_usage( self, usage: Optional[str], diff --git a/cmd2/cmd2.py b/cmd2/cmd2.py index de2ae157..898aad07 100644 --- a/cmd2/cmd2.py +++ b/cmd2/cmd2.py @@ -42,14 +42,16 @@ import sys import tempfile import threading -from code import ( - InteractiveConsole, -) +from code import InteractiveConsole from collections import ( OrderedDict, namedtuple, ) -from collections.abc import Callable, Iterable, Mapping +from collections.abc import ( + Callable, + Iterable, + Mapping, +) from types import ( FrameType, ModuleType, @@ -763,8 +765,8 @@ def _build_parser( """Build argument parser for a command/subcommand. :param parent: CommandParent object which owns the command using the parser. - This function assumes that parent is where parser_builder - is defined when parser_builder is a classmethod. + When parser_builder is a classmethod, this function passes + parent's class to it. :param parser_builder: means used to build the parser :param prog: prog value to set in new parser :return: new parser @@ -781,9 +783,7 @@ def _build_parser( else: raise TypeError(f"Invalid type for parser_builder: {type(parser_builder)}") - from .decorators import ( - _set_parser_prog, - ) + from .decorators import _set_parser_prog _set_parser_prog(parser, prog) diff --git a/pyproject.toml b/pyproject.toml index 163f5e42..4794983f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -32,6 +32,7 @@ dependencies = [ "gnureadline>=8; platform_system == 'Darwin'", "pyperclip>=1.8", "pyreadline3>=3.4; platform_system == 'Windows'", + "rich-argparse>=1.7.1", "wcwidth>=0.2.10", ]