Open sandrospadaro opened 1 year ago
Hi there, I created a PR that fixes the validation issue for input dialogs #1747.
Until the PR is merged you can make your own input_dialog
class that fixes the issue while using the base prompt-toolkit package
class CustomValidationToolbar:
def __init__(self, show_position: bool = False, buffer: Buffer = None) -> None:
def get_formatted_text() -> StyleAndTextTuples:
# If buffer not specified, use the currently focused buffer
if buffer is None:
buff = get_app().current_buffer
else:
buff = buffer
if buff.validation_error:
if show_position:
row, column = buff.document.translate_index_to_position(
buff.validation_error.cursor_position
)
text = "{} (line={} column={})".format(
buff.validation_error.message,
row + 1,
column + 1,
)
else:
text = buff.validation_error.message
return [("class:validation-toolbar", text)]
else:
return []
self.control = FormattedTextControl(get_formatted_text)
self.container = ConditionalContainer(
content=Window(self.control, height=1), filter=True
)
def __pt_container__(self) -> Container:
return self.container
def input_dialog(
title: AnyFormattedText = "",
text: AnyFormattedText = "",
ok_text: str = "OK",
cancel_text: str = "Cancel",
completer: Completer | None = None,
validator: Validator | None = None,
validate_while_typing: FilterOrBool = False,
password: FilterOrBool = False,
style: BaseStyle | None = None,
default: str = "",
) -> Application[str]:
def accept(buf: Buffer) -> bool:
get_app().layout.focus(ok_button)
return True # Keep text.
def ok_handler() -> None:
textfield.buffer.validate() # validate one final time before exiting
if textfield.buffer.validation_error is None:
get_app().exit(result=textfield.text)
ok_button = Button(text=ok_text, handler=ok_handler)
cancel_button = Button(text=cancel_text, handler=_return_none)
textfield = TextArea(
text=default,
multiline=False,
password=password,
completer=completer,
validator=validator,
accept_handler=accept,
)
textfield.buffer.validate_while_typing = validate_while_typing
dialog = Dialog(
title=title,
body=HSplit(
[
Label(text=text, dont_extend_height=True),
textfield,
CustomValidationToolbar(textfield.buffer),
],
padding=D(preferred=1, max=1),
),
buttons=[ok_button, cancel_button],
with_background=True,
)
return _create_app(dialog, style)
You can call input_dialog just as you normally would.
result = input_dialog(title='Input dialog example', text='Please type your name:').run()
The only difference is you can also now pass in the validate_while_typing
argument as well
result = input_dialog(title='Input dialog example',
text='Please type your favorite number:',
validator=NumberValidator(),
validate_while_typing=True
).run()
Validation does not work with input_dialog.
how to reproduce the issue
Fill the input dialog with some string (eg: abc) and press tab key to move focus on OK button. Then press enter key.
Output
Output expected
Error message on focus lost
About the environment