inquirer-textual 0.1.0__py3-none-any.whl → 0.3.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -15,7 +15,7 @@ class InquirerMulti(InquirerWidget):
15
15
  }
16
16
  """
17
17
 
18
- def __init__(self, widgets: list[InquirerWidget]) -> None:
18
+ def __init__(self, widgets: list[tuple[str, InquirerWidget]]) -> None:
19
19
  """
20
20
  Args:
21
21
  widgets (list[InquirerWidget]): A list of InquirerWidget instances to present in sequence.
@@ -23,24 +23,25 @@ class InquirerMulti(InquirerWidget):
23
23
  super().__init__()
24
24
  self.widgets = widgets
25
25
  self._current_widget_index = 0
26
- self._return_values: list[Any] = []
26
+ self._return_values_dict: dict[str, Any] = {}
27
27
 
28
28
  def on_mount(self):
29
29
  self.query_one(ContentSwitcher).current = f'widget-{self._current_widget_index}'
30
30
  self.query_one(ContentSwitcher).visible_content.focus()
31
31
 
32
32
  def on_inquirer_widget_submit(self, message: InquirerWidget.Submit) -> None:
33
- self._return_values.append(message.value)
33
+ current_widget = self.widgets[self._current_widget_index]
34
+ self._return_values_dict[current_widget[0]] = message.value
34
35
  self._current_widget_index += 1
35
36
  if self._current_widget_index < len(self.widgets):
36
37
  message.stop()
37
38
  self.query_one(ContentSwitcher).current = f'widget-{self._current_widget_index}'
38
39
  self.query_one(ContentSwitcher).visible_content.focus()
39
40
  else:
40
- message.value = self._return_values
41
+ message.value = self._return_values_dict
41
42
 
42
43
  def compose(self) -> ComposeResult:
43
44
  with ContentSwitcher(initial=f'widget-{self._current_widget_index}'):
44
45
  for idx, widget in enumerate(self.widgets):
45
- widget.id = f'widget-{idx}'
46
- yield widget
46
+ widget[1].id = f'widget-{idx}'
47
+ yield widget[1]
@@ -1,11 +1,12 @@
1
- from typing import Self
1
+ from __future__ import annotations
2
2
 
3
3
  from textual.app import ComposeResult
4
4
  from textual.containers import HorizontalGroup
5
5
  from textual.widgets import Input
6
+ from typing_extensions import Self, Literal
6
7
 
7
- from inquirer_textual.widgets.InquirerWidget import InquirerWidget
8
8
  from inquirer_textual.common.PromptMessage import PromptMessage
9
+ from inquirer_textual.widgets.InquirerWidget import InquirerWidget
9
10
 
10
11
 
11
12
  class InquirerNumber(InquirerWidget):
@@ -24,17 +25,22 @@ class InquirerNumber(InquirerWidget):
24
25
  }
25
26
  """
26
27
 
27
- def __init__(self, message: str):
28
+ def __init__(self, message: str, name: str | None = None, input_type: Literal['integer', 'number'] = 'integer',
29
+ mandatory: bool = False):
28
30
  """
29
31
  Args:
30
32
  message (str): The prompt message to display.
