@@ -231,38 +231,21 @@ def get_choices(self) -> Choices:
231231from collections .abc import (
232232 Callable ,
233233 Iterable ,
234- Iterator ,
235234 Sequence ,
236235)
237236from typing import (
238237 TYPE_CHECKING ,
239238 Any ,
240- ClassVar ,
241239 NoReturn ,
242240 cast ,
243241)
244242
245- from rich .console import (
246- Console ,
247- ConsoleOptions ,
248- Group ,
249- RenderableType ,
250- RenderResult ,
251- )
243+ from rich .console import RenderableType
252244from rich .table import Column
253- from rich .text import Text
254- from rich_argparse import (
255- ArgumentDefaultsRichHelpFormatter ,
256- MetavarTypeRichHelpFormatter ,
257- RawDescriptionRichHelpFormatter ,
258- RawTextRichHelpFormatter ,
259- RichHelpFormatter ,
260- )
261245
262246from . import constants
263- from . import rich_utils as ru
264247from .completion import CompletionItem
265- from .rich_utils import Cmd2RichArgparseConsole
248+ from .rich_utils import Cmd2HelpFormatter
266249from .styles import Cmd2Style
267250from .types import (
268251 CmdOrSetT ,
@@ -512,230 +495,6 @@ def _ActionsContainer_add_argument( # noqa: N802
512495argparse ._ActionsContainer .add_argument = _ActionsContainer_add_argument # type: ignore[method-assign]
513496
514497
515- ############################################################################################################
516- # Unless otherwise noted, everything below this point are copied from Python's
517- # argparse implementation with minor tweaks to adjust output.
518- # Changes are noted if it's buried in a block of copied code. Otherwise the
519- # function will check for a special case and fall back to the parent function
520- ############################################################################################################
521-
522-
523- class Cmd2HelpFormatter (RichHelpFormatter ):
524- """Custom help formatter to configure ordering of help text."""
525-
526- # Disable automatic highlighting in the help text.
527- highlights : ClassVar [list [str ]] = []
528-
529- # Disable markup rendering in usage, help, description, and epilog text.
530- # cmd2's built-in commands do not escape opening brackets in their help text
531- # and therefore rely on these settings being False. If you desire to use
532- # markup in your help text, inherit from Cmd2HelpFormatter and override
533- # these settings in that child class.
534- usage_markup : ClassVar [bool ] = False
535- help_markup : ClassVar [bool ] = False
536- text_markup : ClassVar [bool ] = False
537-
538- def __init__ (
539- self ,
540- prog : str ,
541- indent_increment : int = 2 ,
542- max_help_position : int = 24 ,
543- width : int | None = None ,
544- * ,
545- console : Cmd2RichArgparseConsole | None = None ,
546- ** kwargs : Any ,
547- ) -> None :
548- """Initialize Cmd2HelpFormatter."""
549- super ().__init__ (prog , indent_increment , max_help_position , width , console = console , ** kwargs )
550-
551- # Recast to assist type checkers
552- self ._console : Cmd2RichArgparseConsole | None
553-
554- @property # type: ignore[override]
555- def console (self ) -> Cmd2RichArgparseConsole :
556- """Return our console instance."""
557- if self ._console is None :
558- self ._console = Cmd2RichArgparseConsole ()
559- return self ._console
560-
561- @console .setter
562- def console (self , console : Cmd2RichArgparseConsole ) -> None :
563- """Set our console instance."""
564- self ._console = console
565-
566- def __rich_console__ (self , console : Console , options : ConsoleOptions ) -> RenderResult :
567- """Provide this help formatter to renderables via the console."""
568- if isinstance (console , Cmd2RichArgparseConsole ):
569- old_formatter = console .help_formatter
570- console .help_formatter = self
571- try :
572- yield from super ().__rich_console__ (console , options )
573- finally :
574- console .help_formatter = old_formatter
575- else :
576- # Handle rendering on a console type other than Cmd2RichArgparseConsole.
577- # In this case, we don't set the help_formatter on the console.
578- yield from super ().__rich_console__ (console , options )
579-
580- def _set_color (self , color : bool , ** kwargs : Any ) -> None :
581- """Set the color for the help output.
582-
583- This override is needed because Python 3.15 added a 'file' keyword argument
584- to _set_color() which some versions of RichHelpFormatter don't support.
585- """
586- # Argparse didn't add color support until 3.14
587- if sys .version_info < (3 , 14 ):
588- return
589-
590- try : # type: ignore[unreachable]
591- super ()._set_color (color , ** kwargs )
592- except TypeError :
593- # Fallback for older versions of RichHelpFormatter that don't support keyword arguments
594- super ()._set_color (color )
595-
596- def _build_nargs_range_str (self , nargs_range : tuple [int , int | float ]) -> str :
597- """Build nargs range string for help text."""
598- if nargs_range [1 ] == constants .INFINITY :
599- # {min+}
600- range_str = f"{{{ nargs_range [0 ]} +}}"
601- else :
602- # {min..max}
603- range_str = f"{{{ nargs_range [0 ]} ..{ nargs_range [1 ]} }}"
604-
605- return range_str
606-
607- def _format_args (self , action : argparse .Action , default_metavar : str ) -> str :
608- """Override to handle cmd2's custom nargs formatting.
609-
610- All formats in this function need to be handled by _rich_metavar_parts().
611- """
612- get_metavar = self ._metavar_formatter (action , default_metavar )
613-
614- # Handle nargs specified as a range
615- nargs_range = action .get_nargs_range () # type: ignore[attr-defined]
616- if nargs_range is not None :
617- arg_str = '%s' % get_metavar (1 ) # noqa: UP031
618- range_str = self ._build_nargs_range_str (nargs_range )
619- return f"{ arg_str } { range_str } "
620-
621- # When nargs is just a number, argparse repeats the arg in the help text.
622- # For instance, when nargs=5 the help text looks like: 'command arg arg arg arg arg'.
623- # To make this less verbose, format it like: 'command arg{5}'.
624- # Do not customize the output when metavar is a tuple of strings. Allow argparse's
625- # formatter to handle that instead.
626- if not isinstance (action .metavar , tuple ) and isinstance (action .nargs , int ) and action .nargs > 1 :
627- arg_str = '%s' % get_metavar (1 ) # noqa: UP031
628- return f"{ arg_str } {{{ action .nargs } }}"
629-
630- # Fallback to parent for all other cases
631- return super ()._format_args (action , default_metavar )
632-
633- def _rich_metavar_parts (
634- self ,
635- action : argparse .Action ,
636- default_metavar : str ,
637- ) -> Iterator [tuple [str , bool ]]:
638- """Override to handle all cmd2-specific formatting in _format_args()."""
639- get_metavar = self ._metavar_formatter (action , default_metavar )
640-
641- # Handle nargs specified as a range
642- nargs_range = action .get_nargs_range () # type: ignore[attr-defined]
643- if nargs_range is not None :
644- yield "%s" % get_metavar (1 ), True # noqa: UP031
645- yield self ._build_nargs_range_str (nargs_range ), False
646- return
647-
648- # Handle specific integer nargs (e.g., nargs=5 -> arg{5})
649- if not isinstance (action .metavar , tuple ) and isinstance (action .nargs , int ) and action .nargs > 1 :
650- yield "%s" % get_metavar (1 ), True # noqa: UP031
651- yield f"{{{ action .nargs } }}" , False
652- return
653-
654- # Fallback to parent for all other cases
655- yield from super ()._rich_metavar_parts (action , default_metavar )
656-
657-
658- class RawDescriptionCmd2HelpFormatter (
659- RawDescriptionRichHelpFormatter ,
660- Cmd2HelpFormatter ,
661- ):
662- """Cmd2 help message formatter which retains any formatting in descriptions and epilogs."""
663-
664-
665- class RawTextCmd2HelpFormatter (
666- RawTextRichHelpFormatter ,
667- Cmd2HelpFormatter ,
668- ):
669- """Cmd2 help message formatter which retains formatting of all help text."""
670-
671-
672- class ArgumentDefaultsCmd2HelpFormatter (
673- ArgumentDefaultsRichHelpFormatter ,
674- Cmd2HelpFormatter ,
675- ):
676- """Cmd2 help message formatter which adds default values to argument help."""
677-
678-
679- class MetavarTypeCmd2HelpFormatter (
680- MetavarTypeRichHelpFormatter ,
681- Cmd2HelpFormatter ,
682- ):
683- """Cmd2 help message formatter which uses the argument 'type' as the default
684- metavar value (instead of the argument 'dest').
685- """ # noqa: D205
686-
687-
688- class TextGroup :
689- """A block of text which is formatted like an argparse argument group, including a title.
690-
691- Title:
692- Here is the first row of text.
693- Here is yet another row of text.
694- """
695-
696- def __init__ (
697- self ,
698- title : str ,
699- text : RenderableType ,
700- ) -> None :
701- """TextGroup initializer.
702-
703- :param title: the group's title
704- :param text: the group's text (string or object that may be rendered by Rich)
705- """
706- self .title = title
707- self .text = text
708-
709- def __rich_console__ (self , console : Console , options : ConsoleOptions ) -> RenderResult :
710- """Return a renderable Rich Group object for the class instance.
711-
712- This method formats the title and indents the text to match argparse
713- group styling, making the object displayable by a Rich console.
714- """
715- formatter : Cmd2HelpFormatter | None = None
716- if isinstance (console , Cmd2RichArgparseConsole ):
717- formatter = console .help_formatter
718-
719- # This occurs if the console is not a Cmd2RichArgparseConsole or if the
720- # TextGroup is printed directly instead of as part of an argparse help message.
721- if formatter is None :
722- # If console is the wrong type, then have Cmd2HelpFormatter create its own.
723- formatter = Cmd2HelpFormatter (
724- prog = "" ,
725- console = console if isinstance (console , Cmd2RichArgparseConsole ) else None ,
726- )
727-
728- styled_title = Text (
729- type (formatter ).group_name_formatter (f"{ self .title } :" ),
730- style = formatter .styles ["argparse.groups" ],
731- )
732-
733- # Indent text like an argparse argument group does
734- indented_text = ru .indent (self .text , formatter ._indent_increment )
735-
736- yield Group (styled_title , indented_text )
737-
738-
739498class Cmd2ArgumentParser (argparse .ArgumentParser ):
740499 """Custom ArgumentParser class that improves error and help output."""
741500
0 commit comments