Description
I have this application which has key bindings under normal circumstances. But when I press a certain key, I want to display a prompt where the user can enter some text. The key bindings should be disabled at this point. On pressing Enter, the input field should be hidden again, bindings re-enabled, and I should get the text to handle.
Based on this comment and the code it pointed to (thanks @rogerbassons!), I have come up with this… which almost works.
The conditional container is working well, and the TextArea
with the prompt prefix is showing when I use the /
key binding. The counter is counting, and the FormattedTextControl is updating on each keypress. The problem is that any text entered after /
never appears on screen. Perhaps it's being collected in some buffer, but I can't access it. The key bindings have been successfully disabled while the TextArea
is shown. But Enter doesn't work, so there's no way to get out of the dialog and back to the rest of the application and its key bindings. In fact, the acceptInput
method is never called.The app also doesn't respond to Ctrl-C or even Ctrl-Z. So entering this state completely locks up the terminal and I have to close the tab entirely.
I have to believe there's something simple that I'm missing, but this code looks the same to me as what's in the pwdmgr.py
file. Do I need to do something to give focus to the TextArea? What am I doing wrong??
from prompt_toolkit.application import Application
from prompt_toolkit.application.current import get_app
from prompt_toolkit.filters import Condition
from prompt_toolkit.key_binding import ConditionalKeyBindings, KeyBindings
from prompt_toolkit.layout import ConditionalContainer, DynamicContainer
from prompt_toolkit.layout.containers import HSplit, Window
from prompt_toolkit.layout.controls import FormattedTextControl
from prompt_toolkit.layout.layout import Layout
from prompt_toolkit.widgets import SearchToolbar, TextArea
show_input = False
@Condition
def inputHidden():
return not show_input
class Annotator:
def __init__(self):
self.counter = 1
self.string = ""
bindings = self.setupBindings()
application = Application(
key_bindings=bindings, full_screen=False, layout=self.layout()
)
application.run()
def layout(self):
def makeLayout():
global show_input
search_field = SearchToolbar() # Is this actually necessary?
self.input = TextArea(height=1, prompt="put it in> ", search_field=search_field)
self.input.accept_handler = self.acceptInput
windows = [
Window(FormattedTextControl(self.status()), height=1),
ConditionalContainer(content=self.input, filter=show_input),
]
return HSplit(windows)
return Layout(DynamicContainer(makeLayout))
def setupBindings(self):
kb = KeyBindings()
@kb.add("+")
def _(event):
self.addOne()
@kb.add("/")
def _(event):
self.showInput()
@kb.add("c-c")
@kb.add("q")
def _(event):
get_app().exit(result=True)
return ConditionalKeyBindings(kb, inputHidden)
def addOne(self):
self.counter += 1
def status(self):
return f"{self.counter} - '{self.string}'"
def showInput(self):
global show_input
show_input = True
def acceptInput(self, buffer):
global show_input
show_input = False
self.string = self.input.text
return False # reset the buffer
if __name__ == "__main__":
Annotator()