33
+ name (str | None): The name of the input field.
34
+ input_type (Literal['integer', 'number']): The type of number input ('integer' or 'number').
35
+ mandatory (bool): Whether the input is mandatory.
31
36
  """
32
- super().__init__()
37
+ super().__init__(name=name, mandatory=mandatory)
33
38
  self.message = message
39
+ self.input_type = input_type
34
40
  self.input: Input | None = None
35
41
 
36
- def on_input_submitted(self, submitted: Input.Submitted):
37
- self.post_message(InquirerWidget.Submit(submitted.value))
42
+ def on_input_submitted(self) -> None:
43
+ self.submit_current_value()
38
44
 
39
45
  def focus(self, scroll_visible: bool = True) -> Self:
40
46
  if self.input:
@@ -43,10 +49,15 @@ class InquirerNumber(InquirerWidget):
43
49
  return super().focus(scroll_visible)
44
50
 
45
51
  def current_value(self):
46
- return self.input.value if self.input else None
52
+ if self.input and self.input.value:
53
+ if self.input_type == 'integer':
54
+ return int(self.input.value)
55
+ elif self.input_type == 'number':
56
+ return float(self.input.value)
57
+ return None
47
58
 
48
59
  def compose(self) -> ComposeResult:
49
60
  with HorizontalGroup():
50
61
  yield PromptMessage(self.message)
51
- self.input = Input(id="inquirer-number-input", type="integer")
62
+ self.input = Input(id="inquirer-number-input", type=self.input_type)
52
63
  yield self.input
@@ -0,0 +1,93 @@
1
+ from __future__ import annotations
2
+
3
+ from enum import Enum
4
+ from pathlib import Path
5
+
6
+ from textual.app import ComposeResult
7
+ from textual.containers import HorizontalGroup
8
+ from textual.widgets import Input, Static
9
+ from typing_extensions import Self
10
+
11
+ from inquirer_textual.common.PromptMessage import PromptMessage
12
+ from inquirer_textual.widgets.InquirerWidget import InquirerWidget
13
+
14
+
15
+ class PathType(Enum):
16
+ FILE = 'file'
17
+ DIRECTORY = 'directory'
18
+ ANY = 'any'
19
+
20
+
21
+ class InquirerPath(InquirerWidget):
22
+ """An input prompt that allows the user to enter a file path."""
23
+
24
+ DEFAULT_CSS = """
25
+ InquirerPath {
26
+ height: auto;
27
+ }
28
+ #inquirer-path-input {
29
+ border: none;
30
+ background: transparent;
31
+ color: $input-color;
32
+ padding: 0;
33
+ height: 1;
34
+ }
35
+ #inquirer-path-error-message {
36
+ color: $error-color;
37
+ height: auto;
38
+ }
39
+ """
40
+
41
+ def __init__(self, message: str, name: str | None = None, default: str = '', exists: bool = False,
42
+ path_type: PathType = PathType.ANY, mandatory: bool = False):
43
+ """
44
+ Args:
45
+ message (str): The prompt message to display.
46
+ default (str): The default value if the user presses Enter without input.
47
+ exists (bool): If True, validate that the entered path exists.
48
+ """
49
+ super().__init__(name=name, mandatory=mandatory)
50
+ self.message = message
51
+ self.input: Input | None = None
52
+ self.default = default
53
+ self.exists = exists
54
+ self.path_type = path_type
55
+
56
+ def on_mount(self):
57
+ super().on_mount()
58
+ self.input.value = self.default
59
+
60
+ def on_input_submitted(self, submitted: Input.Submitted):
61
+ if self.exists:
62
+ if not Path(submitted.value).exists():
63
+ self._show_validation_error("The specified path does not exist.")
64
+ return
65
+ if self.path_type != PathType.ANY:
66
+ path = Path(submitted.value)
67
+ if self.path_type == PathType.FILE and not path.is_file():
68
+ self._show_validation_error("The specified path is not a file.")
69
+ return
70
+ if self.path_type == PathType.DIRECTORY and not path.is_dir():
71
+ self._show_validation_error("The specified path is not a directory.")
72
+ return
73
+ self.submit_current_value()
74
+
75
+ def _show_validation_error(self, message: str):
76
+ error_message = self.query_one('#inquirer-path-error-message', Static)
77
+ error_message.update(message)
78
+
79
+ def focus(self, scroll_visible: bool = True) -> Self:
80
+ if self.input:
81
+ return self.input.focus(scroll_visible)
82
+ else:
83
+ return super().focus(scroll_visible)
84
+
85
+ def current_value(self):
86
+ return self.input.value if self.input else None
87
+
88
+ def compose(self) -> ComposeResult:
89
+ with HorizontalGroup():
90
+ yield PromptMessage(self.message)
91
+ self.input = Input(id="inquirer-path-input")
92
+ yield self.input
93
+ yield Static("", id="inquirer-path-error-message")
@@ -0,0 +1,169 @@
1
+ from __future__ import annotations
2
+
3
+ from textual import on, events
4
+ from textual.app import ComposeResult
5
+ from textual.containers import VerticalGroup, HorizontalGroup
6
+ from textual.css.query import NoMatches
7
+ from textual.reactive import reactive
8
+ from textual.widgets import ListView, ListItem, Input, Static
9
+ from typing_extensions import Self
10
+
11
+ from inquirer_textual.common.Choice import Choice
12
+ from inquirer_textual.common.ChoiceLabel import ChoiceLabel
13
+ from inquirer_textual.common.PromptMessage import PromptMessage
14
+ from inquirer_textual.common.StandardTheme import StandardTheme
15
+ from inquirer_textual.widgets.InquirerWidget import InquirerWidget
16
+
17
+
18
+ class InquirerPattern(InquirerWidget):
19
+ """A select widget that allows a single selection from a list of choices with pattern filtering."""
20
+
21
+ DEFAULT_CSS = """
22
+ #inquirer-pattern-list-view {
23
+ background: transparent;
24
+ }
25
+ #inquirer-pattern-list-view ListItem.-highlight {
26
+ color: $select-list-item-highlight-foreground;
27
+ background: transparent;
28
+ }
29
+ #inquirer-pattern-query-container {
30
+ width: auto;
31
+ # border: red;
32
+ }
33
+ #inquirer-pattern-query {
34
+ border: none;
35
+ background: transparent;
36
+ color: $input-color;
37
+ padding: 0;
38
+ height: 1;
39
+ width: 20;
40
+ }
41
+ #inquirer-pattern-query-pointer {
42
+ width: auto;
43
+ color: $prompt-color;
44
+ }
45
+ """
46
+
47
+ candidates: reactive[list[str | Choice]] = reactive([])
48
+
49
+ def __init__(self, message: str, choices: list[str | Choice], name: str | None = None,
50
+ default: str | Choice | None = None, mandatory: bool = True):
51
+ """
52
+ Args:
53
+ message (str): The prompt message to display.
54
+ choices (list[str | Choice]): A list of choices to present to the user.
55
+ default (str | Choice | None): The default choice to pre-select.
56
+ mandatory (bool): Whether a response is mandatory.
57
+ """
58
+ super().__init__(name=name, mandatory=mandatory)
59
+ self.message = message
60
+ self.choices = choices
61
+ self.candidates = choices.copy()
62
+ self.list_view: ListView | None = None
63
+ self.selected_label: ChoiceLabel | None = None
64
+ self.selected_item: str | Choice | None = None
65
+ self.default = default
66
+ self.query: Input | None = None
67
+
68
+ def on_mount(self):
69
+ super().on_mount()
70
+ if self.app.is_inline:
71
+ self.styles.height = min(10, len(self.choices) + 1)
72
+ else:
73
+ self.styles.height = '1fr'
74
+
75
+ def on_list_view_highlighted(self, event: ListView.Highlighted) -> None:
76
+ if self.selected_label:
77
+ self.selected_label.remove_pointer()
78
+ if event.item:
79
+ try:
80
+ label = event.item.query_one(ChoiceLabel)
81
+ label.add_pointer()
82
+ self.selected_label = label
83
+ self.selected_item = label.item
84
+ return
85
+ except NoMatches:
86
+ pass
87
+ self.selected_label = None
88
+ self.selected_item = None
89
+
90
+ def on_list_view_selected(self, _: ListView.Selected):
91
+ if isinstance(self.selected_item, Choice):
92
+ self.submit_current_value(self.selected_item.command)
93
+ else:
94
+ self.submit_current_value()
95
+
96
+ def focus(self, scroll_visible: bool = True) -> Self:
97
+ if self.query:
98
+ return self.query.focus(scroll_visible)
99
+ else:
100
+ return super().focus(scroll_visible)
101
+
102
+ def current_value(self):
103
+ return self.selected_item
104
+
105
+ def _collect_list_items(self):
106
+ items: list[ListItem] = []
107
+ for candidate in self.candidates:
108
+ list_item = ListItem(ChoiceLabel(candidate, self.query.value if self.query else None))
109
+ items.append(list_item)
110
+ return items
111
+
112
+ def _find_initial_index(self):
113
+ initial_index = 0
114
+ for idx, choice in enumerate(self.choices):
115
+ if self.default and choice == self.default:
116
+ initial_index = idx
117
+ return initial_index
118
+
119
+ @on(Input.Changed, '#inquirer-pattern-query')
120
+ async def handle_query_changed(self, event: Input.Changed):
121
+ query = event.value.lower()
122
+ if query == '':
123
+ self.candidates = self.choices.copy()
124
+ else:
125
+ filtered = []
126
+ for choice in self.choices:
127
+ name = choice.name if isinstance(choice, Choice) else choice
128
+ if query in name.lower():
129
+ filtered.append(choice)
130
+ self.candidates = filtered
131
+ assert isinstance(self.list_view, ListView)
132
+ await self.list_view.clear()
133
+ list_items = self._collect_list_items()
134
+ await self.list_view.extend(list_items)
135
+ if list_items:
136
+ self.list_view.index = 0
137
+
138
+ def watch_candidates(self, candidates: list[str | Choice]) -> None:
139
+ count_suffix = f'[{len(candidates)}/{len(self.choices)}]'
140
+ try:
141
+ count_widget = self.query_one('#inquirer-pattern-query-count-suffix', Static)
142
+ count_widget.update(count_suffix)
143
+ except NoMatches:
144
+ pass
145
+
146
+ def on_key(self, event: events.Key):
147
+ assert isinstance(self.list_view, ListView)
148
+ if event.key == 'down':
149
+ event.stop()
150
+ self.list_view.action_cursor_down()
151
+ elif event.key == 'up':
152
+ event.stop()
153
+ self.list_view.action_cursor_up()
154
+ elif event.key == 'enter':
155
+ event.stop()
156
+ self.list_view.action_select_cursor()
157
+
158
+ def compose(self) -> ComposeResult:
159
+ with VerticalGroup():
160
+ self.list_view = ListView(*self._collect_list_items(), id='inquirer-pattern-list-view',
161
+ initial_index=self._find_initial_index())
162
+ with HorizontalGroup():
163
+ yield PromptMessage(self.message)
164
+ yield Static(f'[{len(self.candidates)}/{len(self.choices)}]', id='inquirer-pattern-query-count-suffix')
165
+ with HorizontalGroup(id='inquirer-pattern-query-container'):
166
+ yield Static(f'{StandardTheme.pointer_character} ', id='inquirer-pattern-query-pointer')
167
+ self.query = Input(id="inquirer-pattern-query")
168
+ yield self.query
169
+ yield self.list_view
@@ -1,8 +1,9 @@
1
- from typing import Self
1
+ from __future__ import annotations
2
2
 
3
3
  from textual.app import ComposeResult
4
4
  from textual.containers import HorizontalGroup
5
5
  from textual.widgets import Input
6
+ from typing_extensions import Self
6
7
 
7
8
  from inquirer_textual.common.PromptMessage import PromptMessage
8
9
  from inquirer_textual.widgets.InquirerWidget import InquirerWidget
@@ -24,12 +25,12 @@ class InquirerSecret(InquirerWidget):
24
25
  }
25
26
  """
