7
7
import pytest
8
8
9
9
import cmd2
10
+ import cmd2 .string_utils as su
10
11
from cmd2 import (
11
12
Cmd2ArgumentParser ,
12
13
CompletionError ,
15
16
argparse_custom ,
16
17
with_argparser ,
17
18
)
19
+ from cmd2 import rich_utils as ru
18
20
19
21
from .conftest import (
20
22
complete_tester ,
21
23
normalize ,
22
24
run_cmd ,
25
+ with_ansi_style ,
23
26
)
24
27
25
28
# Data and functions for testing standalone choice_provider and completer
@@ -109,12 +112,18 @@ def do_pos_and_flag(self, args: argparse.Namespace) -> None:
109
112
static_choices_list = ('static' , 'choices' , 'stop' , 'here' )
110
113
choices_from_provider = ('choices' , 'provider' , 'probably' , 'improved' )
111
114
completion_item_choices = (
112
- CompletionItem ('choice_1' , ['A description' ]),
113
- CompletionItem ('choice_2' , ['Another description' ]),
115
+ CompletionItem ('choice_1' , ['Description 1' ]),
116
+ # Make this the longest description so we can test display width.
117
+ CompletionItem ('choice_2' , [su .stylize ("String with style" , style = cmd2 .Color .BLUE )]),
118
+ CompletionItem ('choice_3' , [su .stylize ("Text with style" , style = cmd2 .Color .RED )]),
114
119
)
115
120
116
121
# This tests that CompletionItems created with numerical values are sorted as numbers.
117
- num_completion_items = (CompletionItem (5 , ["Five" ]), CompletionItem (1.5 , ["One.Five" ]), CompletionItem (2 , ["Five" ]))
122
+ num_completion_items = (
123
+ CompletionItem (5 , ["Five" ]),
124
+ CompletionItem (1.5 , ["One.Five" ]),
125
+ CompletionItem (2 , ["Five" ]),
126
+ )
118
127
119
128
def choices_provider (self ) -> tuple [str ]:
120
129
"""Method that provides choices"""
@@ -704,6 +713,7 @@ def test_autocomp_blank_token(ac_app) -> None:
704
713
assert sorted (completions ) == sorted (ArgparseCompleterTester .completions_for_pos_2 )
705
714
706
715
716
+ @with_ansi_style (ru .AllowStyle .ALWAYS )
707
717
def test_completion_items (ac_app ) -> None :
708
718
# First test CompletionItems created from strings
709
719
text = ''
@@ -716,16 +726,20 @@ def test_completion_items(ac_app) -> None:
716
726
assert len (ac_app .completion_matches ) == len (ac_app .completion_item_choices )
717
727
assert len (ac_app .display_matches ) == len (ac_app .completion_item_choices )
718
728
719
- # Look for both the value and description in the hint table
720
- line_found = False
721
- for line in ac_app .formatted_completions .splitlines ():
722
- # Since the CompletionItems were created from strings, the left-most column is left-aligned.
723
- # Therefore choice_1 will begin the line (with 1 space for padding).
724
- if line .startswith (' choice_1' ) and 'A description' in line :
725
- line_found = True
726
- break
729
+ lines = ac_app .formatted_completions .splitlines ()
730
+
731
+ # Since the CompletionItems were created from strings, the left-most column is left-aligned.
732
+ # Therefore choice_1 will begin the line (with 1 space for padding).
733
+ assert lines [2 ].startswith (' choice_1' )
734
+ assert lines [2 ].strip ().endswith ('Description 1' )
735
+
736
+ # Verify that the styled string was converted to a Rich Text object so that
737
+ # Rich could correctly calculate its display width. Since it was the longest
738
+ # description in the table, we should only see one space of padding after it.
739
+ assert lines [3 ].endswith ("\x1b [34mString with style\x1b [0m " )
727
740
728
- assert line_found
741
+ # Verify that the styled Rich Text also rendered.
742
+ assert lines [4 ].endswith ("\x1b [31mText with style\x1b [0m " )
729
743
730
744
# Now test CompletionItems created from numbers
731
745
text = ''
@@ -738,16 +752,12 @@ def test_completion_items(ac_app) -> None:
738
752
assert len (ac_app .completion_matches ) == len (ac_app .num_completion_items )
739
753
assert len (ac_app .display_matches ) == len (ac_app .num_completion_items )
740
754
741
- # Look for both the value and description in the hint table
742
- line_found = False
743
- for line in ac_app .formatted_completions .splitlines ():
744
- # Since the CompletionItems were created from numbers, the left-most column is right-aligned.
745
- # Therefore 1.5 will be right-aligned.
746
- if line .startswith (" 1.5" ) and "One.Five" in line :
747
- line_found = True
748
- break
755
+ lines = ac_app .formatted_completions .splitlines ()
749
756
750
- assert line_found
757
+ # Since the CompletionItems were created from numbers, the left-most column is right-aligned.
758
+ # Therefore 1.5 will be right-aligned.
759
+ assert lines [2 ].startswith (" 1.5" )
760
+ assert lines [2 ].strip ().endswith ('One.Five' )
751
761
752
762
753
763
@pytest .mark .parametrize (
0 commit comments