2121 overload ,
2222)
2323
24+ from . import string_utils as su
25+
2426if TYPE_CHECKING : # pragma: no cover
2527 from .cmd2 import Cmd
2628 from .command_definition import CommandSet
@@ -64,15 +66,22 @@ class CompletionItem:
6466 text : str = ""
6567
6668 # Optional string for displaying the completion differently in the completion menu.
69+ # This can contain ANSI style sequences. A plain version is stored in display_plain.
6770 display : str = ""
6871
6972 # Optional meta information about completion which displays in the completion menu.
73+ # This can contain ANSI style sequences. A plain version is stored in display_meta_plain.
7074 display_meta : str = ""
7175
7276 # Optional row data for completion tables. Length must match the associated argparse
7377 # argument's table_header. This is stored internally as a tuple.
7478 table_row : Sequence [Any ] = field (default_factory = tuple )
7579
80+ # Plain text versions of display fields (stripped of ANSI) for sorting/filtering.
81+ # These are set in __post_init__().
82+ display_plain : str = field (init = False )
83+ display_meta_plain : str = field (init = False )
84+
7685 def __post_init__ (self ) -> None :
7786 """Finalize the object after initialization."""
7887 # Derive text from value if it wasn't explicitly provided
@@ -83,6 +92,11 @@ def __post_init__(self) -> None:
8392 if not self .display :
8493 object .__setattr__ (self , "display" , self .text )
8594
95+ # Pre-calculate plain text versions by stripping ANSI sequences.
96+ # These are stored as attributes for fast access during sorting/filtering.
97+ object .__setattr__ (self , "display_plain" , su .strip_style (self .display ))
98+ object .__setattr__ (self , "display_meta_plain" , su .strip_style (self .display_meta ))
99+
86100 # Make sure all table row objects are renderable by a Rich table.
87101 renderable_data = [obj if is_renderable (obj ) else str (obj ) for obj in self .table_row ]
88102
@@ -140,10 +154,10 @@ def __post_init__(self) -> None:
140154 if not self .is_sorted :
141155 if all_display_numeric (unique_items ):
142156 # Sort numerically
143- unique_items .sort (key = lambda item : float (item .display ))
157+ unique_items .sort (key = lambda item : float (item .display_plain ))
144158 else :
145159 # Standard string sort
146- unique_items .sort (key = lambda item : utils .DEFAULT_STR_SORT_KEY (item .display ))
160+ unique_items .sort (key = lambda item : utils .DEFAULT_STR_SORT_KEY (item .display_plain ))
147161
148162 object .__setattr__ (self , "is_sorted" , True )
149163
@@ -247,8 +261,8 @@ class Completions(CompletionResultsBase):
247261
248262
249263def all_display_numeric (items : Collection [CompletionItem ]) -> bool :
250- """Return True if items is non-empty and every item.display is a numeric string."""
251- return bool (items ) and all (NUMERIC_RE .match (item .display ) for item in items )
264+ """Return True if items is non-empty and every item.display_plain value is a numeric string."""
265+ return bool (items ) and all (NUMERIC_RE .match (item .display_plain ) for item in items )
252266
253267
254268#############################################
0 commit comments