26
27
 
27
- def __init__(self, message: str):
28
+ def __init__(self, message: str, name: str | None = None, mandatory: bool = False):
28
29
  """
29
30
  Args:
30
31
  message (str): The prompt message to display.
31
32
  """
32
- super().__init__()
33
+ super().__init__(name=name, mandatory=mandatory)
33
34
  self.message = message
34
35
  self.input: Input | None = None
35
36
 
@@ -1,12 +1,14 @@
1
- from typing import Self
1
+ from __future__ import annotations
2
2
 
3
- from inquirer_textual.common.Choice import Choice
4
- from inquirer_textual.widgets.InquirerWidget import InquirerWidget
5
- from inquirer_textual.common.PromptMessage import PromptMessage
6
- from inquirer_textual.common.ChoiceLabel import ChoiceLabel
7
3
  from textual.app import ComposeResult
8
4
  from textual.containers import VerticalGroup
9
5
  from textual.widgets import ListView, ListItem
6
+ from typing_extensions import Self
7
+
8
+ from inquirer_textual.common.Choice import Choice
9
+ from inquirer_textual.common.ChoiceLabel import ChoiceLabel
10
+ from inquirer_textual.common.PromptMessage import PromptMessage
11
+ from inquirer_textual.widgets.InquirerWidget import InquirerWidget
10
12
 
