summaryrefslogtreecommitdiffstats
path: root/examples/full-screen
diff options
context:
space:
mode:
Diffstat (limited to 'examples/full-screen')
-rwxr-xr-xexamples/full-screen/ansi-art-and-textarea.py90
-rwxr-xr-xexamples/full-screen/buttons.py91
-rwxr-xr-xexamples/full-screen/calculator.py98
-rwxr-xr-xexamples/full-screen/dummy-app.py8
-rwxr-xr-xexamples/full-screen/full-screen-demo.py225
-rwxr-xr-xexamples/full-screen/hello-world.py43
-rw-r--r--examples/full-screen/no-layout.py7
-rwxr-xr-xexamples/full-screen/pager.py111
-rw-r--r--examples/full-screen/scrollable-panes/simple-example.py45
-rw-r--r--examples/full-screen/scrollable-panes/with-completion-menu.py120
-rwxr-xr-xexamples/full-screen/simple-demos/alignment.py60
-rwxr-xr-xexamples/full-screen/simple-demos/autocompletion.py100
-rwxr-xr-xexamples/full-screen/simple-demos/colorcolumn.py63
-rwxr-xr-xexamples/full-screen/simple-demos/cursorcolumn-cursorline.py59
-rwxr-xr-xexamples/full-screen/simple-demos/float-transparency.py87
-rwxr-xr-xexamples/full-screen/simple-demos/floats.py116
-rwxr-xr-xexamples/full-screen/simple-demos/focus.py98
-rwxr-xr-xexamples/full-screen/simple-demos/horizontal-align.py209
-rwxr-xr-xexamples/full-screen/simple-demos/horizontal-split.py44
-rwxr-xr-xexamples/full-screen/simple-demos/line-prefixes.py111
-rwxr-xr-xexamples/full-screen/simple-demos/margins.py71
-rwxr-xr-xexamples/full-screen/simple-demos/vertical-align.py168
-rwxr-xr-xexamples/full-screen/simple-demos/vertical-split.py44
-rwxr-xr-xexamples/full-screen/split-screen.py156
-rwxr-xr-xexamples/full-screen/text-editor.py383
25 files changed, 2607 insertions, 0 deletions
diff --git a/examples/full-screen/ansi-art-and-textarea.py b/examples/full-screen/ansi-art-and-textarea.py
new file mode 100755
index 0000000..ee6d93d
--- /dev/null
+++ b/examples/full-screen/ansi-art-and-textarea.py
@@ -0,0 +1,90 @@
+#!/usr/bin/env python
+
+from prompt_toolkit.application import Application
+from prompt_toolkit.formatted_text import ANSI, HTML
+from prompt_toolkit.key_binding import KeyBindings
+from prompt_toolkit.layout import (
+ FormattedTextControl,
+ HSplit,
+ Layout,
+ VSplit,
+ Window,
+ WindowAlign,
+)
+from prompt_toolkit.layout.dimension import D
+from prompt_toolkit.widgets import Dialog, Label, TextArea
+
+
+def main():
+ # Key bindings.
+ kb = KeyBindings()
+
+ @kb.add("c-c")
+ def _(event):
+ "Quit when control-c is pressed."
+ event.app.exit()
+
+ text_area = TextArea(text="You can type here...")
+ dialog_body = HSplit(
+ [
+ Label(
+ HTML("Press <reverse>control-c</reverse> to quit."),
+ align=WindowAlign.CENTER,
+ ),
+ VSplit(
+ [
+ Label(PROMPT_TOOLKIT_LOGO, align=WindowAlign.CENTER),
+ text_area,
+ ],
+ ),
+ ]
+ )
+
+ application = Application(
+ layout=Layout(
+ container=Dialog(
+ title="ANSI Art demo - Art on the left, text area on the right",
+ body=dialog_body,
+ with_background=True,
+ ),
+ focused_element=text_area,
+ ),
+ full_screen=True,
+ mouse_support=True,
+ key_bindings=kb,
+ )
+ application.run()
+
+
+PROMPT_TOOLKIT_LOGO = ANSI(
+ """
+\x1b[48;2;0;0;0m \x1b[m
+\x1b[48;2;0;0;0m \x1b[48;2;0;249;0m\x1b[38;2;0;0;0m▀\x1b[48;2;0;209;0m▀\x1b[48;2;0;207;0m\x1b[38;2;6;34;6m▀\x1b[48;2;0;66;0m\x1b[38;2;30;171;30m▀\x1b[48;2;0;169;0m\x1b[38;2;51;35;51m▀\x1b[48;2;0;248;0m\x1b[38;2;49;194;49m▀\x1b[48;2;0;111;0m\x1b[38;2;25;57;25m▀\x1b[48;2;140;195;140m\x1b[38;2;3;17;3m▀\x1b[48;2;30;171;30m\x1b[38;2;0;0;0m▀\x1b[48;2;0;0;0m \x1b[m
+\x1b[48;2;0;0;0m \x1b[48;2;77;127;78m\x1b[38;2;118;227;108m▀\x1b[48;2;216;1;13m\x1b[38;2;49;221;57m▀\x1b[48;2;26;142;76m\x1b[38;2;108;146;165m▀\x1b[48;2;26;142;90m\x1b[38;2;209;197;114m▀▀\x1b[38;2;209;146;114m▀\x1b[48;2;26;128;90m\x1b[38;2;158;197;114m▀\x1b[48;2;58;210;70m\x1b[38;2;223;152;89m▀\x1b[48;2;232;139;44m\x1b[38;2;97;121;146m▀\x1b[48;2;233;139;45m\x1b[38;2;140;188;183m▀\x1b[48;2;231;139;44m\x1b[38;2;40;168;8m▀\x1b[48;2;228;140;44m\x1b[38;2;37;169;7m▀\x1b[48;2;227;140;44m\x1b[38;2;36;169;7m▀\x1b[48;2;211;142;41m\x1b[38;2;23;171;5m▀\x1b[48;2;86;161;17m\x1b[38;2;2;174;1m▀\x1b[48;2;0;175;0m \x1b[48;2;0;254;0m\x1b[38;2;190;119;190m▀\x1b[48;2;92;39;23m\x1b[38;2;125;50;114m▀\x1b[48;2;43;246;41m\x1b[38;2;49;10;165m▀\x1b[48;2;12;128;90m\x1b[38;2;209;197;114m▀\x1b[48;2;26;128;90m▀▀▀▀\x1b[48;2;26;128;76m▀\x1b[48;2;26;128;90m\x1b[38;2;209;247;114m▀▀\x1b[38;2;209;197;114m▀\x1b[48;2;26;128;76m\x1b[38;2;209;247;114m▀\x1b[48;2;26;128;90m▀▀▀\x1b[48;2;26;128;76m▀\x1b[48;2;26;128;90m▀▀\x1b[48;2;12;128;76m▀\x1b[48;2;12;113;90m\x1b[38;2;209;247;64m▀\x1b[38;2;209;247;114m▀\x1b[48;2;12;128;90m▀\x1b[48;2;12;113;90m▀\x1b[48;2;12;113;76m\x1b[38;2;209;247;64m▀\x1b[48;2;12;128;90m▀\x1b[48;2;12;113;90m▀\x1b[48;2;12;113;76m\x1b[38;2;209;247;114m▀\x1b[48;2;12;113;90m\x1b[38;2;209;247;64m▀\x1b[48;2;26;128;90m\x1b[38;2;151;129;163m▀\x1b[48;2;115;120;103m\x1b[38;2;62;83;227m▀\x1b[48;2;138;14;25m\x1b[38;2;104;106;160m▀\x1b[48;2;0;0;57m\x1b[38;2;0;0;0m▀\x1b[m
+\x1b[48;2;249;147;8m\x1b[38;2;172;69;38m▀\x1b[48;2;197;202;10m\x1b[38;2;82;192;58m▀\x1b[48;2;248;124;45m\x1b[38;2;251;131;47m▀\x1b[48;2;248;124;44m▀\x1b[48;2;248;124;45m▀▀\x1b[48;2;248;124;44m▀\x1b[48;2;248;124;45m▀\x1b[48;2;248;125;45m\x1b[38;2;251;130;47m▀\x1b[48;2;248;124;45m\x1b[38;2;252;130;47m▀\x1b[48;2;248;125;45m\x1b[38;2;252;131;47m▀\x1b[38;2;252;130;47m▀\x1b[38;2;252;131;47m▀▀\x1b[48;2;249;125;45m\x1b[38;2;255;130;48m▀\x1b[48;2;233;127;42m\x1b[38;2;190;141;35m▀\x1b[48;2;57;163;10m\x1b[38;2;13;172;3m▀\x1b[48;2;0;176;0m\x1b[38;2;0;175;0m▀\x1b[48;2;7;174;1m\x1b[38;2;35;169;7m▀\x1b[48;2;178;139;32m\x1b[38;2;220;136;41m▀\x1b[48;2;252;124;45m\x1b[38;2;253;131;47m▀\x1b[48;2;248;125;45m\x1b[38;2;251;131;47m▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀\x1b[48;2;248;125;44m▀\x1b[48;2;248;135;61m\x1b[38;2;251;132;48m▀\x1b[48;2;250;173;122m\x1b[38;2;251;133;50m▀\x1b[48;2;249;155;93m\x1b[38;2;251;132;49m▀\x1b[48;2;248;132;55m\x1b[38;2;251;132;48m▀\x1b[48;2;250;173;122m\x1b[38;2;251;134;51m▀\x1b[48;2;250;163;106m\x1b[38;2;251;134;50m▀\x1b[48;2;248;128;49m\x1b[38;2;251;132;47m▀\x1b[48;2;250;166;110m\x1b[38;2;251;135;52m▀\x1b[48;2;250;175;125m\x1b[38;2;251;136;54m▀\x1b[48;2;248;132;56m\x1b[38;2;251;132;48m▀\x1b[48;2;248;220;160m\x1b[38;2;105;247;172m▀\x1b[48;2;62;101;236m\x1b[38;2;11;207;160m▀\x1b[m
+\x1b[48;2;138;181;197m\x1b[38;2;205;36;219m▀\x1b[48;2;177;211;200m\x1b[38;2;83;231;105m▀\x1b[48;2;242;113;40m\x1b[38;2;245;119;42m▀\x1b[48;2;243;113;41m▀\x1b[48;2;245;114;41m▀▀▀▀▀▀▀▀\x1b[38;2;245;119;43m▀▀▀\x1b[48;2;247;114;41m\x1b[38;2;246;119;43m▀\x1b[48;2;202;125;34m\x1b[38;2;143;141;25m▀\x1b[48;2;84;154;14m\x1b[38;2;97;152;17m▀\x1b[48;2;36;166;6m▀\x1b[48;2;139;140;23m\x1b[38;2;183;133;32m▀\x1b[48;2;248;114;41m\x1b[38;2;248;118;43m▀\x1b[48;2;245;115;41m\x1b[38;2;245;119;43m▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀\x1b[38;2;245;119;42m▀\x1b[48;2;246;117;44m\x1b[38;2;246;132;62m▀\x1b[48;2;246;123;54m\x1b[38;2;249;180;138m▀\x1b[48;2;246;120;49m\x1b[38;2;247;157;102m▀\x1b[48;2;246;116;42m\x1b[38;2;246;127;54m▀\x1b[48;2;246;121;50m\x1b[38;2;248;174;128m▀\x1b[48;2;246;120;48m\x1b[38;2;248;162;110m▀\x1b[48;2;246;116;41m\x1b[38;2;245;122;47m▀\x1b[48;2;246;118;46m\x1b[38;2;248;161;108m▀\x1b[48;2;244;118;47m\x1b[38;2;248;171;123m▀\x1b[48;2;243;115;42m\x1b[38;2;246;127;54m▀\x1b[48;2;179;52;29m\x1b[38;2;86;152;223m▀\x1b[48;2;141;225;95m\x1b[38;2;247;146;130m▀\x1b[m
+\x1b[48;2;50;237;108m\x1b[38;2;94;70;153m▀\x1b[48;2;206;221;133m\x1b[38;2;64;240;39m▀\x1b[48;2;233;100;36m\x1b[38;2;240;107;38m▀\x1b[48;2;114;56;22m\x1b[38;2;230;104;37m▀\x1b[48;2;24;20;10m\x1b[38;2;193;90;33m▀\x1b[48;2;21;19;9m\x1b[38;2;186;87;32m▀▀▀▀▀▀▀\x1b[38;2;186;87;33m▀▀▀\x1b[48;2;22;18;10m\x1b[38;2;189;86;33m▀\x1b[48;2;18;36;8m\x1b[38;2;135;107;24m▀\x1b[48;2;3;153;2m\x1b[38;2;5;171;1m▀\x1b[48;2;0;177;0m \x1b[48;2;4;158;2m\x1b[38;2;69;147;12m▀\x1b[48;2;19;45;8m\x1b[38;2;185;89;32m▀\x1b[48;2;22;17;10m\x1b[38;2;186;87;33m▀\x1b[48;2;21;19;9m▀▀▀▀▀▀▀▀\x1b[48;2;21;19;10m▀▀\x1b[48;2;21;19;9m▀▀▀▀\x1b[48;2;21;19;10m▀▀▀\x1b[38;2;186;87;32m▀▀\x1b[48;2;21;19;9m\x1b[38;2;186;87;33m▀\x1b[48;2;21;19;10m\x1b[38;2;186;87;32m▀▀\x1b[48;2;21;19;9m\x1b[38;2;186;87;33m▀\x1b[48;2;22;19;10m\x1b[38;2;191;89;33m▀\x1b[48;2;95;49;20m\x1b[38;2;226;103;37m▀\x1b[48;2;227;99;36m\x1b[38;2;241;109;39m▀\x1b[48;2;80;140;154m\x1b[38;2;17;240;92m▀\x1b[48;2;221;58;175m\x1b[38;2;71;14;245m▀\x1b[m
+\x1b[48;2;195;38;42m\x1b[38;2;5;126;86m▀\x1b[48;2;139;230;67m\x1b[38;2;253;201;228m▀\x1b[48;2;208;82;30m\x1b[38;2;213;89;32m▀\x1b[48;2;42;26;12m\x1b[38;2;44;27;12m▀\x1b[48;2;9;14;7m\x1b[38;2;8;13;7m▀\x1b[48;2;11;15;8m\x1b[38;2;10;14;7m▀▀▀▀▀▀▀▀▀▀▀\x1b[48;2;11;12;8m\x1b[38;2;10;17;7m▀\x1b[48;2;7;71;5m\x1b[38;2;4;120;3m▀\x1b[48;2;1;164;1m\x1b[38;2;0;178;0m▀\x1b[48;2;4;118;3m\x1b[38;2;0;177;0m▀\x1b[48;2;5;108;3m\x1b[38;2;4;116;3m▀\x1b[48;2;7;75;5m\x1b[38;2;10;23;7m▀\x1b[48;2;10;33;7m\x1b[38;2;10;12;7m▀\x1b[48;2;11;13;8m\x1b[38;2;10;14;7m▀\x1b[48;2;11;14;8m▀\x1b[48;2;11;15;8m▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀\x1b[48;2;10;14;7m\x1b[38;2;9;14;7m▀\x1b[48;2;30;21;10m\x1b[38;2;30;22;10m▀\x1b[48;2;195;79;29m\x1b[38;2;200;84;31m▀\x1b[48;2;205;228;23m\x1b[38;2;111;40;217m▀\x1b[48;2;9;217;69m\x1b[38;2;115;137;104m▀\x1b[m
+\x1b[48;2;106;72;209m\x1b[38;2;151;183;253m▀\x1b[48;2;120;239;0m\x1b[38;2;25;2;162m▀\x1b[48;2;203;72;26m\x1b[38;2;206;77;28m▀\x1b[48;2;42;24;11m\x1b[38;2;42;25;11m▀\x1b[48;2;9;14;7m \x1b[48;2;11;15;8m \x1b[38;2;11;14;8m▀\x1b[48;2;11;13;8m\x1b[38;2;10;28;7m▀\x1b[48;2;9;36;6m\x1b[38;2;7;78;5m▀\x1b[48;2;2;153;1m\x1b[38;2;6;94;4m▀\x1b[48;2;0;178;0m\x1b[38;2;2;156;1m▀\x1b[48;2;0;175;0m\x1b[38;2;1;167;1m▀\x1b[48;2;0;177;0m\x1b[38;2;2;145;2m▀\x1b[48;2;2;147;2m\x1b[38;2;8;54;6m▀\x1b[48;2;9;38;6m\x1b[38;2;11;13;8m▀\x1b[48;2;11;13;8m\x1b[38;2;11;14;8m▀\x1b[48;2;11;15;8m \x1b[48;2;10;14;7m \x1b[48;2;29;20;10m\x1b[38;2;29;21;10m▀\x1b[48;2;190;69;25m\x1b[38;2;193;74;27m▀\x1b[48;2;136;91;148m\x1b[38;2;42;159;86m▀\x1b[48;2;89;85;149m\x1b[38;2;160;5;219m▀\x1b[m
+\x1b[48;2;229;106;143m\x1b[38;2;40;239;187m▀\x1b[48;2;196;134;237m\x1b[38;2;6;11;95m▀\x1b[48;2;197;60;22m\x1b[38;2;201;67;24m▀\x1b[48;2;41;22;10m\x1b[38;2;41;23;11m▀\x1b[48;2;9;14;7m \x1b[48;2;11;15;8m \x1b[48;2;10;14;7m\x1b[38;2;11;15;8m▀▀\x1b[48;2;11;15;8m \x1b[38;2;11;14;8m▀\x1b[48;2;11;14;8m\x1b[38;2;11;16;7m▀\x1b[48;2;11;15;7m\x1b[38;2;7;79;5m▀\x1b[48;2;7;68;5m\x1b[38;2;1;164;1m▀\x1b[48;2;2;153;1m\x1b[38;2;0;176;0m▀\x1b[48;2;2;154;1m\x1b[38;2;0;175;0m▀\x1b[48;2;5;107;3m\x1b[38;2;1;171;1m▀\x1b[48;2;4;115;3m\x1b[38;2;5;105;3m▀\x1b[48;2;6;84;4m\x1b[38;2;11;18;7m▀\x1b[48;2;10;30;7m\x1b[38;2;11;13;8m▀\x1b[48;2;11;13;8m\x1b[38;2;11;15;8m▀\x1b[48;2;11;14;8m▀\x1b[48;2;11;15;8m \x1b[48;2;10;14;7m \x1b[48;2;29;19;9m\x1b[38;2;29;20;10m▀\x1b[48;2;185;58;22m\x1b[38;2;188;64;24m▀\x1b[48;2;68;241;49m\x1b[38;2;199;22;211m▀\x1b[48;2;133;139;8m\x1b[38;2;239;129;78m▀\x1b[m
+\x1b[48;2;74;30;32m\x1b[38;2;163;185;76m▀\x1b[48;2;110;172;9m\x1b[38;2;177;1;123m▀\x1b[48;2;189;43;16m\x1b[38;2;193;52;19m▀\x1b[48;2;39;20;9m\x1b[38;2;40;21;10m▀\x1b[48;2;9;14;7m \x1b[48;2;11;15;8m \x1b[48;2;11;14;7m\x1b[38;2;11;15;8m▀\x1b[48;2;9;14;7m\x1b[38;2;11;14;8m▀\x1b[48;2;106;54;38m\x1b[38;2;31;24;15m▀\x1b[48;2;164;71;49m\x1b[38;2;24;20;12m▀\x1b[48;2;94;46;31m\x1b[38;2;8;14;7m▀\x1b[48;2;36;24;15m\x1b[38;2;9;14;7m▀\x1b[48;2;11;15;8m\x1b[38;2;11;14;7m▀\x1b[48;2;8;14;7m\x1b[38;2;11;15;8m▀\x1b[48;2;10;14;7m▀\x1b[48;2;11;15;8m \x1b[38;2;11;14;8m▀\x1b[48;2;11;14;8m\x1b[38;2;11;13;8m▀\x1b[48;2;11;13;8m\x1b[38;2;9;45;6m▀\x1b[48;2;10;19;7m\x1b[38;2;7;75;5m▀\x1b[48;2;6;83;4m\x1b[38;2;2;143;2m▀\x1b[48;2;2;156;1m\x1b[38;2;0;176;0m▀\x1b[48;2;0;177;0m\x1b[38;2;0;175;0m▀\x1b[38;2;3;134;2m▀\x1b[48;2;2;152;1m\x1b[38;2;9;46;6m▀\x1b[48;2;8;60;5m\x1b[38;2;11;13;8m▀\x1b[48;2;11;14;7m\x1b[38;2;11;14;8m▀\x1b[48;2;11;14;8m\x1b[38;2;11;15;8m▀\x1b[48;2;11;15;8m \x1b[48;2;10;14;7m \x1b[48;2;28;18;9m \x1b[48;2;177;43;16m\x1b[38;2;181;51;19m▀\x1b[48;2;93;35;236m\x1b[38;2;224;10;142m▀\x1b[48;2;72;51;52m\x1b[38;2;213;112;158m▀\x1b[m
+\x1b[48;2;175;209;155m\x1b[38;2;7;131;221m▀\x1b[48;2;24;0;85m\x1b[38;2;44;86;152m▀\x1b[48;2;181;27;10m\x1b[38;2;185;35;13m▀\x1b[48;2;38;17;8m\x1b[38;2;39;18;9m▀\x1b[48;2;9;14;7m \x1b[48;2;11;15;8m \x1b[48;2;11;14;7m \x1b[48;2;9;14;7m \x1b[48;2;87;43;32m\x1b[38;2;114;54;39m▀\x1b[48;2;188;71;54m\x1b[38;2;211;82;59m▀\x1b[48;2;203;73;55m\x1b[38;2;204;80;57m▀\x1b[48;2;205;73;55m\x1b[38;2;178;71;51m▀\x1b[48;2;204;74;55m\x1b[38;2;119;52;37m▀\x1b[48;2;188;69;52m\x1b[38;2;54;29;19m▀\x1b[48;2;141;55;41m\x1b[38;2;16;17;9m▀\x1b[48;2;75;35;24m\x1b[38;2;8;14;7m▀\x1b[48;2;26;20;12m\x1b[38;2;10;14;7m▀\x1b[48;2;9;14;7m\x1b[38;2;11;14;7m▀\x1b[38;2;11;15;8m▀\x1b[48;2;11;14;7m▀\x1b[48;2;11;15;8m \x1b[38;2;11;14;8m▀\x1b[48;2;11;14;8m \x1b[48;2;11;13;8m\x1b[38;2;9;45;6m▀\x1b[48;2;10;23;7m\x1b[38;2;4;123;3m▀\x1b[48;2;7;75;5m\x1b[38;2;1;172;1m▀\x1b[48;2;6;84;4m\x1b[38;2;2;154;1m▀\x1b[48;2;4;114;3m\x1b[38;2;5;107;3m▀\x1b[48;2;5;103;4m\x1b[38;2;10;29;7m▀\x1b[48;2;10;23;7m\x1b[38;2;11;13;8m▀\x1b[48;2;11;14;8m\x1b[38;2;11;15;8m▀\x1b[48;2;11;15;8m \x1b[48;2;10;14;7m \x1b[48;2;27;16;8m\x1b[38;2;27;17;9m▀\x1b[48;2;170;27;10m\x1b[38;2;174;35;13m▀\x1b[48;2;118;117;199m\x1b[38;2;249;61;74m▀\x1b[48;2;10;219;61m\x1b[38;2;187;245;202m▀\x1b[m
+\x1b[48;2;20;155;44m\x1b[38;2;86;54;110m▀\x1b[48;2;195;85;113m\x1b[38;2;214;171;227m▀\x1b[48;2;173;10;4m\x1b[38;2;177;19;7m▀\x1b[48;2;37;14;7m\x1b[38;2;37;16;8m▀\x1b[48;2;9;15;8m\x1b[38;2;9;14;7m▀\x1b[48;2;11;15;8m \x1b[38;2;11;14;7m▀\x1b[48;2;11;14;7m\x1b[38;2;15;17;9m▀\x1b[48;2;9;14;7m\x1b[38;2;50;29;20m▀\x1b[48;2;10;15;8m\x1b[38;2;112;47;36m▀\x1b[48;2;33;22;15m\x1b[38;2;170;61;48m▀\x1b[48;2;88;38;29m\x1b[38;2;197;66;53m▀\x1b[48;2;151;53;43m\x1b[38;2;201;67;53m▀\x1b[48;2;189;60;50m▀\x1b[48;2;198;60;51m\x1b[38;2;194;65;52m▀\x1b[38;2;160;56;44m▀\x1b[48;2;196;60;50m\x1b[38;2;99;40;30m▀\x1b[48;2;174;55;47m\x1b[38;2;41;24;16m▀\x1b[48;2;122;43;35m\x1b[38;2;12;15;8m▀\x1b[48;2;59;27;20m\x1b[38;2;8;14;7m▀\x1b[48;2;16;16;9m\x1b[38;2;10;14;7m▀\x1b[48;2;10;14;7m\x1b[38;2;11;15;8m▀\x1b[48;2;11;15;8m \x1b[38;2;11;14;8m▀\x1b[48;2;11;14;8m\x1b[38;2;11;12;8m▀\x1b[48;2;10;25;7m\x1b[38;2;7;79;5m▀\x1b[48;2;3;141;2m\x1b[38;2;1;174;1m▀\x1b[48;2;0;178;0m\x1b[38;2;1;169;1m▀\x1b[48;2;6;88;4m\x1b[38;2;8;56;6m▀\x1b[48;2;11;12;8m \x1b[48;2;11;14;8m\x1b[38;2;11;15;8m▀\x1b[48;2;11;15;8m \x1b[48;2;10;14;7m \x1b[48;2;26;15;8m\x1b[38;2;27;15;8m▀\x1b[48;2;162;12;5m\x1b[38;2;166;20;8m▀\x1b[48;2;143;168;130m\x1b[38;2;18;142;37m▀\x1b[48;2;240;96;105m\x1b[38;2;125;158;211m▀\x1b[m
+\x1b[48;2;54;0;0m\x1b[38;2;187;22;0m▀\x1b[48;2;204;0;0m\x1b[38;2;128;208;0m▀\x1b[48;2;162;1;1m\x1b[38;2;168;3;1m▀\x1b[48;2;35;13;7m\x1b[38;2;36;13;7m▀\x1b[48;2;9;15;8m \x1b[48;2;11;15;8m \x1b[38;2;11;14;7m▀\x1b[38;2;9;14;7m▀\x1b[38;2;8;14;7m▀\x1b[48;2;10;14;7m\x1b[38;2;21;18;11m▀\x1b[48;2;7;13;6m\x1b[38;2;65;30;23m▀\x1b[48;2;12;16;9m\x1b[38;2;129;45;38m▀\x1b[48;2;57;29;23m\x1b[38;2;176;53;47m▀\x1b[48;2;148;49;44m\x1b[38;2;191;53;48m▀\x1b[48;2;187;52;48m\x1b[38;2;192;53;48m▀\x1b[48;2;186;51;47m\x1b[38;2;194;54;49m▀\x1b[48;2;182;52;47m\x1b[38;2;178;52;46m▀\x1b[48;2;59;27;21m\x1b[38;2;53;26;19m▀\x1b[48;2;8;14;7m \x1b[48;2;11;15;8m \x1b[48;2;11;14;8m\x1b[38;2;11;15;8m▀\x1b[48;2;11;12;8m\x1b[38;2;11;14;8m▀\x1b[48;2;10;30;7m\x1b[38;2;10;23;7m▀\x1b[48;2;5;110;3m\x1b[38;2;3;138;2m▀\x1b[48;2;2;149;2m\x1b[38;2;0;181;0m▀\x1b[48;2;6;92;4m\x1b[38;2;5;100;4m▀\x1b[48;2;11;13;8m \x1b[48;2;11;14;8m \x1b[48;2;11;15;8m \x1b[48;2;10;15;8m \x1b[48;2;25;14;7m\x1b[38;2;26;14;7m▀\x1b[48;2;152;2;1m\x1b[38;2;158;5;2m▀\x1b[48;2;6;0;0m\x1b[38;2;44;193;0m▀\x1b[48;2;108;0;0m\x1b[38;2;64;70;0m▀\x1b[m
+\x1b[48;2;44;0;0m\x1b[38;2;177;0;0m▀\x1b[48;2;147;0;0m\x1b[38;2;71;0;0m▀\x1b[48;2;148;1;1m\x1b[38;2;155;1;1m▀\x1b[48;2;33;13;7m\x1b[38;2;34;13;7m▀\x1b[48;2;9;15;8m \x1b[48;2;11;15;8m \x1b[48;2;11;14;7m\x1b[38;2;11;15;8m▀\x1b[48;2;10;14;7m▀\x1b[48;2;9;14;7m▀\x1b[48;2;13;16;9m\x1b[38;2;11;14;7m▀\x1b[48;2;42;24;17m\x1b[38;2;9;14;7m▀\x1b[48;2;97;38;32m\x1b[38;2;10;15;8m▀\x1b[48;2;149;49;44m\x1b[38;2;30;21;14m▀\x1b[48;2;174;52;48m\x1b[38;2;79;34;28m▀\x1b[48;2;178;52;48m\x1b[38;2;136;45;40m▀\x1b[38;2;172;51;47m▀\x1b[48;2;173;52;48m\x1b[38;2;181;52;48m▀\x1b[48;2;147;47;42m\x1b[38;2;183;52;48m▀\x1b[48;2;94;35;30m\x1b[38;2;177;52;48m▀\x1b[48;2;25;19;12m\x1b[38;2;56;27;20m▀\x1b[48;2;10;14;7m\x1b[38;2;8;14;7m▀\x1b[48;2;11;12;8m\x1b[38;2;11;15;8m▀\x1b[48;2;10;23;7m\x1b[38;2;11;14;8m▀\x1b[48;2;7;76;5m\x1b[38;2;11;13;8m▀\x1b[48;2;2;152;1m\x1b[38;2;9;45;6m▀\x1b[48;2;0;177;0m\x1b[38;2;5;106;3m▀\x1b[48;2;0;178;0m\x1b[38;2;4;123;3m▀\x1b[48;2;1;168;1m\x1b[38;2;5;104;3m▀\x1b[48;2;8;53;6m\x1b[38;2;9;47;6m▀\x1b[48;2;11;12;8m\x1b[38;2;11;13;8m▀\x1b[48;2;11;15;8m \x1b[48;2;10;15;8m \x1b[48;2;24;14;7m\x1b[38;2;25;14;7m▀\x1b[48;2;140;2;1m\x1b[38;2;146;2;1m▀\x1b[48;2;219;0;0m\x1b[38;2;225;0;0m▀\x1b[48;2;126;0;0m\x1b[38;2;117;0;0m▀\x1b[m
+\x1b[48;2;34;0;0m\x1b[38;2;167;0;0m▀\x1b[48;2;89;0;0m\x1b[38;2;14;0;0m▀\x1b[48;2;134;1;1m\x1b[38;2;141;1;1m▀\x1b[48;2;31;13;7m\x1b[38;2;32;13;7m▀\x1b[48;2;10;15;8m \x1b[48;2;11;15;8m \x1b[48;2;11;14;7m\x1b[38;2;11;15;8m▀\x1b[48;2;10;14;7m\x1b[38;2;11;14;7m▀\x1b[48;2;53;29;22m\x1b[38;2;10;14;7m▀\x1b[48;2;127;46;41m\x1b[38;2;20;18;11m▀\x1b[48;2;158;51;47m\x1b[38;2;57;28;22m▀\x1b[48;2;166;52;48m\x1b[38;2;113;42;36m▀\x1b[48;2;167;52;48m\x1b[38;2;156;50;46m▀\x1b[48;2;164;52;48m\x1b[38;2;171;52;48m▀\x1b[48;2;146;48;44m\x1b[38;2;172;52;48m▀\x1b[48;2;102;38;33m▀\x1b[48;2;50;26;19m\x1b[38;2;161;51;46m▀\x1b[48;2;17;17;10m\x1b[38;2;126;44;38m▀\x1b[48;2;8;14;7m\x1b[38;2;71;31;25m▀\x1b[48;2;10;14;7m\x1b[38;2;27;19;13m▀\x1b[48;2;11;13;8m\x1b[38;2;10;14;7m▀\x1b[48;2;9;40;6m\x1b[38;2;10;13;7m▀\x1b[48;2;4;119;3m\x1b[38;2;11;20;7m▀\x1b[48;2;1;168;1m\x1b[38;2;8;63;5m▀\x1b[48;2;0;177;0m\x1b[38;2;3;130;2m▀\x1b[48;2;0;175;0m\x1b[38;2;1;171;1m▀\x1b[48;2;1;174;1m\x1b[38;2;0;176;0m▀\x1b[48;2;1;175;1m\x1b[38;2;1;174;1m▀\x1b[48;2;0;177;0m\x1b[38;2;0;176;0m▀\x1b[48;2;3;134;2m\x1b[38;2;2;158;1m▀\x1b[48;2;10;21;7m\x1b[38;2;9;38;6m▀\x1b[48;2;11;14;8m\x1b[38;2;11;13;8m▀\x1b[48;2;11;15;8m \x1b[48;2;10;15;8m \x1b[48;2;23;14;7m \x1b[48;2;127;2;1m\x1b[38;2;133;2;1m▀\x1b[48;2;176;0;0m\x1b[38;2;213;0;0m▀\x1b[48;2;109;0;0m\x1b[38;2;100;0;0m▀\x1b[m
+\x1b[48;2;24;0;0m\x1b[38;2;157;0;0m▀\x1b[48;2;32;0;0m\x1b[38;2;165;0;0m▀\x1b[48;2;121;1;1m\x1b[38;2;128;1;1m▀\x1b[48;2;28;13;7m\x1b[38;2;30;13;7m▀\x1b[48;2;10;15;8m \x1b[48;2;11;15;8m \x1b[48;2;11;14;7m \x1b[48;2;9;15;7m \x1b[48;2;88;41;34m\x1b[38;2;91;41;34m▀\x1b[48;2;145;51;47m\x1b[38;2;163;53;49m▀\x1b[48;2;107;42;36m\x1b[38;2;161;52;48m▀\x1b[48;2;58;29;22m\x1b[38;2;155;51;47m▀\x1b[48;2;21;18;11m\x1b[38;2;128;45;40m▀\x1b[48;2;9;14;7m\x1b[38;2;79;33;27m▀\x1b[38;2;33;21;15m▀\x1b[48;2;11;14;7m\x1b[38;2;12;15;8m▀\x1b[48;2;11;15;8m\x1b[38;2;9;14;7m▀\x1b[38;2;10;14;7m▀ \x1b[48;2;11;12;8m\x1b[38;2;11;14;8m▀\x1b[48;2;8;54;6m\x1b[38;2;10;28;7m▀\x1b[48;2;6;93;4m\x1b[38;2;4;125;3m▀\x1b[48;2;2;152;1m\x1b[38;2;0;175;0m▀\x1b[48;2;0;176;0m▀\x1b[48;2;0;175;0m\x1b[38;2;1;174;1m▀\x1b[48;2;0;177;0m\x1b[38;2;1;175;1m▀\x1b[48;2;0;175;0m▀▀\x1b[48;2;1;162;1m\x1b[38;2;0;176;0m▀\x1b[48;2;9;47;6m\x1b[38;2;6;95;4m▀\x1b[48;2;11;13;8m \x1b[48;2;11;15;8m\x1b[38;2;11;14;8m▀ \x1b[48;2;10;15;8m \x1b[48;2;21;13;7m\x1b[38;2;22;13;7m▀\x1b[48;2;114;2;1m\x1b[38;2;121;2;1m▀\x1b[48;2;164;0;0m\x1b[38;2;170;0;0m▀\x1b[48;2;127;0;0m\x1b[38;2;118;0;0m▀\x1b[m
+\x1b[48;2;14;0;0m\x1b[38;2;147;0;0m▀\x1b[48;2;183;0;0m\x1b[38;2;108;0;0m▀\x1b[48;2;107;1;1m\x1b[38;2;114;1;1m▀\x1b[48;2;26;13;7m\x1b[38;2;27;13;7m▀\x1b[48;2;10;15;8m \x1b[48;2;11;15;8m \x1b[38;2;11;14;7m▀ \x1b[48;2;10;14;7m\x1b[38;2;43;27;20m▀\x1b[48;2;9;14;7m\x1b[38;2;42;25;18m▀\x1b[48;2;11;14;7m\x1b[38;2;14;16;9m▀\x1b[48;2;11;15;8m\x1b[38;2;9;14;7m▀\x1b[38;2;10;14;7m▀\x1b[38;2;11;14;7m▀ \x1b[48;2;11;12;8m \x1b[48;2;9;49;6m\x1b[38;2;8;64;5m▀\x1b[48;2;1;166;1m\x1b[38;2;1;159;1m▀\x1b[48;2;0;175;0m\x1b[38;2;1;171;1m▀ \x1b[48;2;1;159;1m\x1b[38;2;1;167;1m▀\x1b[48;2;7;79;5m\x1b[38;2;4;122;3m▀\x1b[48;2;2;144;2m\x1b[38;2;2;158;1m▀\x1b[48;2;0;158;1m\x1b[38;2;0;177;0m▀\x1b[48;2;7;44;6m\x1b[38;2;4;112;3m▀\x1b[48;2;9;12;7m\x1b[38;2;11;17;7m▀\x1b[48;2;9;14;7m\x1b[38;2;11;14;8m▀\x1b[38;2;11;15;8m▀▀▀▀▀▀▀▀▀▀▀\x1b[48;2;11;14;7m▀\x1b[48;2;11;15;8m \x1b[48;2;10;15;8m \x1b[48;2;20;13;7m\x1b[38;2;21;13;7m▀\x1b[48;2;102;2;1m\x1b[38;2;108;2;1m▀\x1b[48;2;121;0;0m\x1b[38;2;127;0;0m▀\x1b[48;2;146;0;0m\x1b[38;2;136;0;0m▀\x1b[m
+\x1b[48;2;3;0;0m\x1b[38;2;137;0;0m▀\x1b[48;2;173;0;0m\x1b[38;2;50;0;0m▀\x1b[48;2;93;1;1m\x1b[38;2;100;1;1m▀\x1b[48;2;24;13;7m\x1b[38;2;25;13;7m▀\x1b[48;2;10;15;8m \x1b[48;2;11;15;8m \x1b[48;2;11;14;7m\x1b[38;2;11;15;8m▀▀\x1b[48;2;17;14;7m\x1b[38;2;11;14;8m▀\x1b[48;2;49;12;7m\x1b[38;2;9;24;7m▀\x1b[48;2;62;54;4m\x1b[38;2;8;133;2m▀\x1b[48;2;7;159;1m\x1b[38;2;2;176;0m▀\x1b[48;2;0;175;0m \x1b[48;2;1;172;1m\x1b[38;2;0;175;0m▀\x1b[48;2;1;159;1m\x1b[38;2;0;173;1m▀\x1b[48;2;46;122;19m\x1b[38;2;1;176;0m▀\x1b[48;2;122;63;45m\x1b[38;2;45;111;18m▀\x1b[48;2;135;52;49m\x1b[38;2;75;36;31m▀\x1b[48;2;135;53;49m\x1b[38;2;74;36;30m▀▀▀▀▀▀▀▀▀▀▀\x1b[48;2;136;53;49m\x1b[38;2;75;37;31m▀\x1b[48;2;119;49;45m\x1b[38;2;66;34;28m▀\x1b[48;2;25;20;13m\x1b[38;2;18;18;11m▀\x1b[48;2;10;14;7m \x1b[48;2;11;15;8m \x1b[48;2;10;15;8m \x1b[48;2;19;13;7m \x1b[48;2;89;2;1m\x1b[38;2;95;2;1m▀\x1b[48;2;77;0;0m\x1b[38;2;83;0;0m▀\x1b[48;2;128;0;0m\x1b[38;2;119;0;0m▀\x1b[m
+\x1b[48;2;60;0;0m\x1b[38;2;126;0;0m▀\x1b[48;2;182;0;0m\x1b[38;2;249;0;0m▀\x1b[48;2;83;1;1m\x1b[38;2;87;1;1m▀\x1b[48;2;22;13;7m\x1b[38;2;23;13;7m▀\x1b[48;2;10;15;8m \x1b[48;2;11;15;8m \x1b[48;2;11;14;7m\x1b[38;2;16;14;7m▀\x1b[48;2;14;14;7m\x1b[38;2;42;13;7m▀\x1b[48;2;58;13;6m\x1b[38;2;95;11;5m▀\x1b[48;2;34;13;7m\x1b[38;2;100;11;5m▀\x1b[48;2;9;14;7m\x1b[38;2;21;17;7m▀\x1b[48;2;11;12;8m\x1b[38;2;8;55;6m▀\x1b[38;2;7;75;5m▀\x1b[38;2;8;65;5m▀\x1b[48;2;11;13;8m\x1b[38;2;9;41;6m▀\x1b[48;2;12;15;8m\x1b[38;2;60;37;28m▀\x1b[38;2;90;42;37m▀\x1b[38;2;88;42;36m▀▀▀▀▀▀▀▀▀▀▀▀\x1b[38;2;89;42;37m▀\x1b[38;2;78;39;33m▀\x1b[48;2;11;15;8m\x1b[38;2;20;18;11m▀\x1b[48;2;11;14;7m\x1b[38;2;10;14;7m▀\x1b[48;2;11;15;8m \x1b[48;2;10;15;8m \x1b[48;2;18;13;7m \x1b[48;2;78;2;1m\x1b[38;2;83;2;1m▀\x1b[48;2;196;0;0m\x1b[38;2;40;0;0m▀\x1b[48;2;217;0;0m\x1b[38;2;137;0;0m▀\x1b[m
+\x1b[48;2;227;0;0m\x1b[38;2;16;0;0m▀\x1b[48;2;116;0;0m\x1b[38;2;21;0;0m▀\x1b[48;2;79;1;1m\x1b[38;2;81;1;1m▀\x1b[48;2;22;13;7m \x1b[48;2;10;15;8m \x1b[48;2;11;15;8m \x1b[38;2;10;15;8m▀\x1b[48;2;10;15;8m\x1b[38;2;21;14;7m▀\x1b[48;2;11;15;8m\x1b[38;2;14;14;7m▀\x1b[38;2;11;14;7m▀ ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ \x1b[48;2;10;15;8m \x1b[48;2;17;13;7m\x1b[38;2;18;13;7m▀\x1b[48;2;75;2;1m\x1b[38;2;76;2;1m▀\x1b[48;2;97;0;0m\x1b[38;2;34;0;0m▀\x1b[48;2;76;0;0m\x1b[38;2;147;0;0m▀\x1b[m
+\x1b[48;2;161;0;0m\x1b[38;2;183;0;0m▀\x1b[48;2;49;0;0m\x1b[38;2;211;0;0m▀\x1b[48;2;75;1;1m\x1b[38;2;77;1;1m▀\x1b[48;2;21;13;7m \x1b[48;2;10;15;8m \x1b[48;2;11;15;8m \x1b[48;2;10;15;8m \x1b[48;2;17;13;7m \x1b[48;2;71;2;1m\x1b[38;2;73;2;1m▀\x1b[48;2;253;0;0m\x1b[38;2;159;0;0m▀\x1b[48;2;191;0;0m\x1b[38;2;5;0;0m▀\x1b[m
+\x1b[48;2;110;161;100m\x1b[38;2;116;0;0m▀\x1b[48;2;9;205;205m\x1b[38;2;192;0;0m▀\x1b[48;2;78;0;0m\x1b[38;2;77;1;0m▀\x1b[48;2;66;3;1m\x1b[38;2;30;11;6m▀\x1b[48;2;42;8;4m\x1b[38;2;9;15;8m▀\x1b[48;2;39;8;4m\x1b[38;2;10;15;8m▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀\x1b[48;2;40;8;4m▀\x1b[48;2;39;8;4m▀▀▀▀▀▀▀\x1b[48;2;40;8;4m▀▀▀\x1b[48;2;39;8;4m▀\x1b[48;2;40;8;4m▀\x1b[48;2;39;8;4m▀\x1b[48;2;41;8;4m\x1b[38;2;9;15;8m▀\x1b[48;2;62;4;2m\x1b[38;2;24;13;7m▀\x1b[48;2;78;0;0m\x1b[38;2;74;1;1m▀\x1b[48;2;221;222;0m\x1b[38;2;59;0;0m▀\x1b[48;2;67;199;133m\x1b[38;2;85;0;0m▀\x1b[m
+\x1b[48;2;0;0;0m\x1b[38;2;143;233;149m▀\x1b[48;2;108;184;254m\x1b[38;2;213;6;76m▀\x1b[48;2;197;183;82m\x1b[38;2;76;0;0m▀\x1b[48;2;154;157;0m▀\x1b[48;2;96;0;0m▀\x1b[48;2;253;0;0m▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀\x1b[48;2;226;0;0m▀\x1b[48;2;255;127;255m▀\x1b[48;2;84;36;66m\x1b[38;2;64;247;251m▀\x1b[48;2;0;0;0m\x1b[38;2;18;76;210m▀\x1b[m
+\x1b[48;2;0;0;0m \x1b[m
+\x1b[48;2;0;0;0m \x1b[m
+"""
+)
+
+if __name__ == "__main__":
+ main()
diff --git a/examples/full-screen/buttons.py b/examples/full-screen/buttons.py
new file mode 100755
index 0000000..540194d
--- /dev/null
+++ b/examples/full-screen/buttons.py
@@ -0,0 +1,91 @@
+#!/usr/bin/env python
+"""
+A simple example of a few buttons and click handlers.
+"""
+from prompt_toolkit.application import Application
+from prompt_toolkit.application.current import get_app
+from prompt_toolkit.key_binding import KeyBindings
+from prompt_toolkit.key_binding.bindings.focus import focus_next, focus_previous
+from prompt_toolkit.layout import HSplit, Layout, VSplit
+from prompt_toolkit.styles import Style
+from prompt_toolkit.widgets import Box, Button, Frame, Label, TextArea
+
+
+# Event handlers for all the buttons.
+def button1_clicked():
+ text_area.text = "Button 1 clicked"
+
+
+def button2_clicked():
+ text_area.text = "Button 2 clicked"
+
+
+def button3_clicked():
+ text_area.text = "Button 3 clicked"
+
+
+def exit_clicked():
+ get_app().exit()
+
+
+# All the widgets for the UI.
+button1 = Button("Button 1", handler=button1_clicked)
+button2 = Button("Button 2", handler=button2_clicked)
+button3 = Button("Button 3", handler=button3_clicked)
+button4 = Button("Exit", handler=exit_clicked)
+text_area = TextArea(focusable=True)
+
+
+# Combine all the widgets in a UI.
+# The `Box` object ensures that padding will be inserted around the containing
+# widget. It adapts automatically, unless an explicit `padding` amount is given.
+root_container = Box(
+ HSplit(
+ [
+ Label(text="Press `Tab` to move the focus."),
+ VSplit(
+ [
+ Box(
+ body=HSplit([button1, button2, button3, button4], padding=1),
+ padding=1,
+ style="class:left-pane",
+ ),
+ Box(body=Frame(text_area), padding=1, style="class:right-pane"),
+ ]
+ ),
+ ]
+ ),
+)
+
+layout = Layout(container=root_container, focused_element=button1)
+
+
+# Key bindings.
+kb = KeyBindings()
+kb.add("tab")(focus_next)
+kb.add("s-tab")(focus_previous)
+
+
+# Styling.
+style = Style(
+ [
+ ("left-pane", "bg:#888800 #000000"),
+ ("right-pane", "bg:#00aa00 #000000"),
+ ("button", "#000000"),
+ ("button-arrow", "#000000"),
+ ("button focused", "bg:#ff0000"),
+ ("text-area focused", "bg:#ff0000"),
+ ]
+)
+
+
+# Build a main application object.
+application = Application(layout=layout, key_bindings=kb, style=style, full_screen=True)
+
+
+def main():
+ application.run()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/examples/full-screen/calculator.py b/examples/full-screen/calculator.py
new file mode 100755
index 0000000..fda6567
--- /dev/null
+++ b/examples/full-screen/calculator.py
@@ -0,0 +1,98 @@
+#!/usr/bin/env python
+"""
+A simple example of a calculator program.
+This could be used as inspiration for a REPL.
+"""
+from prompt_toolkit.application import Application
+from prompt_toolkit.document import Document
+from prompt_toolkit.filters import has_focus
+from prompt_toolkit.key_binding import KeyBindings
+from prompt_toolkit.layout.containers import HSplit, Window
+from prompt_toolkit.layout.layout import Layout
+from prompt_toolkit.styles import Style
+from prompt_toolkit.widgets import SearchToolbar, TextArea
+
+help_text = """
+Type any expression (e.g. "4 + 4") followed by enter to execute.
+Press Control-C to exit.
+"""
+
+
+def main():
+ # The layout.
+ search_field = SearchToolbar() # For reverse search.
+
+ output_field = TextArea(style="class:output-field", text=help_text)
+ input_field = TextArea(
+ height=1,
+ prompt=">>> ",
+ style="class:input-field",
+ multiline=False,
+ wrap_lines=False,
+ search_field=search_field,
+ )
+
+ container = HSplit(
+ [
+ output_field,
+ Window(height=1, char="-", style="class:line"),
+ input_field,
+ search_field,
+ ]
+ )
+
+ # Attach accept handler to the input field. We do this by assigning the
+ # handler to the `TextArea` that we created earlier. it is also possible to
+ # pass it to the constructor of `TextArea`.
+ # NOTE: It's better to assign an `accept_handler`, rather then adding a
+ # custom ENTER key binding. This will automatically reset the input
+ # field and add the strings to the history.
+ def accept(buff):
+ # Evaluate "calculator" expression.
+ try:
+ output = "\n\nIn: {}\nOut: {}".format(
+ input_field.text, eval(input_field.text)
+ ) # Don't do 'eval' in real code!
+ except BaseException as e:
+ output = f"\n\n{e}"
+ new_text = output_field.text + output
+
+ # Add text to output buffer.
+ output_field.buffer.document = Document(
+ text=new_text, cursor_position=len(new_text)
+ )
+
+ input_field.accept_handler = accept
+
+ # The key bindings.
+ kb = KeyBindings()
+
+ @kb.add("c-c")
+ @kb.add("c-q")
+ def _(event):
+ "Pressing Ctrl-Q or Ctrl-C will exit the user interface."
+ event.app.exit()
+
+ # Style.
+ style = Style(
+ [
+ ("output-field", "bg:#000044 #ffffff"),
+ ("input-field", "bg:#000000 #ffffff"),
+ ("line", "#004400"),
+ ]
+ )
+
+ # Run application.
+ application = Application(
+ layout=Layout(container, focused_element=input_field),
+ key_bindings=kb,
+ style=style,
+ mouse_support=True,
+ full_screen=True,
+ )
+
+ application.run()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/examples/full-screen/dummy-app.py b/examples/full-screen/dummy-app.py
new file mode 100755
index 0000000..7ea7506
--- /dev/null
+++ b/examples/full-screen/dummy-app.py
@@ -0,0 +1,8 @@
+#!/usr/bin/env python
+"""
+This is the most simple example possible.
+"""
+from prompt_toolkit import Application
+
+app = Application(full_screen=False)
+app.run()
diff --git a/examples/full-screen/full-screen-demo.py b/examples/full-screen/full-screen-demo.py
new file mode 100755
index 0000000..de7379a
--- /dev/null
+++ b/examples/full-screen/full-screen-demo.py
@@ -0,0 +1,225 @@
+#!/usr/bin/env python
+"""
+"""
+from pygments.lexers.html import HtmlLexer
+
+from prompt_toolkit.application import Application
+from prompt_toolkit.application.current import get_app
+from prompt_toolkit.completion import WordCompleter
+from prompt_toolkit.key_binding import KeyBindings
+from prompt_toolkit.key_binding.bindings.focus import focus_next, focus_previous
+from prompt_toolkit.layout.containers import Float, HSplit, VSplit
+from prompt_toolkit.layout.dimension import D
+from prompt_toolkit.layout.layout import Layout
+from prompt_toolkit.layout.menus import CompletionsMenu
+from prompt_toolkit.lexers import PygmentsLexer
+from prompt_toolkit.styles import Style
+from prompt_toolkit.widgets import (
+ Box,
+ Button,
+ Checkbox,
+ Dialog,
+ Frame,
+ Label,
+ MenuContainer,
+ MenuItem,
+ ProgressBar,
+ RadioList,
+ TextArea,
+)
+
+
+def accept_yes():
+ get_app().exit(result=True)
+
+
+def accept_no():
+ get_app().exit(result=False)
+
+
+def do_exit():
+ get_app().exit(result=False)
+
+
+yes_button = Button(text="Yes", handler=accept_yes)
+no_button = Button(text="No", handler=accept_no)
+textfield = TextArea(lexer=PygmentsLexer(HtmlLexer))
+checkbox1 = Checkbox(text="Checkbox")
+checkbox2 = Checkbox(text="Checkbox")
+
+radios = RadioList(
+ values=[
+ ("Red", "red"),
+ ("Green", "green"),
+ ("Blue", "blue"),
+ ("Orange", "orange"),
+ ("Yellow", "yellow"),
+ ("Purple", "Purple"),
+ ("Brown", "Brown"),
+ ]
+)
+
+animal_completer = WordCompleter(
+ [
+ "alligator",
+ "ant",
+ "ape",
+ "bat",
+ "bear",
+ "beaver",
+ "bee",
+ "bison",
+ "butterfly",
+ "cat",
+ "chicken",
+ "crocodile",
+ "dinosaur",
+ "dog",
+ "dolphin",
+ "dove",
+ "duck",
+ "eagle",
+ "elephant",
+ "fish",
+ "goat",
+ "gorilla",
+ "kangaroo",
+ "leopard",
+ "lion",
+ "mouse",
+ "rabbit",
+ "rat",
+ "snake",
+ "spider",
+ "turkey",
+ "turtle",
+ ],
+ ignore_case=True,
+)
+
+root_container = HSplit(
+ [
+ VSplit(
+ [
+ Frame(body=Label(text="Left frame\ncontent")),
+ Dialog(title="The custom window", body=Label("hello\ntest")),
+ textfield,
+ ],
+ height=D(),
+ ),
+ VSplit(
+ [
+ Frame(body=ProgressBar(), title="Progress bar"),
+ Frame(
+ title="Checkbox list",
+ body=HSplit([checkbox1, checkbox2]),
+ ),
+ Frame(title="Radio list", body=radios),
+ ],
+ padding=1,
+ ),
+ Box(
+ body=VSplit([yes_button, no_button], align="CENTER", padding=3),
+ style="class:button-bar",
+ height=3,
+ ),
+ ]
+)
+
+root_container = MenuContainer(
+ body=root_container,
+ menu_items=[
+ MenuItem(
+ "File",
+ children=[
+ MenuItem("New"),
+ MenuItem(
+ "Open",
+ children=[
+ MenuItem("From file..."),
+ MenuItem("From URL..."),
+ MenuItem(
+ "Something else..",
+ children=[
+ MenuItem("A"),
+ MenuItem("B"),
+ MenuItem("C"),
+ MenuItem("D"),
+ MenuItem("E"),
+ ],
+ ),
+ ],
+ ),
+ MenuItem("Save"),
+ MenuItem("Save as..."),
+ MenuItem("-", disabled=True),
+ MenuItem("Exit", handler=do_exit),
+ ],
+ ),
+ MenuItem(
+ "Edit",
+ children=[
+ MenuItem("Undo"),
+ MenuItem("Cut"),
+ MenuItem("Copy"),
+ MenuItem("Paste"),
+ MenuItem("Delete"),
+ MenuItem("-", disabled=True),
+ MenuItem("Find"),
+ MenuItem("Find next"),
+ MenuItem("Replace"),
+ MenuItem("Go To"),
+ MenuItem("Select All"),
+ MenuItem("Time/Date"),
+ ],
+ ),
+ MenuItem("View", children=[MenuItem("Status Bar")]),
+ MenuItem("Info", children=[MenuItem("About")]),
+ ],
+ floats=[
+ Float(
+ xcursor=True,
+ ycursor=True,
+ content=CompletionsMenu(max_height=16, scroll_offset=1),
+ ),
+ ],
+)
+
+# Global key bindings.
+bindings = KeyBindings()
+bindings.add("tab")(focus_next)
+bindings.add("s-tab")(focus_previous)
+
+
+style = Style.from_dict(
+ {
+ "window.border": "#888888",
+ "shadow": "bg:#222222",
+ "menu-bar": "bg:#aaaaaa #888888",
+ "menu-bar.selected-item": "bg:#ffffff #000000",
+ "menu": "bg:#888888 #ffffff",
+ "menu.border": "#aaaaaa",
+ "window.border shadow": "#444444",
+ "focused button": "bg:#880000 #ffffff noinherit",
+ # Styling for Dialog widgets.
+ "button-bar": "bg:#aaaaff",
+ }
+)
+
+
+application = Application(
+ layout=Layout(root_container, focused_element=yes_button),
+ key_bindings=bindings,
+ style=style,
+ mouse_support=True,
+ full_screen=True,
+)
+
+
+def run():
+ result = application.run()
+ print("You said: %r" % result)
+
+
+if __name__ == "__main__":
+ run()
diff --git a/examples/full-screen/hello-world.py b/examples/full-screen/hello-world.py
new file mode 100755
index 0000000..b818018
--- /dev/null
+++ b/examples/full-screen/hello-world.py
@@ -0,0 +1,43 @@
+#!/usr/bin/env python
+"""
+A simple example of a a text area displaying "Hello World!".
+"""
+from prompt_toolkit.application import Application
+from prompt_toolkit.key_binding import KeyBindings
+from prompt_toolkit.layout import Layout
+from prompt_toolkit.widgets import Box, Frame, TextArea
+
+# Layout for displaying hello world.
+# (The frame creates the border, the box takes care of the margin/padding.)
+root_container = Box(
+ Frame(
+ TextArea(
+ text="Hello world!\nPress control-c to quit.",
+ width=40,
+ height=10,
+ )
+ ),
+)
+layout = Layout(container=root_container)
+
+
+# Key bindings.
+kb = KeyBindings()
+
+
+@kb.add("c-c")
+def _(event):
+ "Quit when control-c is pressed."
+ event.app.exit()
+
+
+# Build a main application object.
+application = Application(layout=layout, key_bindings=kb, full_screen=True)
+
+
+def main():
+ application.run()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/examples/full-screen/no-layout.py b/examples/full-screen/no-layout.py
new file mode 100644
index 0000000..be5c6f8
--- /dev/null
+++ b/examples/full-screen/no-layout.py
@@ -0,0 +1,7 @@
+#!/usr/bin/env python
+"""
+An empty full screen application without layout.
+"""
+from prompt_toolkit import Application
+
+Application(full_screen=True).run()
diff --git a/examples/full-screen/pager.py b/examples/full-screen/pager.py
new file mode 100755
index 0000000..799c834
--- /dev/null
+++ b/examples/full-screen/pager.py
@@ -0,0 +1,111 @@
+#!/usr/bin/env python
+"""
+A simple application that shows a Pager application.
+"""
+from pygments.lexers.python import PythonLexer
+
+from prompt_toolkit.application import Application
+from prompt_toolkit.key_binding import KeyBindings
+from prompt_toolkit.layout.containers import HSplit, Window
+from prompt_toolkit.layout.controls import FormattedTextControl
+from prompt_toolkit.layout.dimension import LayoutDimension as D
+from prompt_toolkit.layout.layout import Layout
+from prompt_toolkit.lexers import PygmentsLexer
+from prompt_toolkit.styles import Style
+from prompt_toolkit.widgets import SearchToolbar, TextArea
+
+# Create one text buffer for the main content.
+
+_pager_py_path = __file__
+
+
+with open(_pager_py_path, "rb") as f:
+ text = f.read().decode("utf-8")
+
+
+def get_statusbar_text():
+ return [
+ ("class:status", _pager_py_path + " - "),
+ (
+ "class:status.position",
+ "{}:{}".format(
+ text_area.document.cursor_position_row + 1,
+ text_area.document.cursor_position_col + 1,
+ ),
+ ),
+ ("class:status", " - Press "),
+ ("class:status.key", "Ctrl-C"),
+ ("class:status", " to exit, "),
+ ("class:status.key", "/"),
+ ("class:status", " for searching."),
+ ]
+
+
+search_field = SearchToolbar(
+ text_if_not_searching=[("class:not-searching", "Press '/' to start searching.")]
+)
+
+
+text_area = TextArea(
+ text=text,
+ read_only=True,
+ scrollbar=True,
+ line_numbers=True,
+ search_field=search_field,
+ lexer=PygmentsLexer(PythonLexer),
+)
+
+
+root_container = HSplit(
+ [
+ # The top toolbar.
+ Window(
+ content=FormattedTextControl(get_statusbar_text),
+ height=D.exact(1),
+ style="class:status",
+ ),
+ # The main content.
+ text_area,
+ search_field,
+ ]
+)
+
+
+# Key bindings.
+bindings = KeyBindings()
+
+
+@bindings.add("c-c")
+@bindings.add("q")
+def _(event):
+ "Quit."
+ event.app.exit()
+
+
+style = Style.from_dict(
+ {
+ "status": "reverse",
+ "status.position": "#aaaa00",
+ "status.key": "#ffaa00",
+ "not-searching": "#888888",
+ }
+)
+
+
+# create application.
+application = Application(
+ layout=Layout(root_container, focused_element=text_area),
+ key_bindings=bindings,
+ enable_page_navigation_bindings=True,
+ mouse_support=True,
+ style=style,
+ full_screen=True,
+)
+
+
+def run():
+ application.run()
+
+
+if __name__ == "__main__":
+ run()
diff --git a/examples/full-screen/scrollable-panes/simple-example.py b/examples/full-screen/scrollable-panes/simple-example.py
new file mode 100644
index 0000000..4606479
--- /dev/null
+++ b/examples/full-screen/scrollable-panes/simple-example.py
@@ -0,0 +1,45 @@
+#!/usr/bin/env python
+"""
+A simple example of a scrollable pane.
+"""
+from prompt_toolkit.application import Application
+from prompt_toolkit.application.current import get_app
+from prompt_toolkit.key_binding import KeyBindings
+from prompt_toolkit.key_binding.bindings.focus import focus_next, focus_previous
+from prompt_toolkit.layout import Dimension, HSplit, Layout, ScrollablePane
+from prompt_toolkit.widgets import Frame, Label, TextArea
+
+
+def main():
+ # Create a big layout of many text areas, then wrap them in a `ScrollablePane`.
+ root_container = Frame(
+ ScrollablePane(
+ HSplit(
+ [
+ Frame(TextArea(text=f"label-{i}"), width=Dimension())
+ for i in range(20)
+ ]
+ )
+ )
+ # ScrollablePane(HSplit([TextArea(text=f"label-{i}") for i in range(20)]))
+ )
+
+ layout = Layout(container=root_container)
+
+ # Key bindings.
+ kb = KeyBindings()
+
+ @kb.add("c-c")
+ def exit(event) -> None:
+ get_app().exit()
+
+ kb.add("tab")(focus_next)
+ kb.add("s-tab")(focus_previous)
+
+ # Create and run application.
+ application = Application(layout=layout, key_bindings=kb, full_screen=True)
+ application.run()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/examples/full-screen/scrollable-panes/with-completion-menu.py b/examples/full-screen/scrollable-panes/with-completion-menu.py
new file mode 100644
index 0000000..fba8d17
--- /dev/null
+++ b/examples/full-screen/scrollable-panes/with-completion-menu.py
@@ -0,0 +1,120 @@
+#!/usr/bin/env python
+"""
+A simple example of a scrollable pane.
+"""
+from prompt_toolkit.application import Application
+from prompt_toolkit.application.current import get_app
+from prompt_toolkit.completion import WordCompleter
+from prompt_toolkit.key_binding import KeyBindings
+from prompt_toolkit.key_binding.bindings.focus import focus_next, focus_previous
+from prompt_toolkit.layout import (
+ CompletionsMenu,
+ Float,
+ FloatContainer,
+ HSplit,
+ Layout,
+ ScrollablePane,
+ VSplit,
+)
+from prompt_toolkit.widgets import Frame, Label, TextArea
+
+
+def main():
+ # Create a big layout of many text areas, then wrap them in a `ScrollablePane`.
+ root_container = VSplit(
+ [
+ Label("<left column>"),
+ HSplit(
+ [
+ Label("ScrollContainer Demo"),
+ Frame(
+ ScrollablePane(
+ HSplit(
+ [
+ Frame(
+ TextArea(
+ text=f"label-{i}",
+ completer=animal_completer,
+ )
+ )
+ for i in range(20)
+ ]
+ )
+ ),
+ ),
+ ]
+ ),
+ ]
+ )
+
+ root_container = FloatContainer(
+ root_container,
+ floats=[
+ Float(
+ xcursor=True,
+ ycursor=True,
+ content=CompletionsMenu(max_height=16, scroll_offset=1),
+ ),
+ ],
+ )
+
+ layout = Layout(container=root_container)
+
+ # Key bindings.
+ kb = KeyBindings()
+
+ @kb.add("c-c")
+ def exit(event) -> None:
+ get_app().exit()
+
+ kb.add("tab")(focus_next)
+ kb.add("s-tab")(focus_previous)
+
+ # Create and run application.
+ application = Application(
+ layout=layout, key_bindings=kb, full_screen=True, mouse_support=True
+ )
+ application.run()
+
+
+animal_completer = WordCompleter(
+ [
+ "alligator",
+ "ant",
+ "ape",
+ "bat",
+ "bear",
+ "beaver",
+ "bee",
+ "bison",
+ "butterfly",
+ "cat",
+ "chicken",
+ "crocodile",
+ "dinosaur",
+ "dog",
+ "dolphin",
+ "dove",
+ "duck",
+ "eagle",
+ "elephant",
+ "fish",
+ "goat",
+ "gorilla",
+ "kangaroo",
+ "leopard",
+ "lion",
+ "mouse",
+ "rabbit",
+ "rat",
+ "snake",
+ "spider",
+ "turkey",
+ "turtle",
+ ],
+ ignore_case=True,
+)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/examples/full-screen/simple-demos/alignment.py b/examples/full-screen/simple-demos/alignment.py
new file mode 100755
index 0000000..b20b43d
--- /dev/null
+++ b/examples/full-screen/simple-demos/alignment.py
@@ -0,0 +1,60 @@
+#!/usr/bin/env python
+"""
+Demo of the different Window alignment options.
+"""
+from prompt_toolkit.application import Application
+from prompt_toolkit.key_binding import KeyBindings
+from prompt_toolkit.layout.containers import HSplit, Window, WindowAlign
+from prompt_toolkit.layout.controls import FormattedTextControl
+from prompt_toolkit.layout.layout import Layout
+
+LIPSUM = """Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas
+quis interdum enim. Nam viverra, mauris et blandit malesuada, ante est bibendum
+mauris, ac dignissim dui tellus quis ligula. Aenean condimentum leo at
+dignissim placerat. In vel dictum ex, vulputate accumsan mi. Donec ut quam
+placerat massa tempor elementum. Sed tristique mauris ac suscipit euismod. Ut
+tempus vehicula augue non venenatis. Mauris aliquam velit turpis, nec congue
+risus aliquam sit amet. Pellentesque blandit scelerisque felis, faucibus
+consequat ante. Curabitur tempor tortor a imperdiet tincidunt. Nam sed justo
+sit amet odio bibendum congue. Quisque varius ligula nec ligula gravida, sed
+convallis augue faucibus. Nunc ornare pharetra bibendum. Praesent blandit ex
+quis sodales maximus."""
+
+# 1. The layout
+
+left_text = '\nLeft aligned text. - (Press "q" to quit)\n\n' + LIPSUM
+center_text = "Centered text.\n\n" + LIPSUM
+right_text = "Right aligned text.\n\n" + LIPSUM
+
+
+body = HSplit(
+ [
+ Window(FormattedTextControl(left_text), align=WindowAlign.LEFT),
+ Window(height=1, char="-"),
+ Window(FormattedTextControl(center_text), align=WindowAlign.CENTER),
+ Window(height=1, char="-"),
+ Window(FormattedTextControl(right_text), align=WindowAlign.RIGHT),
+ ]
+)
+
+
+# 2. Key bindings
+kb = KeyBindings()
+
+
+@kb.add("q")
+def _(event):
+ "Quit application."
+ event.app.exit()
+
+
+# 3. The `Application`
+application = Application(layout=Layout(body), key_bindings=kb, full_screen=True)
+
+
+def run():
+ application.run()
+
+
+if __name__ == "__main__":
+ run()
diff --git a/examples/full-screen/simple-demos/autocompletion.py b/examples/full-screen/simple-demos/autocompletion.py
new file mode 100755
index 0000000..bcbb594
--- /dev/null
+++ b/examples/full-screen/simple-demos/autocompletion.py
@@ -0,0 +1,100 @@
+#!/usr/bin/env python
+"""
+An example of a BufferControl in a full screen layout that offers auto
+completion.
+
+Important is to make sure that there is a `CompletionsMenu` in the layout,
+otherwise the completions won't be visible.
+"""
+from prompt_toolkit.application import Application
+from prompt_toolkit.buffer import Buffer
+from prompt_toolkit.completion import WordCompleter
+from prompt_toolkit.key_binding import KeyBindings
+from prompt_toolkit.layout.containers import Float, FloatContainer, HSplit, Window
+from prompt_toolkit.layout.controls import BufferControl, FormattedTextControl
+from prompt_toolkit.layout.layout import Layout
+from prompt_toolkit.layout.menus import CompletionsMenu
+
+# The completer.
+animal_completer = WordCompleter(
+ [
+ "alligator",
+ "ant",
+ "ape",
+ "bat",
+ "bear",
+ "beaver",
+ "bee",
+ "bison",
+ "butterfly",
+ "cat",
+ "chicken",
+ "crocodile",
+ "dinosaur",
+ "dog",
+ "dolphin",
+ "dove",
+ "duck",
+ "eagle",
+ "elephant",
+ "fish",
+ "goat",
+ "gorilla",
+ "kangaroo",
+ "leopard",
+ "lion",
+ "mouse",
+ "rabbit",
+ "rat",
+ "snake",
+ "spider",
+ "turkey",
+ "turtle",
+ ],
+ ignore_case=True,
+)
+
+
+# The layout
+buff = Buffer(completer=animal_completer, complete_while_typing=True)
+
+body = FloatContainer(
+ content=HSplit(
+ [
+ Window(
+ FormattedTextControl('Press "q" to quit.'), height=1, style="reverse"
+ ),
+ Window(BufferControl(buffer=buff)),
+ ]
+ ),
+ floats=[
+ Float(
+ xcursor=True,
+ ycursor=True,
+ content=CompletionsMenu(max_height=16, scroll_offset=1),
+ )
+ ],
+)
+
+
+# Key bindings
+kb = KeyBindings()
+
+
+@kb.add("q")
+@kb.add("c-c")
+def _(event):
+ "Quit application."
+ event.app.exit()
+
+
+# The `Application`
+application = Application(layout=Layout(body), key_bindings=kb, full_screen=True)
+
+
+def run():
+ application.run()
+
+
+if __name__ == "__main__":
+ run()
diff --git a/examples/full-screen/simple-demos/colorcolumn.py b/examples/full-screen/simple-demos/colorcolumn.py
new file mode 100755
index 0000000..054aa44
--- /dev/null
+++ b/examples/full-screen/simple-demos/colorcolumn.py
@@ -0,0 +1,63 @@
+#!/usr/bin/env python
+"""
+Colorcolumn example.
+"""
+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 ColorColumn, HSplit, Window
+from prompt_toolkit.layout.controls import BufferControl, FormattedTextControl
+from prompt_toolkit.layout.layout import Layout
+
+LIPSUM = """
+Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas
+quis interdum enim. Nam viverra, mauris et blandit malesuada, ante est bibendum
+mauris, ac dignissim dui tellus quis ligula. Aenean condimentum leo at
+dignissim placerat. In vel dictum ex, vulputate accumsan mi. Donec ut quam
+placerat massa tempor elementum. Sed tristique mauris ac suscipit euismod. Ut
+tempus vehicula augue non venenatis. Mauris aliquam velit turpis, nec congue
+risus aliquam sit amet. Pellentesque blandit scelerisque felis, faucibus
+consequat ante. Curabitur tempor tortor a imperdiet tincidunt. Nam sed justo
+sit amet odio bibendum congue. Quisque varius ligula nec ligula gravida, sed
+convallis augue faucibus. Nunc ornare pharetra bibendum. Praesent blandit ex
+quis sodales maximus."""
+
+# Create text buffers.
+buff = Buffer()
+buff.text = LIPSUM
+
+# 1. The layout
+color_columns = [
+ ColorColumn(50),
+ ColorColumn(80, style="bg:#ff0000"),
+ ColorColumn(10, style="bg:#ff0000"),
+]
+
+body = HSplit(
+ [
+ Window(FormattedTextControl('Press "q" to quit.'), height=1, style="reverse"),
+ Window(BufferControl(buffer=buff), colorcolumns=color_columns),
+ ]
+)
+
+
+# 2. Key bindings
+kb = KeyBindings()
+
+
+@kb.add("q")
+def _(event):
+ "Quit application."
+ event.app.exit()
+
+
+# 3. The `Application`
+application = Application(layout=Layout(body), key_bindings=kb, full_screen=True)
+
+
+def run():
+ application.run()
+
+
+if __name__ == "__main__":
+ run()
diff --git a/examples/full-screen/simple-demos/cursorcolumn-cursorline.py b/examples/full-screen/simple-demos/cursorcolumn-cursorline.py
new file mode 100755
index 0000000..505b3ee
--- /dev/null
+++ b/examples/full-screen/simple-demos/cursorcolumn-cursorline.py
@@ -0,0 +1,59 @@
+#!/usr/bin/env python
+"""
+Cursorcolumn / cursorline example.
+"""
+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, Window
+from prompt_toolkit.layout.controls import BufferControl, FormattedTextControl
+from prompt_toolkit.layout.layout import Layout
+
+LIPSUM = """
+Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas
+quis interdum enim. Nam viverra, mauris et blandit malesuada, ante est bibendum
+mauris, ac dignissim dui tellus quis ligula. Aenean condimentum leo at
+dignissim placerat. In vel dictum ex, vulputate accumsan mi. Donec ut quam
+placerat massa tempor elementum. Sed tristique mauris ac suscipit euismod. Ut
+tempus vehicula augue non venenatis. Mauris aliquam velit turpis, nec congue
+risus aliquam sit amet. Pellentesque blandit scelerisque felis, faucibus
+consequat ante. Curabitur tempor tortor a imperdiet tincidunt. Nam sed justo
+sit amet odio bibendum congue. Quisque varius ligula nec ligula gravida, sed
+convallis augue faucibus. Nunc ornare pharetra bibendum. Praesent blandit ex
+quis sodales maximus."""
+
+# Create text buffers. Cursorcolumn/cursorline are mostly combined with an
+# (editable) text buffers, where the user can move the cursor.
+
+buff = Buffer()
+buff.text = LIPSUM
+
+# 1. The layout
+body = HSplit(
+ [
+ Window(FormattedTextControl('Press "q" to quit.'), height=1, style="reverse"),
+ Window(BufferControl(buffer=buff), cursorcolumn=True, cursorline=True),
+ ]
+)
+
+
+# 2. Key bindings
+kb = KeyBindings()
+
+
+@kb.add("q")
+def _(event):
+ "Quit application."
+ event.app.exit()
+
+
+# 3. The `Application`
+application = Application(layout=Layout(body), key_bindings=kb, full_screen=True)
+
+
+def run():
+ application.run()
+
+
+if __name__ == "__main__":
+ run()
diff --git a/examples/full-screen/simple-demos/float-transparency.py b/examples/full-screen/simple-demos/float-transparency.py
new file mode 100755
index 0000000..4dc38fc
--- /dev/null
+++ b/examples/full-screen/simple-demos/float-transparency.py
@@ -0,0 +1,87 @@
+#!/usr/bin/env python
+"""
+Example of the 'transparency' attribute of `Window' when used in a Float.
+"""
+from prompt_toolkit.application import Application
+from prompt_toolkit.formatted_text import HTML
+from prompt_toolkit.key_binding import KeyBindings
+from prompt_toolkit.layout.containers import Float, FloatContainer, Window
+from prompt_toolkit.layout.controls import FormattedTextControl
+from prompt_toolkit.layout.layout import Layout
+from prompt_toolkit.widgets import Frame
+
+LIPSUM = " ".join(
+ (
+ """Lorem ipsum dolor sit amet, consectetur adipiscing elit.
+Maecenas quis interdum enim. Nam viverra, mauris et blandit malesuada, ante est
+bibendum mauris, ac dignissim dui tellus quis ligula. Aenean condimentum leo at
+dignissim placerat. In vel dictum ex, vulputate accumsan mi. Donec ut quam
+placerat massa tempor elementum. Sed tristique mauris ac suscipit euismod. Ut
+tempus vehicula augue non venenatis. Mauris aliquam velit turpis, nec congue
+risus aliquam sit amet. Pellentesque blandit scelerisque felis, faucibus
+consequat ante. Curabitur tempor tortor a imperdiet tincidunt. Nam sed justo
+sit amet odio bibendum congue. Quisque varius ligula nec ligula gravida, sed
+convallis augue faucibus. Nunc ornare pharetra bibendum. Praesent blandit ex
+quis sodales maximus. """
+ * 100
+ ).split()
+)
+
+
+# 1. The layout
+left_text = HTML("<reverse>transparent=False</reverse>\n")
+right_text = HTML("<reverse>transparent=True</reverse>")
+quit_text = "Press 'q' to quit."
+
+
+body = FloatContainer(
+ content=Window(FormattedTextControl(LIPSUM), wrap_lines=True),
+ floats=[
+ # Important note: Wrapping the floating objects in a 'Frame' is
+ # only required for drawing the border around the
+ # floating text. We do it here to make the layout more
+ # obvious.
+ # Left float.
+ Float(
+ Frame(Window(FormattedTextControl(left_text), width=20, height=4)),
+ transparent=False,
+ left=0,
+ ),
+ # Right float.
+ Float(
+ Frame(Window(FormattedTextControl(right_text), width=20, height=4)),
+ transparent=True,
+ right=0,
+ ),
+ # Quit text.
+ Float(
+ Frame(
+ Window(FormattedTextControl(quit_text), width=18, height=1),
+ style="bg:#ff44ff #ffffff",
+ ),
+ top=1,
+ ),
+ ],
+)
+
+
+# 2. Key bindings
+kb = KeyBindings()
+
+
+@kb.add("q")
+def _(event):
+ "Quit application."
+ event.app.exit()
+
+
+# 3. The `Application`
+application = Application(layout=Layout(body), key_bindings=kb, full_screen=True)
+
+
+def run():
+ application.run()
+
+
+if __name__ == "__main__":
+ run()
diff --git a/examples/full-screen/simple-demos/floats.py b/examples/full-screen/simple-demos/floats.py
new file mode 100755
index 0000000..0d45be9
--- /dev/null
+++ b/examples/full-screen/simple-demos/floats.py
@@ -0,0 +1,116 @@
+#!/usr/bin/env python
+"""
+Horizontal split example.
+"""
+from prompt_toolkit.application import Application
+from prompt_toolkit.key_binding import KeyBindings
+from prompt_toolkit.layout.containers import Float, FloatContainer, Window
+from prompt_toolkit.layout.controls import FormattedTextControl
+from prompt_toolkit.layout.layout import Layout
+from prompt_toolkit.widgets import Frame
+
+LIPSUM = " ".join(
+ (
+ """Lorem ipsum dolor sit amet, consectetur adipiscing elit.
+Maecenas quis interdum enim. Nam viverra, mauris et blandit malesuada, ante est
+bibendum mauris, ac dignissim dui tellus quis ligula. Aenean condimentum leo at
+dignissim placerat. In vel dictum ex, vulputate accumsan mi. Donec ut quam
+placerat massa tempor elementum. Sed tristique mauris ac suscipit euismod. Ut
+tempus vehicula augue non venenatis. Mauris aliquam velit turpis, nec congue
+risus aliquam sit amet. Pellentesque blandit scelerisque felis, faucibus
+consequat ante. Curabitur tempor tortor a imperdiet tincidunt. Nam sed justo
+sit amet odio bibendum congue. Quisque varius ligula nec ligula gravida, sed
+convallis augue faucibus. Nunc ornare pharetra bibendum. Praesent blandit ex
+quis sodales maximus. """
+ * 100
+ ).split()
+)
+
+
+# 1. The layout
+left_text = "Floating\nleft"
+right_text = "Floating\nright"
+top_text = "Floating\ntop"
+bottom_text = "Floating\nbottom"
+center_text = "Floating\ncenter"
+quit_text = "Press 'q' to quit."
+
+
+body = FloatContainer(
+ content=Window(FormattedTextControl(LIPSUM), wrap_lines=True),
+ floats=[
+ # Important note: Wrapping the floating objects in a 'Frame' is
+ # only required for drawing the border around the
+ # floating text. We do it here to make the layout more
+ # obvious.
+ # Left float.
+ Float(
+ Frame(
+ Window(FormattedTextControl(left_text), width=10, height=2),
+ style="bg:#44ffff #ffffff",
+ ),
+ left=0,
+ ),
+ # Right float.
+ Float(
+ Frame(
+ Window(FormattedTextControl(right_text), width=10, height=2),
+ style="bg:#44ffff #ffffff",
+ ),
+ right=0,
+ ),
+ # Bottom float.
+ Float(
+ Frame(
+ Window(FormattedTextControl(bottom_text), width=10, height=2),
+ style="bg:#44ffff #ffffff",
+ ),
+ bottom=0,
+ ),
+ # Top float.
+ Float(
+ Frame(
+ Window(FormattedTextControl(top_text), width=10, height=2),
+ style="bg:#44ffff #ffffff",
+ ),
+ top=0,
+ ),
+ # Center float.
+ Float(
+ Frame(
+ Window(FormattedTextControl(center_text), width=10, height=2),
+ style="bg:#44ffff #ffffff",
+ )
+ ),
+ # Quit text.
+ Float(
+ Frame(
+ Window(FormattedTextControl(quit_text), width=18, height=1),
+ style="bg:#ff44ff #ffffff",
+ ),
+ top=6,
+ ),
+ ],
+)
+
+
+# 2. Key bindings
+kb = KeyBindings()
+
+
+@kb.add("q")
+def _(event):
+ "Quit application."
+ event.app.exit()
+
+
+# 3. The `Application`
+application = Application(layout=Layout(body), key_bindings=kb, full_screen=True)
+
+
+def run():
+ application.run()
+
+
+if __name__ == "__main__":
+ run()
diff --git a/examples/full-screen/simple-demos/focus.py b/examples/full-screen/simple-demos/focus.py
new file mode 100755
index 0000000..9fe9b8f
--- /dev/null
+++ b/examples/full-screen/simple-demos/focus.py
@@ -0,0 +1,98 @@
+#!/usr/bin/env python
+"""
+Demonstration of how to programmatically focus a certain widget.
+"""
+from prompt_toolkit.application import Application
+from prompt_toolkit.buffer import Buffer
+from prompt_toolkit.document import Document
+from prompt_toolkit.key_binding import KeyBindings
+from prompt_toolkit.layout.containers import HSplit, VSplit, Window
+from prompt_toolkit.layout.controls import BufferControl, FormattedTextControl
+from prompt_toolkit.layout.layout import Layout
+
+# 1. The layout
+top_text = (
+ "Focus example.\n"
+ "[q] Quit [a] Focus left top [b] Right top [c] Left bottom [d] Right bottom."
+)
+
+LIPSUM = """Lorem ipsum dolor sit amet, consectetur adipiscing elit.
+Maecenas quis interdum enim. Nam viverra, mauris et blandit malesuada, ante est
+bibendum mauris, ac dignissim dui tellus quis ligula. Aenean condimentum leo at
+dignissim placerat. In vel dictum ex, vulputate accumsan mi. Donec ut quam
+placerat massa tempor elementum. Sed tristique mauris ac suscipit euismod. Ut
+tempus vehicula augue non venenatis. Mauris aliquam velit turpis, nec congue
+risus aliquam sit amet. Pellentesque blandit scelerisque felis, faucibus
+consequat ante. Curabitur tempor tortor a imperdiet tincidunt. Nam sed justo
+sit amet odio bibendum congue. Quisque varius ligula nec ligula gravida, sed
+convallis augue faucibus. Nunc ornare pharetra bibendum. Praesent blandit ex
+quis sodales maximus. """
+
+
+left_top = Window(BufferControl(Buffer(document=Document(LIPSUM))))
+left_bottom = Window(BufferControl(Buffer(document=Document(LIPSUM))))
+right_top = Window(BufferControl(Buffer(document=Document(LIPSUM))))
+right_bottom = Window(BufferControl(Buffer(document=Document(LIPSUM))))
+
+
+body = HSplit(
+ [
+ Window(FormattedTextControl(top_text), height=2, style="reverse"),
+ Window(height=1, char="-"), # Horizontal line in the middle.
+ VSplit([left_top, Window(width=1, char="|"), right_top]),
+ Window(height=1, char="-"), # Horizontal line in the middle.
+ VSplit([left_bottom, Window(width=1, char="|"), right_bottom]),
+ ]
+)
+
+
+# 2. Key bindings
+kb = KeyBindings()
+
+
+@kb.add("q")
+def _(event):
+ "Quit application."
+ event.app.exit()
+
+
+@kb.add("a")
+def _(event):
+ event.app.layout.focus(left_top)
+
+
+@kb.add("b")
+def _(event):
+ event.app.layout.focus(right_top)
+
+
+@kb.add("c")
+def _(event):
+ event.app.layout.focus(left_bottom)
+
+
+@kb.add("d")
+def _(event):
+ event.app.layout.focus(right_bottom)
+
+
+@kb.add("tab")
+def _(event):
+ event.app.layout.focus_next()
+
+
+@kb.add("s-tab")
+def _(event):
+ event.app.layout.focus_previous()
+
+
+# 3. The `Application`
+application = Application(layout=Layout(body), key_bindings=kb, full_screen=True)
+
+
+def run():
+ application.run()
+
+
+if __name__ == "__main__":
+ run()
diff --git a/examples/full-screen/simple-demos/horizontal-align.py b/examples/full-screen/simple-demos/horizontal-align.py
new file mode 100755
index 0000000..f50b9e8
--- /dev/null
+++ b/examples/full-screen/simple-demos/horizontal-align.py
@@ -0,0 +1,209 @@
+#!/usr/bin/env python
+"""
+Horizontal align demo with HSplit.
+"""
+from prompt_toolkit.application import Application
+from prompt_toolkit.formatted_text import HTML
+from prompt_toolkit.key_binding import KeyBindings
+from prompt_toolkit.layout.containers import (
+ HorizontalAlign,
+ HSplit,
+ VerticalAlign,
+ VSplit,
+ Window,
+ WindowAlign,
+)
+from prompt_toolkit.layout.controls import FormattedTextControl
+from prompt_toolkit.layout.dimension import D
+from prompt_toolkit.layout.layout import Layout
+from prompt_toolkit.widgets import Frame
+
+TITLE = HTML(
+ """ <u>HSplit HorizontalAlign</u> example.
+ Press <b>'q'</b> to quit."""
+)
+
+LIPSUM = """\
+Lorem ipsum dolor
+sit amet, consectetur
+adipiscing elit.
+Maecenas quis
+interdum enim."""
+
+
+# 1. The layout
+body = HSplit(
+ [
+ Frame(
+ Window(FormattedTextControl(TITLE), height=2), style="bg:#88ff88 #000000"
+ ),
+ HSplit(
+ [
+ # Left alignment.
+ VSplit(
+ [
+ Window(
+ FormattedTextControl(HTML("<u>LEFT</u>")),
+ width=10,
+ ignore_content_width=True,
+ style="bg:#ff3333 ansiblack",
+ align=WindowAlign.CENTER,
+ ),
+ VSplit(
+ [
+ Window(
+ FormattedTextControl(LIPSUM),
+ height=4,
+ style="bg:#444488",
+ ),
+ Window(
+ FormattedTextControl(LIPSUM),
+ height=4,
+ style="bg:#444488",
+ ),
+ Window(
+ FormattedTextControl(LIPSUM),
+ height=4,
+ style="bg:#444488",
+ ),
+ ],
+ padding=1,
+ padding_style="bg:#888888",
+ align=HorizontalAlign.LEFT,
+ height=5,
+ padding_char="|",
+ ),
+ ]
+ ),
+ # Center alignment.
+ VSplit(
+ [
+ Window(
+ FormattedTextControl(HTML("<u>CENTER</u>")),
+ width=10,
+ ignore_content_width=True,
+ style="bg:#ff3333 ansiblack",
+ align=WindowAlign.CENTER,
+ ),
+ VSplit(
+ [
+ Window(
+ FormattedTextControl(LIPSUM),
+ height=4,
+ style="bg:#444488",
+ ),
+ Window(
+ FormattedTextControl(LIPSUM),
+ height=4,
+ style="bg:#444488",
+ ),
+ Window(
+ FormattedTextControl(LIPSUM),
+ height=4,
+ style="bg:#444488",
+ ),
+ ],
+ padding=1,
+ padding_style="bg:#888888",
+ align=HorizontalAlign.CENTER,
+ height=5,
+ padding_char="|",
+ ),
+ ]
+ ),
+ # Right alignment.
+ VSplit(
+ [
+ Window(
+ FormattedTextControl(HTML("<u>RIGHT</u>")),
+ width=10,
+ ignore_content_width=True,
+ style="bg:#ff3333 ansiblack",
+ align=WindowAlign.CENTER,
+ ),
+ VSplit(
+ [
+ Window(
+ FormattedTextControl(LIPSUM),
+ height=4,
+ style="bg:#444488",
+ ),
+ Window(
+ FormattedTextControl(LIPSUM),
+ height=4,
+ style="bg:#444488",
+ ),
+ Window(
+ FormattedTextControl(LIPSUM),
+ height=4,
+ style="bg:#444488",
+ ),
+ ],
+ padding=1,
+ padding_style="bg:#888888",
+ align=HorizontalAlign.RIGHT,
+ height=5,
+ padding_char="|",
+ ),
+ ]
+ ),
+ # Justify
+ VSplit(
+ [
+ Window(
+ FormattedTextControl(HTML("<u>JUSTIFY</u>")),
+ width=10,
+ ignore_content_width=True,
+ style="bg:#ff3333 ansiblack",
+ align=WindowAlign.CENTER,
+ ),
+ VSplit(
+ [
+ Window(
+ FormattedTextControl(LIPSUM), style="bg:#444488"
+ ),
+ Window(
+ FormattedTextControl(LIPSUM), style="bg:#444488"
+ ),
+ Window(
+ FormattedTextControl(LIPSUM), style="bg:#444488"
+ ),
+ ],
+ padding=1,
+ padding_style="bg:#888888",
+ align=HorizontalAlign.JUSTIFY,
+ height=5,
+ padding_char="|",
+ ),
+ ]
+ ),
+ ],
+ padding=1,
+ padding_style="bg:#ff3333 #ffffff",
+ padding_char=".",
+ align=VerticalAlign.TOP,
+ ),
+ ]
+)
+
+
+# 2. Key bindings
+kb = KeyBindings()
+
+
+@kb.add("q")
+def _(event):
+ "Quit application."
+ event.app.exit()
+
+
+# 3. The `Application`
+application = Application(layout=Layout(body), key_bindings=kb, full_screen=True)
+
+
+def run():
+ application.run()
+
+
+if __name__ == "__main__":
+ run()
diff --git a/examples/full-screen/simple-demos/horizontal-split.py b/examples/full-screen/simple-demos/horizontal-split.py
new file mode 100755
index 0000000..0427e67
--- /dev/null
+++ b/examples/full-screen/simple-demos/horizontal-split.py
@@ -0,0 +1,44 @@
+#!/usr/bin/env python
+"""
+Horizontal split example.
+"""
+from prompt_toolkit.application import Application
+from prompt_toolkit.key_binding import KeyBindings
+from prompt_toolkit.layout.containers import HSplit, Window
+from prompt_toolkit.layout.controls import FormattedTextControl
+from prompt_toolkit.layout.layout import Layout
+
+# 1. The layout
+left_text = "\nVertical-split example. Press 'q' to quit.\n\n(top pane.)"
+right_text = "\n(bottom pane.)"
+
+
+body = HSplit(
+ [
+ Window(FormattedTextControl(left_text)),
+ Window(height=1, char="-"), # Horizontal line in the middle.
+ Window(FormattedTextControl(right_text)),
+ ]
+)
+
+
+# 2. Key bindings
+kb = KeyBindings()
+
+
+@kb.add("q")
+def _(event):
+ "Quit application."
+ event.app.exit()
+
+
+# 3. The `Application`
+application = Application(layout=Layout(body), key_bindings=kb, full_screen=True)
+
+
+def run():
+ application.run()
+
+
+if __name__ == "__main__":
+ run()
diff --git a/examples/full-screen/simple-demos/line-prefixes.py b/examples/full-screen/simple-demos/line-prefixes.py
new file mode 100755
index 0000000..ab47ef6
--- /dev/null
+++ b/examples/full-screen/simple-demos/line-prefixes.py
@@ -0,0 +1,111 @@
+#!/usr/bin/env python
+"""
+An example of a BufferControl in a full screen layout that offers auto
+completion.
+
+Important is to make sure that there is a `CompletionsMenu` in the layout,
+otherwise the completions won't be visible.
+"""
+from prompt_toolkit.application import Application
+from prompt_toolkit.buffer import Buffer
+from prompt_toolkit.completion import WordCompleter
+from prompt_toolkit.filters import Condition
+from prompt_toolkit.formatted_text import HTML
+from prompt_toolkit.key_binding import KeyBindings
+from prompt_toolkit.layout.containers import Float, FloatContainer, HSplit, Window
+from prompt_toolkit.layout.controls import BufferControl, FormattedTextControl
+from prompt_toolkit.layout.layout import Layout
+from prompt_toolkit.layout.menus import CompletionsMenu
+
+LIPSUM = """
+Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas
+quis interdum enim. Nam viverra, mauris et blandit malesuada, ante est bibendum
+mauris, ac dignissim dui tellus quis ligula. Aenean condimentum leo at
+dignissim placerat. In vel dictum ex, vulputate accumsan mi. Donec ut quam
+placerat massa tempor elementum. Sed tristique mauris ac suscipit euismod. Ut
+tempus vehicula augue non venenatis. Mauris aliquam velit turpis, nec congue
+risus aliquam sit amet. Pellentesque blandit scelerisque felis, faucibus
+consequat ante. Curabitur tempor tortor a imperdiet tincidunt. Nam sed justo
+sit amet odio bibendum congue. Quisque varius ligula nec ligula gravida, sed
+convallis augue faucibus. Nunc ornare pharetra bibendum. Praesent blandit ex
+quis sodales maximus."""
+
+
+def get_line_prefix(lineno, wrap_count):
+ if wrap_count == 0:
+ return HTML('[%s] <style bg="orange" fg="black">--&gt;</style> ') % lineno
+
+ text = str(lineno) + "-" + "*" * (lineno // 2) + ": "
+ return HTML('[%s.%s] <style bg="ansigreen" fg="ansiblack">%s</style>') % (
+ lineno,
+ wrap_count,
+ text,
+ )
+
+
+# Global wrap lines flag.
+wrap_lines = True
+
+
+# The layout
+buff = Buffer(complete_while_typing=True)
+buff.text = LIPSUM
+
+
+body = FloatContainer(
+ content=HSplit(
+ [
+ Window(
+ FormattedTextControl(
+ 'Press "q" to quit. Press "w" to enable/disable wrapping.'
+ ),
+ height=1,
+ style="reverse",
+ ),
+ Window(
+ BufferControl(buffer=buff),
+ get_line_prefix=get_line_prefix,
+ wrap_lines=Condition(lambda: wrap_lines),
+ ),
+ ]
+ ),
+ floats=[
+ Float(
+ xcursor=True,
+ ycursor=True,
+ content=CompletionsMenu(max_height=16, scroll_offset=1),
+ )
+ ],
+)
+
+
+# Key bindings
+kb = KeyBindings()
+
+
+@kb.add("q")
+@kb.add("c-c")
+def _(event):
+ "Quit application."
+ event.app.exit()
+
+
+@kb.add("w")
+def _(event):
+ "Disable/enable wrapping."
+ global wrap_lines
+ wrap_lines = not wrap_lines
+
+
+# The `Application`
+application = Application(
+ layout=Layout(body), key_bindings=kb, full_screen=True, mouse_support=True
+)
+
+
+def run():
+ application.run()
+
+
+if __name__ == "__main__":
+ run()
diff --git a/examples/full-screen/simple-demos/margins.py b/examples/full-screen/simple-demos/margins.py
new file mode 100755
index 0000000..467492d
--- /dev/null
+++ b/examples/full-screen/simple-demos/margins.py
@@ -0,0 +1,71 @@
+#!/usr/bin/env python
+"""
+Example of Window margins.
+
+This is mainly used for displaying line numbers and scroll bars, but it could
+be used to display any other kind of information as well.
+"""
+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, Window
+from prompt_toolkit.layout.controls import BufferControl, FormattedTextControl
+from prompt_toolkit.layout.layout import Layout
+from prompt_toolkit.layout.margins import NumberedMargin, ScrollbarMargin
+
+LIPSUM = (
+ """
+Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas
+quis interdum enim. Nam viverra, mauris et blandit malesuada, ante est bibendum
+mauris, ac dignissim dui tellus quis ligula. Aenean condimentum leo at
+dignissim placerat. In vel dictum ex, vulputate accumsan mi. Donec ut quam
+placerat massa tempor elementum. Sed tristique mauris ac suscipit euismod. Ut
+tempus vehicula augue non venenatis. Mauris aliquam velit turpis, nec congue
+risus aliquam sit amet. Pellentesque blandit scelerisque felis, faucibus
+consequat ante. Curabitur tempor tortor a imperdiet tincidunt. Nam sed justo
+sit amet odio bibendum congue. Quisque varius ligula nec ligula gravida, sed
+convallis augue faucibus. Nunc ornare pharetra bibendum. Praesent blandit ex
+quis sodales maximus."""
+ * 40
+)
+
+# Create text buffers. The margins will update if you scroll up or down.
+
+buff = Buffer()
+buff.text = LIPSUM
+
+# 1. The layout
+body = HSplit(
+ [
+ Window(FormattedTextControl('Press "q" to quit.'), height=1, style="reverse"),
+ Window(
+ BufferControl(buffer=buff),
+ # Add margins.
+ left_margins=[NumberedMargin(), ScrollbarMargin()],
+ right_margins=[ScrollbarMargin(), ScrollbarMargin()],
+ ),
+ ]
+)
+
+
+# 2. Key bindings
+kb = KeyBindings()
+
+
+@kb.add("q")
+@kb.add("c-c")
+def _(event):
+ "Quit application."
+ event.app.exit()
+
+
+# 3. The `Application`
+application = Application(layout=Layout(body), key_bindings=kb, full_screen=True)
+
+
+def run():
+ application.run()
+
+
+if __name__ == "__main__":
+ run()
diff --git a/examples/full-screen/simple-demos/vertical-align.py b/examples/full-screen/simple-demos/vertical-align.py
new file mode 100755
index 0000000..824695e
--- /dev/null
+++ b/examples/full-screen/simple-demos/vertical-align.py
@@ -0,0 +1,168 @@
+#!/usr/bin/env python
+"""
+Vertical align demo with VSplit.
+"""
+from prompt_toolkit.application import Application
+from prompt_toolkit.formatted_text import HTML
+from prompt_toolkit.key_binding import KeyBindings
+from prompt_toolkit.layout.containers import (
+ HSplit,
+ VerticalAlign,
+ VSplit,
+ Window,
+ WindowAlign,
+)
+from prompt_toolkit.layout.controls import FormattedTextControl
+from prompt_toolkit.layout.dimension import D
+from prompt_toolkit.layout.layout import Layout
+from prompt_toolkit.widgets import Frame
+
+TITLE = HTML(
+ """ <u>VSplit VerticalAlign</u> example.
+ Press <b>'q'</b> to quit."""
+)
+
+LIPSUM = """
+Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas
+quis interdum enim. Nam viverra, mauris et blandit malesuada, ante est bibendum
+mauris, ac dignissim dui tellus quis ligula. Aenean condimentum leo at
+dignissim placerat."""
+
+# 1. The layout
+body = HSplit(
+ [
+ Frame(
+ Window(FormattedTextControl(TITLE), height=2), style="bg:#88ff88 #000000"
+ ),
+ VSplit(
+ [
+ Window(
+ FormattedTextControl(HTML(" <u>VerticalAlign.TOP</u>")),
+ height=4,
+ ignore_content_width=True,
+ style="bg:#ff3333 #000000 bold",
+ align=WindowAlign.CENTER,
+ ),
+ Window(
+ FormattedTextControl(HTML(" <u>VerticalAlign.CENTER</u>")),
+ height=4,
+ ignore_content_width=True,
+ style="bg:#ff3333 #000000 bold",
+ align=WindowAlign.CENTER,
+ ),
+ Window(
+ FormattedTextControl(HTML(" <u>VerticalAlign.BOTTOM</u>")),
+ height=4,
+ ignore_content_width=True,
+ style="bg:#ff3333 #000000 bold",
+ align=WindowAlign.CENTER,
+ ),
+ Window(
+ FormattedTextControl(HTML(" <u>VerticalAlign.JUSTIFY</u>")),
+ height=4,
+ ignore_content_width=True,
+ style="bg:#ff3333 #000000 bold",
+ align=WindowAlign.CENTER,
+ ),
+ ],
+ height=1,
+ padding=1,
+ padding_style="bg:#ff3333",
+ ),
+ VSplit(
+ [
+ # Top alignment.
+ HSplit(
+ [
+ Window(
+ FormattedTextControl(LIPSUM), height=4, style="bg:#444488"
+ ),
+ Window(
+ FormattedTextControl(LIPSUM), height=4, style="bg:#444488"
+ ),
+ Window(
+ FormattedTextControl(LIPSUM), height=4, style="bg:#444488"
+ ),
+ ],
+ padding=1,
+ padding_style="bg:#888888",
+ align=VerticalAlign.TOP,
+ padding_char="~",
+ ),
+ # Center alignment.
+ HSplit(
+ [
+ Window(
+ FormattedTextControl(LIPSUM), height=4, style="bg:#444488"
+ ),
+ Window(
+ FormattedTextControl(LIPSUM), height=4, style="bg:#444488"
+ ),
+ Window(
+ FormattedTextControl(LIPSUM), height=4, style="bg:#444488"
+ ),
+ ],
+ padding=1,
+ padding_style="bg:#888888",
+ align=VerticalAlign.CENTER,
+ padding_char="~",
+ ),
+ # Bottom alignment.
+ HSplit(
+ [
+ Window(
+ FormattedTextControl(LIPSUM), height=4, style="bg:#444488"
+ ),
+ Window(
+ FormattedTextControl(LIPSUM), height=4, style="bg:#444488"
+ ),
+ Window(
+ FormattedTextControl(LIPSUM), height=4, style="bg:#444488"
+ ),
+ ],
+ padding=1,
+ padding_style="bg:#888888",
+ align=VerticalAlign.BOTTOM,
+ padding_char="~",
+ ),
+ # Justify
+ HSplit(
+ [
+ Window(FormattedTextControl(LIPSUM), style="bg:#444488"),
+ Window(FormattedTextControl(LIPSUM), style="bg:#444488"),
+ Window(FormattedTextControl(LIPSUM), style="bg:#444488"),
+ ],
+ padding=1,
+ padding_style="bg:#888888",
+ align=VerticalAlign.JUSTIFY,
+ padding_char="~",
+ ),
+ ],
+ padding=1,
+ padding_style="bg:#ff3333 #ffffff",
+ padding_char=".",
+ ),
+ ]
+)
+
+
+# 2. Key bindings
+kb = KeyBindings()
+
+
+@kb.add("q")
+def _(event):
+ "Quit application."
+ event.app.exit()
+
+
+# 3. The `Application`
+application = Application(layout=Layout(body), key_bindings=kb, full_screen=True)
+
+
+def run():
+ application.run()
+
+
+if __name__ == "__main__":
+ run()
diff --git a/examples/full-screen/simple-demos/vertical-split.py b/examples/full-screen/simple-demos/vertical-split.py
new file mode 100755
index 0000000..b48d106
--- /dev/null
+++ b/examples/full-screen/simple-demos/vertical-split.py
@@ -0,0 +1,44 @@
+#!/usr/bin/env python
+"""
+Vertical split example.
+"""
+from prompt_toolkit.application import Application
+from prompt_toolkit.key_binding import KeyBindings
+from prompt_toolkit.layout.containers import VSplit, Window
+from prompt_toolkit.layout.controls import FormattedTextControl
+from prompt_toolkit.layout.layout import Layout
+
+# 1. The layout
+left_text = "\nVertical-split example. Press 'q' to quit.\n\n(left pane.)"
+right_text = "\n(right pane.)"
+
+
+body = VSplit(
+ [
+ Window(FormattedTextControl(left_text)),
+ Window(width=1, char="|"), # Vertical line in the middle.
+ Window(FormattedTextControl(right_text)),
+ ]
+)
+
+
+# 2. Key bindings
+kb = KeyBindings()
+
+
+@kb.add("q")
+def _(event):
+ "Quit application."
+ event.app.exit()
+
+
+# 3. The `Application`
+application = Application(layout=Layout(body), key_bindings=kb, full_screen=True)
+
+
+def run():
+ application.run()
+
+
+if __name__ == "__main__":
+ run()
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()
diff --git a/examples/full-screen/text-editor.py b/examples/full-screen/text-editor.py
new file mode 100755
index 0000000..9c0a414
--- /dev/null
+++ b/examples/full-screen/text-editor.py
@@ -0,0 +1,383 @@
+#!/usr/bin/env python
+"""
+A simple example of a Notepad-like text editor.
+"""
+import datetime
+from asyncio import Future, ensure_future
+
+from prompt_toolkit.application import Application
+from prompt_toolkit.application.current import get_app
+from prompt_toolkit.completion import PathCompleter
+from prompt_toolkit.filters import Condition
+from prompt_toolkit.key_binding import KeyBindings
+from prompt_toolkit.layout.containers import (
+ ConditionalContainer,
+ Float,
+ HSplit,
+ VSplit,
+ Window,
+ WindowAlign,
+)
+from prompt_toolkit.layout.controls import FormattedTextControl
+from prompt_toolkit.layout.dimension import D
+from prompt_toolkit.layout.layout import Layout
+from prompt_toolkit.layout.menus import CompletionsMenu
+from prompt_toolkit.lexers import DynamicLexer, PygmentsLexer
+from prompt_toolkit.search import start_search
+from prompt_toolkit.styles import Style
+from prompt_toolkit.widgets import (
+ Button,
+ Dialog,
+ Label,
+ MenuContainer,
+ MenuItem,
+ SearchToolbar,
+ TextArea,
+)
+
+
+class ApplicationState:
+ """
+ Application state.
+
+ For the simplicity, we store this as a global, but better would be to
+ instantiate this as an object and pass at around.
+ """
+
+ show_status_bar = True
+ current_path = None
+
+
+def get_statusbar_text():
+ return " Press Ctrl-C to open menu. "
+
+
+def get_statusbar_right_text():
+ return " {}:{} ".format(
+ text_field.document.cursor_position_row + 1,
+ text_field.document.cursor_position_col + 1,
+ )
+
+
+search_toolbar = SearchToolbar()
+text_field = TextArea(
+ lexer=DynamicLexer(
+ lambda: PygmentsLexer.from_filename(
+ ApplicationState.current_path or ".txt", sync_from_start=False
+ )
+ ),
+ scrollbar=True,
+ line_numbers=True,
+ search_field=search_toolbar,
+)
+
+
+class TextInputDialog:
+ def __init__(self, title="", label_text="", completer=None):
+ self.future = Future()
+
+ def accept_text(buf):
+ get_app().layout.focus(ok_button)
+ buf.complete_state = None
+ return True
+
+ def accept():
+ self.future.set_result(self.text_area.text)
+
+ def cancel():
+ self.future.set_result(None)
+
+ self.text_area = TextArea(
+ completer=completer,
+ multiline=False,
+ width=D(preferred=40),
+ accept_handler=accept_text,
+ )
+
+ ok_button = Button(text="OK", handler=accept)
+ cancel_button = Button(text="Cancel", handler=cancel)
+
+ self.dialog = Dialog(
+ title=title,
+ body=HSplit([Label(text=label_text), self.text_area]),
+ buttons=[ok_button, cancel_button],
+ width=D(preferred=80),
+ modal=True,
+ )
+
+ def __pt_container__(self):
+ return self.dialog
+
+
+class MessageDialog:
+ def __init__(self, title, text):
+ self.future = Future()
+
+ def set_done():
+ self.future.set_result(None)
+
+ ok_button = Button(text="OK", handler=(lambda: set_done()))
+
+ self.dialog = Dialog(
+ title=title,
+ body=HSplit([Label(text=text)]),
+ buttons=[ok_button],
+ width=D(preferred=80),
+ modal=True,
+ )
+
+ def __pt_container__(self):
+ return self.dialog
+
+
+body = HSplit(
+ [
+ text_field,
+ search_toolbar,
+ ConditionalContainer(
+ content=VSplit(
+ [
+ Window(
+ FormattedTextControl(get_statusbar_text), style="class:status"
+ ),
+ Window(
+ FormattedTextControl(get_statusbar_right_text),
+ style="class:status.right",
+ width=9,
+ align=WindowAlign.RIGHT,
+ ),
+ ],
+ height=1,
+ ),
+ filter=Condition(lambda: ApplicationState.show_status_bar),
+ ),
+ ]
+)
+
+
+# Global key bindings.
+bindings = KeyBindings()
+
+
+@bindings.add("c-c")
+def _(event):
+ "Focus menu."
+ event.app.layout.focus(root_container.window)
+
+
+#
+# Handlers for menu items.
+#
+
+
+def do_open_file():
+ async def coroutine():
+ open_dialog = TextInputDialog(
+ title="Open file",
+ label_text="Enter the path of a file:",
+ completer=PathCompleter(),
+ )
+
+ path = await show_dialog_as_float(open_dialog)
+ ApplicationState.current_path = path
+
+ if path is not None:
+ try:
+ with open(path, "rb") as f:
+ text_field.text = f.read().decode("utf-8", errors="ignore")
+ except OSError as e:
+ show_message("Error", f"{e}")
+
+ ensure_future(coroutine())
+
+
+def do_about():
+ show_message("About", "Text editor demo.\nCreated by Jonathan Slenders.")
+
+
+def show_message(title, text):
+ async def coroutine():
+ dialog = MessageDialog(title, text)
+ await show_dialog_as_float(dialog)
+
+ ensure_future(coroutine())
+
+
+async def show_dialog_as_float(dialog):
+ "Coroutine."
+ float_ = Float(content=dialog)
+ root_container.floats.insert(0, float_)
+
+ app = get_app()
+
+ focused_before = app.layout.current_window
+ app.layout.focus(dialog)
+ result = await dialog.future
+ app.layout.focus(focused_before)
+
+ if float_ in root_container.floats:
+ root_container.floats.remove(float_)
+
+ return result
+
+
+def do_new_file():
+ text_field.text = ""
+
+
+def do_exit():
+ get_app().exit()
+
+
+def do_time_date():
+ text = datetime.datetime.now().isoformat()
+ text_field.buffer.insert_text(text)
+
+
+def do_go_to():
+ async def coroutine():
+ dialog = TextInputDialog(title="Go to line", label_text="Line number:")
+
+ line_number = await show_dialog_as_float(dialog)
+
+ try:
+ line_number = int(line_number)
+ except ValueError:
+ show_message("Invalid line number")
+ else:
+ text_field.buffer.cursor_position = (
+ text_field.buffer.document.translate_row_col_to_index(
+ line_number - 1, 0
+ )
+ )
+
+ ensure_future(coroutine())
+
+
+def do_undo():
+ text_field.buffer.undo()
+
+
+def do_cut():
+ data = text_field.buffer.cut_selection()
+ get_app().clipboard.set_data(data)
+
+
+def do_copy():
+ data = text_field.buffer.copy_selection()
+ get_app().clipboard.set_data(data)
+
+
+def do_delete():
+ text_field.buffer.cut_selection()
+
+
+def do_find():
+ start_search(text_field.control)
+
+
+def do_find_next():
+ search_state = get_app().current_search_state
+
+ cursor_position = text_field.buffer.get_search_position(
+ search_state, include_current_position=False
+ )
+ text_field.buffer.cursor_position = cursor_position
+
+
+def do_paste():
+ text_field.buffer.paste_clipboard_data(get_app().clipboard.get_data())
+
+
+def do_select_all():
+ text_field.buffer.cursor_position = 0
+ text_field.buffer.start_selection()
+ text_field.buffer.cursor_position = len(text_field.buffer.text)
+
+
+def do_status_bar():
+ ApplicationState.show_status_bar = not ApplicationState.show_status_bar
+
+
+#
+# The menu container.
+#
+
+
+root_container = MenuContainer(
+ body=body,
+ menu_items=[
+ MenuItem(
+ "File",
+ children=[
+ MenuItem("New...", handler=do_new_file),
+ MenuItem("Open...", handler=do_open_file),
+ MenuItem("Save"),
+ MenuItem("Save as..."),
+ MenuItem("-", disabled=True),
+ MenuItem("Exit", handler=do_exit),
+ ],
+ ),
+ MenuItem(
+ "Edit",
+ children=[
+ MenuItem("Undo", handler=do_undo),
+ MenuItem("Cut", handler=do_cut),
+ MenuItem("Copy", handler=do_copy),
+ MenuItem("Paste", handler=do_paste),
+ MenuItem("Delete", handler=do_delete),
+ MenuItem("-", disabled=True),
+ MenuItem("Find", handler=do_find),
+ MenuItem("Find next", handler=do_find_next),
+ MenuItem("Replace"),
+ MenuItem("Go To", handler=do_go_to),
+ MenuItem("Select All", handler=do_select_all),
+ MenuItem("Time/Date", handler=do_time_date),
+ ],
+ ),
+ MenuItem(
+ "View",
+ children=[MenuItem("Status Bar", handler=do_status_bar)],
+ ),
+ MenuItem(
+ "Info",
+ children=[MenuItem("About", handler=do_about)],
+ ),
+ ],
+ floats=[
+ Float(
+ xcursor=True,
+ ycursor=True,
+ content=CompletionsMenu(max_height=16, scroll_offset=1),
+ ),
+ ],
+ key_bindings=bindings,
+)
+
+
+style = Style.from_dict(
+ {
+ "status": "reverse",
+ "shadow": "bg:#440044",
+ }
+)
+
+
+layout = Layout(root_container, focused_element=text_field)
+
+
+application = Application(
+ layout=layout,
+ enable_page_navigation_bindings=True,
+ style=style,
+ mouse_support=True,
+ full_screen=True,
+)
+
+
+def run():
+ application.run()
+
+
+if __name__ == "__main__":
+ run()