66import  argparse 
77import  inspect 
88import  numbers 
9+ import  sys 
910from  collections  import  (
1011    deque ,
1112)
13+ from  collections .abc  import  Sequence 
1214from  typing  import  (
1315    IO ,
1416    TYPE_CHECKING ,
1517    cast ,
1618)
1719
18- from  .ansi  import  (
19-     style_aware_wcswidth ,
20-     widest_line ,
21- )
2220from  .constants  import  (
2321    INFINITY ,
2422)
23+ from  .rich_utils  import  (
24+     Cmd2Console ,
25+     Cmd2Style ,
26+ )
2527
2628if  TYPE_CHECKING :  # pragma: no cover 
2729    from  .cmd2  import  (
2830        Cmd ,
2931    )
3032
33+ 
34+ from  rich .box  import  SIMPLE_HEAD 
35+ from  rich .table  import  Column , Table 
36+ 
3137from  .argparse_custom  import  (
3238    ChoicesCallable ,
3339    ChoicesProviderFuncWithTokens ,
4046from  .exceptions  import  (
4147    CompletionError ,
4248)
43- from  .table_creator  import  (
44-     Column ,
45-     HorizontalAlignment ,
46-     SimpleTable ,
47- )
4849
49- # If no descriptive header is  supplied, then this will be used instead 
50- DEFAULT_DESCRIPTIVE_HEADER   =   'Description' 
50+ # If no descriptive headers are  supplied, then this will be used instead 
51+ DEFAULT_DESCRIPTIVE_HEADERS :  Sequence [ str   |   Column ]  =  ( 'Description' ,) 
5152
5253# Name of the choice/completer function argument that, if present, will be passed a dictionary of 
5354# command line tokens up through the token being completed mapped to their argparse destination name. 
@@ -546,8 +547,6 @@ def _format_completions(self, arg_state: _ArgumentState, completions: list[str]
546547
547548        # Check if there are too many CompletionItems to display as a table 
548549        if  len (completions ) <=  self ._cmd2_app .max_completion_items :
549-             four_spaces  =  4  *  ' ' 
550- 
551550            # If a metavar was defined, use that instead of the dest field 
552551            destination  =  arg_state .action .metavar  if  arg_state .action .metavar  else  arg_state .action .dest 
553552
@@ -560,39 +559,45 @@ def _format_completions(self, arg_state: _ArgumentState, completions: list[str]
560559                tuple_index  =  min (len (destination ) -  1 , arg_state .count )
561560                destination  =  destination [tuple_index ]
562561
563-             desc_header  =  arg_state .action .get_descriptive_header ()  # type: ignore[attr-defined] 
564-             if  desc_header  is  None :
565-                 desc_header  =  DEFAULT_DESCRIPTIVE_HEADER 
566- 
567-             # Replace tabs with 4 spaces so we can calculate width 
568-             desc_header  =  desc_header .replace ('\t ' , four_spaces )
562+             desc_headers  =  cast (Sequence [str  |  Column ] |  None , arg_state .action .get_descriptive_headers ())  # type: ignore[attr-defined] 
563+             if  desc_headers  is  None :
564+                 desc_headers  =  DEFAULT_DESCRIPTIVE_HEADERS 
569565
570-             # Calculate needed widths for the token and description columns of the table 
571-             token_width  =  style_aware_wcswidth (destination )
572-             desc_width  =  widest_line (desc_header )
573- 
574-             for  item  in  completion_items :
575-                 token_width  =  max (style_aware_wcswidth (item ), token_width )
576- 
577-                 # Replace tabs with 4 spaces so we can calculate width 
578-                 item .description  =  item .description .replace ('\t ' , four_spaces )
579-                 desc_width  =  max (widest_line (item .description ), desc_width )
580- 
581-             cols  =  []
582-             dest_alignment  =  HorizontalAlignment .RIGHT  if  all_nums  else  HorizontalAlignment .LEFT 
583-             cols .append (
566+             # Build all headers for the hint table 
567+             headers : list [Column ] =  []
568+             headers .append (
584569                Column (
585570                    destination .upper (),
586-                     width = token_width ,
587-                     header_horiz_align = dest_alignment ,
588-                     data_horiz_align = dest_alignment ,
571+                     justify = "right"  if  all_nums  else  "left" ,
572+                     no_wrap = True ,
589573                )
590574            )
591-             cols .append (Column (desc_header , width = desc_width ))
575+             for  desc_header  in  desc_headers :
576+                 header  =  (
577+                     desc_header 
578+                     if  isinstance (desc_header , Column )
579+                     else  Column (
580+                         desc_header ,
581+                         overflow = "fold" ,
582+                     )
583+                 )
584+                 headers .append (header )
585+ 
586+             # Build the hint table 
587+             hint_table  =  Table (
588+                 * headers ,
589+                 box = SIMPLE_HEAD ,
590+                 show_edge = False ,
591+                 border_style = Cmd2Style .RULE_LINE ,
592+             )
593+             for  item  in  completion_items :
594+                 hint_table .add_row (item , * item .descriptive_data )
592595
593-             hint_table  =  SimpleTable (cols , divider_char = self ._cmd2_app .ruler )
594-             table_data  =  [[item , item .description ] for  item  in  completion_items ]
595-             self ._cmd2_app .formatted_completions  =  hint_table .generate_table (table_data , row_spacing = 0 )
596+             # Generate the hint table string 
597+             console  =  Cmd2Console (sys .stdout )
598+             with  console .capture () as  capture :
599+                 console .print (hint_table )
600+             self ._cmd2_app .formatted_completions  =  capture .get ()
596601
597602        # Return sorted list of completions 
598603        return  cast (list [str ], completions )
0 commit comments