11
13
 
12
14
  class InquirerSelect(InquirerWidget):
@@ -22,8 +24,8 @@ class InquirerSelect(InquirerWidget):
22
24
  }
23
25
  """
24
26
 
25
- def __init__(self, message: str, choices: list[str | Choice], default: str | Choice | None = None,
26
- mandatory: bool = True):
27
+ def __init__(self, message: str, choices: list[str | Choice], name: str | None = None,
28
+ default: str | Choice | None = None, mandatory: bool = True):
27
29
  """
28
30
  Args:
29
31
  message (str): The prompt message to display.
@@ -31,7 +33,7 @@ class InquirerSelect(InquirerWidget):
31
33
  default (str | Choice | None): The default choice to pre-select.
32
34
  mandatory (bool): Whether a response is mandatory.
33
35
  """
34
- super().__init__(mandatory)
36
+ super().__init__(name=name, mandatory=mandatory)
35
37
  self.message = message
36
38
  self.choices = choices
37
39
  self.list_view: ListView | None = None
@@ -41,7 +43,10 @@ class InquirerSelect(InquirerWidget):
41
43
 
42
44
  def on_mount(self):
43
45
  super().on_mount()
44
- self.styles.height = min(10, len(self.choices) + 1)
46
+ if self.app.is_inline:
47
+ self.styles.height = min(10, len(self.choices) + 1)
48
+ else:
49
+ self.styles.height = '1fr'
45
50
 
46
51
  def on_list_view_highlighted(self, event: ListView.Highlighted) -> None:
47
52
  if self.selected_label:
@@ -53,9 +58,9 @@ class InquirerSelect(InquirerWidget):
53
58
 
54
59
  def on_list_view_selected(self, _: ListView.Selected):
55
60
  if isinstance(self.selected_item, Choice):
56
- self.post_message(InquirerWidget.Submit(self.selected_item, self.selected_item.command))
61
+ self.submit_current_value(self.selected_item.command)
57
62
  else:
58
- self.post_message(InquirerWidget.Submit(self.selected_item))
63
+ self.submit_current_value()
59
64
 
60
65
  def focus(self, scroll_visible: bool = True) -> Self:
61
66
  if self.list_view:
@@ -1,12 +1,15 @@
1
- from typing import Self, Iterable
1
+ from __future__ import annotations
2
+
3
+ from typing import Iterable
2
4
 
3
5
  from textual.app import ComposeResult
4
6
  from textual.containers import HorizontalGroup
5
7
  from textual.validation import Validator
6
8
  from textual.widgets import Input
9
+ from typing_extensions import Self
7
10
 
8
- from inquirer_textual.widgets.InquirerWidget import InquirerWidget
9
11
  from inquirer_textual.common.PromptMessage import PromptMessage
12
+ from inquirer_textual.widgets.InquirerWidget import InquirerWidget
10
13
 
11
14
 
12
15
  class InquirerText(InquirerWidget):
@@ -25,7 +28,9 @@ class InquirerText(InquirerWidget):
25
28
  }
26
29
  """
