Skip to content

Commit

Permalink
Adds the description and show_description options to Choice and…
Browse files Browse the repository at this point in the history
… `InquirerControl` (#330)

* add description and show_description options

* show description by default, but only if set

* add docs

* add test

* add show_description to checkbox

* add more docs

* trigger CI

* fix newline removal logic

---------

Co-authored-by: Philip Meier <[email protected]>
  • Loading branch information
viniciusdc and pmeier authored Jan 11, 2024
1 parent d21ba3e commit bba92b4
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 4 deletions.
9 changes: 8 additions & 1 deletion questionary/prompts/checkbox.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ def checkbox(
use_jk_keys: bool = True,
use_emacs_keys: bool = True,
instruction: Optional[str] = None,
show_description: bool = True,
**kwargs: Any,
) -> Question:
"""Ask the user to select from a list of items.
Expand Down Expand Up @@ -106,6 +107,8 @@ def checkbox(
`Ctrl+N` (down) and `Ctrl+P` (up) keys.
instruction: A message describing how to navigate the menu.
show_description: Display description of current selection if available.
Returns:
:class:`Question`: Question instance, ready to be prompted (using ``.ask()``).
"""
Expand All @@ -130,7 +133,11 @@ def checkbox(
raise ValueError("validate must be callable")

ic = InquirerControl(
choices, default, pointer=pointer, initial_choice=initial_choice
choices,
default,
pointer=pointer,
initial_choice=initial_choice,
show_description=show_description,
)

def get_prompt_tokens() -> List[Tuple[str, str]]:
Expand Down
25 changes: 22 additions & 3 deletions questionary/prompts/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ class Choice:
checked: Preselect this choice when displaying the options.
shortcut_key: Key shortcut used to select this item.
description: Optional description of the item that can be displayed.
"""

title: FormattedText
Expand All @@ -70,17 +72,22 @@ class Choice:
shortcut_key: Optional[str]
"""A shortcut key for the choice"""

description: Optional[str]
"""Choice description"""

def __init__(
self,
title: FormattedText,
value: Optional[Any] = None,
disabled: Optional[str] = None,
checked: Optional[bool] = False,
shortcut_key: Optional[Union[str, bool]] = True,
description: Optional[str] = None,
) -> None:
self.disabled = disabled
self.title = title
self.checked = checked if checked is not None else False
self.description = description

if value is not None:
self.value = value
Expand Down Expand Up @@ -124,6 +131,7 @@ def build(c: Union[str, "Choice", Dict[str, Any]]) -> "Choice":
c.get("disabled", None),
c.get("checked"),
c.get("key"),
c.get("description", None),
)

def get_shortcut_title(self):
Expand Down Expand Up @@ -202,6 +210,7 @@ class InquirerControl(FormattedTextControl):
pointer: Optional[str]
pointed_at: int
is_answered: bool
show_description: bool

def __init__(
self,
Expand All @@ -211,13 +220,15 @@ def __init__(
use_indicator: bool = True,
use_shortcuts: bool = False,
show_selected: bool = False,
show_description: bool = True,
use_arrow_keys: bool = True,
initial_choice: Optional[Union[str, Choice, Dict[str, Any]]] = None,
**kwargs: Any,
):
self.use_indicator = use_indicator
self.use_shortcuts = use_shortcuts
self.show_selected = show_selected
self.show_description = show_description
self.use_arrow_keys = use_arrow_keys
self.default = default
self.pointer = pointer
Expand Down Expand Up @@ -417,18 +428,26 @@ def append(index: int, choice: Choice):
for i, c in enumerate(self.choices):
append(i, c)

if self.show_selected:
current = self.get_pointed_at()
current = self.get_pointed_at()

if self.show_selected:
answer = current.get_shortcut_title() if self.use_shortcuts else ""

answer += (
current.title if isinstance(current.title, str) else current.title[0][1]
)

tokens.append(("class:text", " Answer: {}".format(answer)))
else:

show_description = self.show_description and current.description is not None
if show_description:
tokens.append(
("class:text", " Description: {}".format(current.description))
)

if not (self.show_selected or show_description):
tokens.pop() # Remove last newline.

return tokens

def is_selection_a_separator(self) -> bool:
Expand Down
4 changes: 4 additions & 0 deletions questionary/prompts/select.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ def select(
use_jk_keys: bool = True,
use_emacs_keys: bool = True,
show_selected: bool = False,
show_description: bool = True,
instruction: Optional[str] = None,
**kwargs: Any,
) -> Question:
Expand Down Expand Up @@ -110,6 +111,8 @@ def select(
show_selected: Display current selection choice at the bottom of list.
show_description: Display description of current selection if available.
Returns:
:class:`Question`: Question instance, ready to be prompted (using ``.ask()``).
"""
Expand Down Expand Up @@ -150,6 +153,7 @@ def select(
use_indicator=use_indicator,
use_shortcuts=use_shortcuts,
show_selected=show_selected,
show_description=show_description,
use_arrow_keys=use_arrow_keys,
initial_choice=default,
)
Expand Down
40 changes: 40 additions & 0 deletions tests/prompts/test_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -222,3 +222,43 @@ def test_print_with_style(monkeypatch):

assert mock.method_calls[1][0] == "write"
assert mock.method_calls[1][1][0] == "Hello World"


def test_prompt_show_description():
ic = InquirerControl(
["a", Choice("b", description="B")],
show_selected=True,
show_description=True,
)

expected_tokens = [
("class:pointer", " » "),
("[SetCursorPosition]", ""),
("class:text", "○ "),
("class:highlighted", "a"),
("", "\n"),
("class:text", " "),
("class:text", "○ "),
("class:text", "b"),
("", "\n"),
("class:text", " Answer: a"),
]
assert ic.pointed_at == 0
assert ic._get_choice_tokens() == expected_tokens

ic.select_next()
expected_tokens = [
("class:text", " "),
("class:text", "○ "),
("class:text", "a"),
("", "\n"),
("class:pointer", " » "),
("[SetCursorPosition]", ""),
("class:text", "○ "),
("class:highlighted", "b"),
("", "\n"),
("class:text", " Answer: b"),
("class:text", " Description: B"),
]
assert ic.pointed_at == 1
assert ic._get_choice_tokens() == expected_tokens

0 comments on commit bba92b4

Please sign in to comment.