@@ -694,24 +694,41 @@ class _DialogList(Generic[_T]):
694694 Common code for `RadioList` and `CheckboxList`.
695695 """
696696
697- open_character : str = ""
698- close_character : str = ""
699- container_style : str = ""
700- default_style : str = ""
701- selected_style : str = ""
702- checked_style : str = ""
703- multiple_selection : bool = False
704- show_scrollbar : bool = True
705-
706697 def __init__ (
707698 self ,
708699 values : Sequence [tuple [_T , AnyFormattedText ]],
709700 default_values : Sequence [_T ] | None = None ,
701+ select_on_focus : bool = False ,
702+ open_character : str = "" ,
703+ select_character : str = "*" ,
704+ close_character : str = "" ,
705+ container_style : str = "" ,
706+ default_style : str = "" ,
707+ number_style : str = "" ,
708+ selected_style : str = "" ,
709+ checked_style : str = "" ,
710+ multiple_selection : bool = False ,
711+ show_scrollbar : bool = True ,
712+ show_cursor : bool = True ,
713+ show_numbers : bool = False ,
710714 ) -> None :
711715 assert len (values ) > 0
712716 default_values = default_values or []
713717
714718 self .values = values
719+ self .show_numbers = show_numbers
720+
721+ self .open_character = open_character
722+ self .select_character = select_character
723+ self .close_character = close_character
724+ self .container_style = container_style
725+ self .default_style = default_style
726+ self .number_style = number_style
727+ self .selected_style = selected_style
728+ self .checked_style = checked_style
729+ self .multiple_selection = multiple_selection
730+ self .show_scrollbar = show_scrollbar
731+
715732 # current_values will be used in multiple_selection,
716733 # current_value will be used otherwise.
717734 keys : list [_T ] = [value for (value , _ ) in values ]
@@ -734,12 +751,18 @@ def __init__(
734751 kb = KeyBindings ()
735752
736753 @kb .add ("up" )
754+ @kb .add ("k" ) # Vi-like.
737755 def _up (event : E ) -> None :
738756 self ._selected_index = max (0 , self ._selected_index - 1 )
757+ if select_on_focus :
758+ self ._handle_enter ()
739759
740760 @kb .add ("down" )
761+ @kb .add ("j" ) # Vi-like.
741762 def _down (event : E ) -> None :
742763 self ._selected_index = min (len (self .values ) - 1 , self ._selected_index + 1 )
764+ if select_on_focus :
765+ self ._handle_enter ()
743766
744767 @kb .add ("pageup" )
745768 def _pageup (event : E ) -> None :
@@ -774,9 +797,22 @@ def _find(event: E) -> None:
774797 self ._selected_index = self .values .index (value )
775798 return
776799
800+ numbers_visible = Condition (lambda : self .show_numbers )
801+
802+ for i in range (1 , 10 ):
803+
804+ @kb .add (str (i ), filter = numbers_visible )
805+ def _select_i (event : E , index : int = i ) -> None :
806+ self ._selected_index = min (len (self .values ) - 1 , index - 1 )
807+ if select_on_focus :
808+ self ._handle_enter ()
809+
777810 # Control and window.
778811 self .control = FormattedTextControl (
779- self ._get_text_fragments , key_bindings = kb , focusable = True
812+ self ._get_text_fragments ,
813+ key_bindings = kb ,
814+ focusable = True ,
815+ show_cursor = show_cursor ,
780816 )
781817
782818 self .window = Window (
@@ -831,13 +867,19 @@ def mouse_handler(mouse_event: MouseEvent) -> None:
831867 result .append (("[SetCursorPosition]" , "" ))
832868
833869 if checked :
834- result .append ((style , "*" ))
870+ result .append ((style , self . select_character ))
835871 else :
836872 result .append ((style , " " ))
837873
838874 result .append ((style , self .close_character ))
839- result .append ((self .default_style , " " ))
840- result .extend (to_formatted_text (value [1 ], style = self .default_style ))
875+ result .append ((f"{ style } { self .default_style } " , " " ))
876+
877+ if self .show_numbers :
878+ result .append ((f"{ style } { self .number_style } " , f"{ i + 1 :2d} . " ))
879+
880+ result .extend (
881+ to_formatted_text (value [1 ], style = f"{ style } { self .default_style } " )
882+ )
841883 result .append (("" , "\n " ))
842884
843885 # Add mouse handler to all fragments.
@@ -858,25 +900,44 @@ class RadioList(_DialogList[_T]):
858900 :param values: List of (value, label) tuples.
859901 """
860902
861- open_character = "("
862- close_character = ")"
863- container_style = "class:radio-list"
864- default_style = "class:radio"
865- selected_style = "class:radio-selected"
866- checked_style = "class:radio-checked"
867- multiple_selection = False
868-
869903 def __init__ (
870904 self ,
871905 values : Sequence [tuple [_T , AnyFormattedText ]],
872906 default : _T | None = None ,
907+ show_numbers : bool = False ,
908+ select_on_focus : bool = False ,
909+ open_character : str = "(" ,
910+ select_character : str = "*" ,
911+ close_character : str = ")" ,
912+ container_style : str = "class:radio-list" ,
913+ default_style : str = "class:radio" ,
914+ selected_style : str = "class:radio-selected" ,
915+ checked_style : str = "class:radio-checked" ,
916+ number_style : str = "class:radio-number" ,
917+ multiple_selection : bool = False ,
918+ show_cursor : bool = True ,
873919 ) -> None :
874920 if default is None :
875921 default_values = None
876922 else :
877923 default_values = [default ]
878924
879- super ().__init__ (values , default_values = default_values )
925+ super ().__init__ (
926+ values ,
927+ default_values = default_values ,
928+ select_on_focus = select_on_focus ,
929+ show_numbers = show_numbers ,
930+ open_character = open_character ,
931+ select_character = select_character ,
932+ close_character = close_character ,
933+ container_style = container_style ,
934+ default_style = default_style ,
935+ selected_style = selected_style ,
936+ checked_style = checked_style ,
937+ number_style = number_style ,
938+ multiple_selection = False ,
939+ show_cursor = show_cursor ,
940+ )
880941
881942
882943class CheckboxList (_DialogList [_T ]):
@@ -886,13 +947,30 @@ class CheckboxList(_DialogList[_T]):
886947 :param values: List of (value, label) tuples.
887948 """
888949
889- open_character = "["
890- close_character = "]"
891- container_style = "class:checkbox-list"
892- default_style = "class:checkbox"
893- selected_style = "class:checkbox-selected"
894- checked_style = "class:checkbox-checked"
895- multiple_selection = True
950+ def __init__ (
951+ self ,
952+ values : Sequence [tuple [_T , AnyFormattedText ]],
953+ default_values : Sequence [_T ] | None = None ,
954+ open_character : str = "[" ,
955+ select_character : str = "*" ,
956+ close_character : str = "]" ,
957+ container_style : str = "class:checkbox-list" ,
958+ default_style : str = "class:checkbox" ,
959+ selected_style : str = "class:checkbox-selected" ,
960+ checked_style : str = "class:checkbox-checked" ,
961+ ) -> None :
962+ super ().__init__ (
963+ values ,
964+ default_values = default_values ,
965+ open_character = open_character ,
966+ select_character = select_character ,
967+ close_character = close_character ,
968+ container_style = container_style ,
969+ default_style = default_style ,
970+ selected_style = selected_style ,
971+ checked_style = checked_style ,
972+ multiple_selection = True ,
973+ )
896974
897975
898976class Checkbox (CheckboxList [str ]):
0 commit comments