27
30
 
28
- def __init__(self, message: str, default: str = '', validators: Validator | Iterable[Validator] | None = None):
31
+ def __init__(self, message: str, name: str | None = None, default: str = '',
32
+ validators: Validator | Iterable[Validator] | None = None,
33
+ mandatory: bool = False):
29
34
  """
30
35
  Args:
31
36
  message (str): The prompt message to display.
@@ -33,7 +38,7 @@ class InquirerText(InquirerWidget):
33
38
  validators (Validator | Iterable[Validator] | None): A validator or list of validators to validate the
34
39
  input.
35
40
  """
36
- super().__init__()
41
+ super().__init__(name=name, mandatory=mandatory)
37
42
  self.message = message
38
43
  self.input: Input | None = None
39
44
  self.default = default
@@ -45,7 +50,9 @@ class InquirerText(InquirerWidget):
45
50
 
46
51
  def on_input_submitted(self, submitted: Input.Submitted):
47
52
  if self.validators is None or submitted.validation_result.is_valid:
48
- self.post_message(InquirerWidget.Submit(submitted.value))
53
+ if self.input:
54
+ self.input._cursor_visible = False
55
+ self.submit_current_value()
49
56
 
50
57
  def focus(self, scroll_visible: bool = True) -> Self:
51
58
  if self.input:
