summaryrefslogtreecommitdiffstats
path: root/examples/full-screen/split-screen.py
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-04 17:35:20 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-04 17:35:20 +0000
commite106bf94eff07d9a59771d9ccc4406421e18ab64 (patch)
treeedb6545500e39df9c67aa918a6125bffc8ec1aee /examples/full-screen/split-screen.py
parentInitial commit. (diff)
downloadprompt-toolkit-upstream/3.0.36.tar.xz
prompt-toolkit-upstream/3.0.36.zip
Adding upstream version 3.0.36.upstream/3.0.36upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'examples/full-screen/split-screen.py')
-rwxr-xr-xexamples/full-screen/split-screen.py156
1 files changed, 156 insertions, 0 deletions
diff --git a/examples/full-screen/split-screen.py b/examples/full-screen/split-screen.py
new file mode 100755
index 0000000..fd654fb
--- /dev/null
+++ b/examples/full-screen/split-screen.py
@@ -0,0 +1,156 @@
+#!/usr/bin/env python
+"""
+Simple example of a full screen application with a vertical split.
+
+This will show a window on the left for user input. When the user types, the
+reversed input is shown on the right. Pressing Ctrl-Q will quit the application.
+"""
+from prompt_toolkit.application import Application
+from prompt_toolkit.buffer import Buffer
+from prompt_toolkit.key_binding import KeyBindings
+from prompt_toolkit.layout.containers import HSplit, VSplit, Window, WindowAlign
+from prompt_toolkit.layout.controls import BufferControl, FormattedTextControl
+from prompt_toolkit.layout.layout import Layout
+
+# 3. Create the buffers
+# ------------------
+
+left_buffer = Buffer()
+right_buffer = Buffer()
+
+# 1. First we create the layout
+# --------------------------
+
+left_window = Window(BufferControl(buffer=left_buffer))
+right_window = Window(BufferControl(buffer=right_buffer))
+
+
+body = VSplit(
+ [
+ left_window,
+ # A vertical line in the middle. We explicitly specify the width, to make
+ # sure that the layout engine will not try to divide the whole width by
+ # three for all these windows.
+ Window(width=1, char="|", style="class:line"),
+ # Display the Result buffer on the right.
+ right_window,
+ ]
+)
+
+# As a demonstration. Let's add a title bar to the top, displaying "Hello world".
+
+# somewhere, because usually the default key bindings include searching. (Press
+# Ctrl-R.) It would be really annoying if the search key bindings are handled,
+# but the user doesn't see any feedback. We will add the search toolbar to the
+# bottom by using an HSplit.
+
+
+def get_titlebar_text():
+ return [
+ ("class:title", " Hello world "),
+ ("class:title", " (Press [Ctrl-Q] to quit.)"),
+ ]
+
+
+root_container = HSplit(
+ [
+ # The titlebar.
+ Window(
+ height=1,
+ content=FormattedTextControl(get_titlebar_text),
+ align=WindowAlign.CENTER,
+ ),
+ # Horizontal separator.
+ Window(height=1, char="-", style="class:line"),
+ # The 'body', like defined above.
+ body,
+ ]
+)
+
+
+# 2. Adding key bindings
+# --------------------
+
+# As a demonstration, we will add just a ControlQ key binding to exit the
+# application. Key bindings are registered in a
+# `prompt_toolkit.key_bindings.registry.Registry` instance. We use the
+# `load_default_key_bindings` utility function to create a registry that
+# already contains the default key bindings.
+
+kb = KeyBindings()
+
+# Now add the Ctrl-Q binding. We have to pass `eager=True` here. The reason is
+# that there is another key *sequence* that starts with Ctrl-Q as well. Yes, a
+# key binding is linked to a sequence of keys, not necessarily one key. So,
+# what happens if there is a key binding for the letter 'a' and a key binding
+# for 'ab'. When 'a' has been pressed, nothing will happen yet. Because the
+# next key could be a 'b', but it could as well be anything else. If it's a 'c'
+# for instance, we'll handle the key binding for 'a' and then look for a key
+# binding for 'c'. So, when there's a common prefix in a key binding sequence,
+# prompt-toolkit will wait calling a handler, until we have enough information.
+
+# Now, There is an Emacs key binding for the [Ctrl-Q Any] sequence by default.
+# Pressing Ctrl-Q followed by any other key will do a quoted insert. So to be
+# sure that we won't wait for that key binding to match, but instead execute
+# Ctrl-Q immediately, we can pass eager=True. (Don't make a habit of adding
+# `eager=True` to all key bindings, but do it when it conflicts with another
+# existing key binding, and you definitely want to override that behaviour.
+
+
+@kb.add("c-c", eager=True)
+@kb.add("c-q", eager=True)
+def _(event):
+ """
+ Pressing Ctrl-Q or Ctrl-C will exit the user interface.
+
+ Setting a return value means: quit the event loop that drives the user
+ interface and return this value from the `Application.run()` call.
+
+ Note that Ctrl-Q does not work on all terminals. Sometimes it requires
+ executing `stty -ixon`.
+ """
+ event.app.exit()
+
+
+# Now we add an event handler that captures change events to the buffer on the
+# left. If the text changes over there, we'll update the buffer on the right.
+
+
+def default_buffer_changed(_):
+ """
+ When the buffer on the left changes, update the buffer on
+ the right. We just reverse the text.
+ """
+ right_buffer.text = left_buffer.text[::-1]
+
+
+left_buffer.on_text_changed += default_buffer_changed
+
+
+# 3. Creating an `Application` instance
+# ----------------------------------
+
+# This glues everything together.
+
+application = Application(
+ layout=Layout(root_container, focused_element=left_window),
+ key_bindings=kb,
+ # Let's add mouse support!
+ mouse_support=True,
+ # Using an alternate screen buffer means as much as: "run full screen".
+ # It switches the terminal to an alternate screen.
+ full_screen=True,
+)
+
+
+# 4. Run the application
+# -------------------
+
+
+def run():
+ # Run the interface. (This runs the event loop until Ctrl-Q is pressed.)
+ application.run()
+
+
+if __name__ == "__main__":
+ run()