Skip to content

Commit 0218f5c

Browse files
committed
Update Input Dialog to use Validator
1 parent 564ff54 commit 0218f5c

File tree

4 files changed

+50
-11
lines changed

4 files changed

+50
-11
lines changed

Diff for: src/prompt_toolkit/filters/app.py

+27
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
"has_selection",
2525
"has_suggestion",
2626
"has_validation_error",
27+
"has_any_validation_error",
2728
"is_done",
2829
"is_read_only",
2930
"is_multiline",
@@ -170,6 +171,32 @@ def has_validation_error() -> bool:
170171
return get_app().current_buffer.validation_error is not None
171172

172173

174+
@Condition
175+
def has_any_validation_error() -> bool:
176+
"Any buffer in the layout has validation error."
177+
from prompt_toolkit.layout.containers import Window
178+
from prompt_toolkit.layout.controls import (
179+
BufferControl,
180+
SearchBufferControl,
181+
UIControl,
182+
)
183+
184+
# Extract buffer validation errors for buffer UIControl children classes
185+
def get_buffer_from_content(content: UIControl) -> bool:
186+
if isinstance(content, (BufferControl, SearchBufferControl)):
187+
return content.buffer.validation_error is not None
188+
else:
189+
return False
190+
# Get all windows for the current layout
191+
windows = get_app().layout.find_all_windows()
192+
# Iterate over each window in the layout and return true if any of the buffers have validation errors
193+
for window in windows:
194+
if isinstance(window, Window):
195+
if get_buffer_from_content(window.content):
196+
return True
197+
return False
198+
199+
173200
@Condition
174201
def has_arg() -> bool:
175202
"Enable when the input processor has an 'arg'."

Diff for: src/prompt_toolkit/shortcuts/dialogs.py

+6-2
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ def input_dialog(
110110
cancel_text: str = "Cancel",
111111
completer: Completer | None = None,
112112
validator: Validator | None = None,
113+
validate_while_typing: FilterOrBool = False,
113114
password: FilterOrBool = False,
114115
style: BaseStyle | None = None,
115116
default: str = "",
@@ -124,7 +125,9 @@ def accept(buf: Buffer) -> bool:
124125
return True # Keep text.
125126

126127
def ok_handler() -> None:
127-
get_app().exit(result=textfield.text)
128+
textfield.buffer.validate() # validate one final time before exiting
129+
if textfield.buffer.validation_error is None:
130+
get_app().exit(result=textfield.text)
128131

129132
ok_button = Button(text=ok_text, handler=ok_handler)
130133
cancel_button = Button(text=cancel_text, handler=_return_none)
@@ -135,6 +138,7 @@ def ok_handler() -> None:
135138
password=password,
136139
completer=completer,
137140
validator=validator,
141+
validate_while_typing=validate_while_typing,
138142
accept_handler=accept,
139143
)
140144

@@ -144,7 +148,7 @@ def ok_handler() -> None:
144148
[
145149
Label(text=text, dont_extend_height=True),
146150
textfield,
147-
ValidationToolbar(),
151+
ValidationToolbar(buffer=textfield.buffer),
148152
],
149153
padding=D(preferred=1, max=1),
150154
),

Diff for: src/prompt_toolkit/widgets/base.py

+5
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,7 @@ def __init__(
179179
completer: Completer | None = None,
180180
complete_while_typing: FilterOrBool = True,
181181
validator: Validator | None = None,
182+
validate_while_typing: FilterOrBool = False,
182183
accept_handler: BufferAcceptHandler | None = None,
183184
history: History | None = None,
184185
focusable: FilterOrBool = True,
@@ -215,6 +216,7 @@ def __init__(
215216
self.read_only = read_only
216217
self.wrap_lines = wrap_lines
217218
self.validator = validator
219+
self.validate_while_typing = validate_while_typing
218220

219221
self.buffer = Buffer(
220222
document=Document(text, 0),
@@ -225,6 +227,9 @@ def __init__(
225227
lambda: is_true(self.complete_while_typing)
226228
),
227229
validator=DynamicValidator(lambda: self.validator),
230+
validate_while_typing=Condition(
231+
lambda: is_true(self.validate_while_typing)
232+
),
228233
auto_suggest=DynamicAutoSuggest(lambda: self.auto_suggest),
229234
accept_handler=accept_handler,
230235
history=history,

Diff for: src/prompt_toolkit/widgets/toolbars.py

+12-9
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@
99
Condition,
1010
FilterOrBool,
1111
emacs_mode,
12+
has_any_validation_error,
1213
has_arg,
1314
has_completions,
1415
has_focus,
15-
has_validation_error,
1616
to_filter,
1717
vi_mode,
1818
vi_navigation_mode,
@@ -342,16 +342,19 @@ def __pt_container__(self) -> Container:
342342

343343

344344
class ValidationToolbar:
345-
def __init__(self, show_position: bool = False) -> None:
345+
def __init__(self, show_position: bool = False, buffer: Buffer | None = None) -> None:
346346
def get_formatted_text() -> StyleAndTextTuples:
347-
buff = get_app().current_buffer
348-
347+
# If buffer not specified, use the currently focused buffer
348+
if buffer is None:
349+
buff = get_app().current_buffer
350+
else:
351+
buff = buffer
349352
if buff.validation_error:
350-
row, column = buff.document.translate_index_to_position(
351-
buff.validation_error.cursor_position
352-
)
353-
354353
if show_position:
354+
row, column = buff.document.translate_index_to_position(
355+
buff.validation_error.cursor_position
356+
)
357+
355358
text = "{} (line={} column={})".format(
356359
buff.validation_error.message,
357360
row + 1,
@@ -367,7 +370,7 @@ def get_formatted_text() -> StyleAndTextTuples:
367370
self.control = FormattedTextControl(get_formatted_text)
368371

369372
self.container = ConditionalContainer(
370-
content=Window(self.control, height=1), filter=has_validation_error
373+
content=Window(self.control, height=1), filter=has_any_validation_error
371374
)
372375

373376
def __pt_container__(self) -> Container:

0 commit comments

Comments
 (0)