@@ -1,3 +1,5 @@
1
+ from __future__ import annotations
2
+
1
3
  from typing import Any
2
4
 
3
5
  from textual.message import Message
@@ -11,8 +13,8 @@ class InquirerWidget(Widget):
11
13
  self.value = value
12
14
  self.command = command
13
15
 
14
- def __init__(self, mandatory: bool = True):
15
- super().__init__()
16
+ def __init__(self, name: str | None = None, mandatory: bool = False):
17
+ super().__init__(name=name)
16
18
  self.mandatory = mandatory
17
19
 
18
20
  def on_mount(self):
@@ -20,7 +22,13 @@ class InquirerWidget(Widget):
20
22
  self._bindings.bind('ctrl+c', 'exit_now', show=False)
21
23
 
22
24
  def action_exit_now(self):
23
- self.post_message(InquirerWidget.Submit(None, None))
25
+ self.post_message(InquirerWidget.Submit(None, 'ctrl+c'))
24
26
 
25
27
  def current_value(self):
26
28
  raise NotImplementedError("Subclasses must implement current_value method")
29
+
30
+ async def set_selected_value(self, value: Any) -> None:
31
+ pass
32
+
33
+ def submit_current_value(self, command: str | None = "select"):
34
+ self.post_message(InquirerWidget.Submit(self.current_value(), command))
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: inquirer-textual
3
- Version: 0.1.0
3
+ Version: 0.3.0
4
4
  Summary: Inquirer based on Textual
5
5
  Project-URL: Changelog, https://github.com/robvanderleek/inquirer-textual/blob/master/CHANGELOG.md
6
6
  Project-URL: Documentation, https://robvanderleek.github.io/inquirer-textual/
@@ -8,8 +8,10 @@ Project-URL: Source, https://github.com/robvanderleek/inquirer-textual
8
8
  Author-email: Rob van der Leek <robvanderleek@gmail.com>
9
9
  License-Expression: GPL-3.0-or-later
10
10
  License-File: LICENSE
