diff --git a/prompt_toolkit/shortcuts/dialogs.py b/prompt_toolkit/shortcuts/dialogs.py index a91bb3142..9140f86ab 100644 --- a/prompt_toolkit/shortcuts/dialogs.py +++ b/prompt_toolkit/shortcuts/dialogs.py @@ -1,5 +1,5 @@ import functools -from typing import Any, Callable, List, Optional, Tuple, TypeVar +from typing import Any, Callable, List, Optional, Sequence, Tuple, TypeVar from prompt_toolkit.application import Application from prompt_toolkit.application.current import get_app @@ -174,7 +174,8 @@ def radiolist_dialog( text: AnyFormattedText = "", ok_text: str = "Ok", cancel_text: str = "Cancel", - values: Optional[List[Tuple[_T, AnyFormattedText]]] = None, + values: Optional[Sequence[Tuple[_T, AnyFormattedText]]] = None, + default: Optional[_T] = None, style: Optional[BaseStyle] = None, ) -> Application[_T]: """ @@ -189,7 +190,7 @@ def radiolist_dialog( def ok_handler() -> None: get_app().exit(result=radio_list.current_value) - radio_list = RadioList(values) + radio_list = RadioList(values=values, default=default) dialog = Dialog( title=title, @@ -212,7 +213,8 @@ def checkboxlist_dialog( text: AnyFormattedText = "", ok_text: str = "Ok", cancel_text: str = "Cancel", - values: Optional[List[Tuple[_T, AnyFormattedText]]] = None, + values: Optional[Sequence[Tuple[_T, AnyFormattedText]]] = None, + default_values: Optional[Sequence[_T]] = None, style: Optional[BaseStyle] = None, ) -> Application[List[_T]]: """ @@ -227,7 +229,7 @@ def checkboxlist_dialog( def ok_handler() -> None: get_app().exit(result=cb_list.current_values) - cb_list = CheckboxList(values) + cb_list = CheckboxList(values=values, default_values=default_values) dialog = Dialog( title=title, diff --git a/prompt_toolkit/widgets/base.py b/prompt_toolkit/widgets/base.py index ac8896351..885d23a88 100644 --- a/prompt_toolkit/widgets/base.py +++ b/prompt_toolkit/widgets/base.py @@ -686,15 +686,32 @@ class _DialogList(Generic[_T]): multiple_selection: bool = False show_scrollbar: bool = True - def __init__(self, values: Sequence[Tuple[_T, AnyFormattedText]]) -> None: + def __init__( + self, + values: Sequence[Tuple[_T, AnyFormattedText]], + default_values: Optional[Sequence[_T]] = None, + ) -> None: assert len(values) > 0 + default_values = default_values or [] self.values = values # current_values will be used in multiple_selection, # current_value will be used otherwise. - self.current_values: List[_T] = [] - self.current_value: _T = values[0][0] - self._selected_index = 0 + keys: List[_T] = [value for (value, _) in values] + self.current_values: List[_T] = [ + value for value in default_values if value in keys + ] + self.current_value: _T = ( + default_values[0] + if len(default_values) and default_values[0] in keys + else values[0][0] + ) + + # Cursor index: take first selected item or first item otherwise. + if len(self.current_values) > 0: + self._selected_index = keys.index(self.current_values[0]) + else: + self._selected_index = 0 # Key bindings. kb = KeyBindings() @@ -832,6 +849,18 @@ class RadioList(_DialogList[_T]): checked_style = "class:radio-checked" multiple_selection = False + def __init__( + self, + values: Sequence[Tuple[_T, AnyFormattedText]], + default: Optional[_T] = None, + ) -> None: + if default is None: + default_values = None + else: + default_values = [default] + + super().__init__(values, default_values=default_values) + class CheckboxList(_DialogList[_T]): """ @@ -859,7 +888,7 @@ class Checkbox(CheckboxList[str]): def __init__(self, text: AnyFormattedText = "", checked: bool = False) -> None: values = [("value", text)] - CheckboxList.__init__(self, values) + CheckboxList.__init__(self, values=values) self.checked = checked @property