11
- Requires-Python: >=3.12
12
- Requires-Dist: textual>=6.2.1
11
+ Requires-Python: <3.15,>=3.9
12
+ Requires-Dist: textual>=7.1.0
13
+ Provides-Extra: examples
14
+ Requires-Dist: textual-slider>=0.2.0; extra == 'examples'
13
15
  Description-Content-Type: text/markdown
14
16
 
15
17
  # Inquirer-Textual
@@ -20,6 +22,12 @@ Description-Content-Type: text/markdown
20
22
 
21
23
  </div>
22
24
 
25
+ <div align="center">
26
+
27
+ *Versatile library for user input in Python 🎙️*
28
+
29
+ </div>
30
+
23
31
  <div align="center">
24
32
 
25
33
  [![main](https://github.com/robvanderleek/inquirer-textual/actions/workflows/main.yml/badge.svg)](https://github.com/robvanderleek/inquirer-textual/actions/workflows/main.yml)
@@ -28,6 +36,22 @@ Description-Content-Type: text/markdown
28
36
 
29
37
  </div>
30
38
 
39
+ All terminal programs start small. Some stay small, and some become incredibly
40
+ big. The goal of this Python library is to make user input simple for small
41
+ programs, while enabling a smooth transition to a comprehensive UI library as
42
+ your program grows.
43
+
44
+ Read the [documentation here](https://robvanderleek.github.io/inquirer-textual/)
45
+
46
+ ## Installation
47
+
48
+ Create and activate a virtual environment (for example with
49
+ [uv](https://docs.astral.sh/uv/)), and then install this package:
50
+
51
+ ```shell
52
+ pip install inquirer-textual
53
+ ```
54
+
31
55
  ## Development
32
56
 
33
57
  Add this library as an editable local dependency to another project using `uv`:
@@ -35,3 +59,31 @@ Add this library as an editable local dependency to another project using `uv`:
35
59
  ```shell
36
60
  uv add --editable <path-to-inquirer-textual>
37
61
  ```
62
+
63
+ ### Textual console
64
+
65
+ 1. Open the Textual Development Console:
66
+
67
+ ```shell
68
+ uv run textual console
69
+ ```
70
+
71
+ 2. Run application in development mode:
72
+
73
+ ```shell
74
+ uv run textual run --dev examples/prompt_pattern.py
75
+ ```
76
+
77
+ ### Static documentation
78
+
79
+ Generating the static documentation:
80
+
81
+ ```shell
82
+ uv run mkdocs build
83
+ ```
84
+
85
+ Viewing the static documentation:
86
+
87
+ ```shell
88
+ uv run mkdocs serve
89
+ ```
@@ -0,0 +1,30 @@
1
+ inquirer_textual/InquirerApp.py,sha256=ohFn5KpnZmd0AQVNRC3Ll3EMrXn-nwmedReb8sBRRsY,5979
2
+ inquirer_textual/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
+ inquirer_textual/prompts.py,sha256=lEVWbel8GvqRCgxGcp5ki_tSNMgVD84eaqawwySqwr4,4236
4
+ inquirer_textual/version.py,sha256=EqIccytbgmIh3EOfv7QIiksdjJSlB-o2LbyXxRtoMGs,18
5
+ inquirer_textual/common/AppConfig.py,sha256=z4PN75ABDQBg8QpRrJrWwL_PD5KEdx2lV1mlp6PEm7I,187
6
+ inquirer_textual/common/Choice.py,sha256=_0EGDbl6NGGiuOqCmfOkkmRX9IP09KQbRRmAdjPxwYs,203
7
+ inquirer_textual/common/ChoiceCheckboxLabel.py,sha256=BZg5vLe6_qc0ipYUaonNfygSOnHyJuEVrB8mmM6tOjw,675
8
+ inquirer_textual/common/ChoiceLabel.py,sha256=23ZtQ4FKPD4EdiuRPtTYPB4TOcQmNGq1JfoOlGowYZg,970
9
+ inquirer_textual/common/InquirerHeader.py,sha256=txl-TRe3DKsOPcmDKy1fhfTa-YAURsjTYePDDHzcPH8,802
10
+ inquirer_textual/common/InquirerResult.py,sha256=2inNdfc2xUTCUFqAGazKJJv6YUQjjFzn-f3NTDxm1-M,481
11
+ inquirer_textual/common/PromptMessage.py,sha256=MCXdsE9j0XlqVKjWUhXB-9qZ24Lk7dA5QWRgUWTdF8o,831
12
+ inquirer_textual/common/Shortcut.py,sha256=9mzLVnphImnehNo1HHU_gPMv-vFi5nXsb1G2CAbpuEY,297
13
+ inquirer_textual/common/StandardTheme.py,sha256=4y0HWIqKDTl1xT9i3TdzRWcDo1oDjvI6Wbzt_XBz2jI,233
14
+ inquirer_textual/common/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
+ inquirer_textual/widgets/InquirerCheckbox.py,sha256=84DoTtTLBL61dxJRTq23KPRZYPMcYF6rfT2B41A1gNA,3785
16
+ inquirer_textual/widgets/InquirerConfirm.py,sha256=oJSssC8L7_fWUqBJ46KLxwXajo8ZRVAdTNuxgWq-zvY,2432
17
+ inquirer_textual/widgets/InquirerEditor.py,sha256=n6SfKcaE2sNz8r_jvc9FvCWRyM8bHJcGj8Z5bQkgdnw,1999
18
+ inquirer_textual/widgets/InquirerMulti.py,sha256=wgrngSbbmJ4aTDig0_RTopYH8brTM4jPNvAKL7UZpZs,1754
19
+ inquirer_textual/widgets/InquirerNumber.py,sha256=mS5h0vi0W3q0JJwQxZEjAfoH-ARLoxMdrcffy9ANCSY,2120
20
+ inquirer_textual/widgets/InquirerPath.py,sha256=qiKkoWMS8yOVyOA82oezbrSvpUU4xIZxkOJMRR59FmY,3091
21
+ inquirer_textual/widgets/InquirerPattern.py,sha256=uyN6PchvPKOvQ7sSwYHnmDaplJMZwAVc7qnG7P0zCVo,6428
22
+ inquirer_textual/widgets/InquirerSecret.py,sha256=K2gZ-KsSjYZD-xPQa9PVqtlvIiQ17_X0ujGMnfBhWmo,1666
23
+ inquirer_textual/widgets/InquirerSelect.py,sha256=IsCDwLXTbzKMfwd-jjBdeRY3_734QOjoaJrjbGy3lMU,3237
24
+ inquirer_textual/widgets/InquirerText.py,sha256=xc21nreIFH-8YkuQfanQPsiLbLATfHVK7ggtTuWYU7Y,2316
25
+ inquirer_textual/widgets/InquirerWidget.py,sha256=TUU68Bef4A-S1bomgR0uFiVcQbfudrH-Vp9_h3WJgDg,1060
26
+ inquirer_textual/widgets/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
27
+ inquirer_textual-0.3.0.dist-info/METADATA,sha256=xdacOD3xrAWACJBJkN_jhPT4UNfGCGFW7v-Jz1Fhaps,2410
28
+ inquirer_textual-0.3.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
29
+ inquirer_textual-0.3.0.dist-info/licenses/LICENSE,sha256=fJuRou64yfkof3ZFdeHcgk7K8pqxis6SBr-vtUEgBuA,1073
30
+ inquirer_textual-0.3.0.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: hatchling 1.27.0
2
+ Generator: hatchling 1.28.0
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
@@ -1,13 +0,0 @@
1
- from dataclasses import dataclass
2
- from typing import TypeVar
3
-
4
- T = TypeVar('T')
5
-
6
-
7
- @dataclass
8
- class Result[T]:
9
- command: str | None
10
- value: T
11
-
12
- def __str__(self):
13
- return str(self.value)